1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
https://git.kernel.org/pub/scm/network/connman/connman.git/patch/?id=72343929836de80727a27d6744c869dff045757c
From 72343929836de80727a27d6744c869dff045757c Mon Sep 17 00:00:00 2001
From: Daniel Wagner <wagi@monom.org>
Date: Tue, 5 Jul 2022 08:32:12 +0200
Subject: wispr: Add reference counter to portal context
Track the connman_wispr_portal_context live time via a
refcounter. This only adds the infrastructure to do proper reference
counting.
Fixes: CVE-2022-32293
---
src/wispr.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 42 insertions(+), 10 deletions(-)
diff --git a/src/wispr.c b/src/wispr.c
index a07896ca..bde7e63b 100644
--- a/src/wispr.c
+++ b/src/wispr.c
@@ -56,6 +56,7 @@ struct wispr_route {
};
struct connman_wispr_portal_context {
+ int refcount;
struct connman_service *service;
enum connman_ipconfig_type type;
struct connman_wispr_portal *wispr_portal;
@@ -97,6 +98,11 @@ static char *online_check_ipv4_url = NULL;
static char *online_check_ipv6_url = NULL;
static bool enable_online_to_ready_transition = false;
+#define wispr_portal_context_ref(wp_context) \
+ wispr_portal_context_ref_debug(wp_context, __FILE__, __LINE__, __func__)
+#define wispr_portal_context_unref(wp_context) \
+ wispr_portal_context_unref_debug(wp_context, __FILE__, __LINE__, __func__)
+
static void connman_wispr_message_init(struct connman_wispr_message *msg)
{
DBG("");
@@ -162,9 +168,6 @@ static void free_connman_wispr_portal_context(
{
DBG("context %p", wp_context);
- if (!wp_context)
- return;
-
if (wp_context->wispr_portal) {
if (wp_context->wispr_portal->ipv4_context == wp_context)
wp_context->wispr_portal->ipv4_context = NULL;
@@ -201,9 +204,38 @@ static void free_connman_wispr_portal_context(
g_free(wp_context);
}
+static struct connman_wispr_portal_context *
+wispr_portal_context_ref_debug(struct connman_wispr_portal_context *wp_context,
+ const char *file, int line, const char *caller)
+{
+ DBG("%p ref %d by %s:%d:%s()", wp_context,
+ wp_context->refcount + 1, file, line, caller);
+
+ __sync_fetch_and_add(&wp_context->refcount, 1);
+
+ return wp_context;
+}
+
+static void wispr_portal_context_unref_debug(
+ struct connman_wispr_portal_context *wp_context,
+ const char *file, int line, const char *caller)
+{
+ if (!wp_context)
+ return;
+
+ DBG("%p ref %d by %s:%d:%s()", wp_context,
+ wp_context->refcount - 1, file, line, caller);
+
+ if (__sync_fetch_and_sub(&wp_context->refcount, 1) != 1)
+ return;
+
+ free_connman_wispr_portal_context(wp_context);
+}
+
static struct connman_wispr_portal_context *create_wispr_portal_context(void)
{
- return g_try_new0(struct connman_wispr_portal_context, 1);
+ return wispr_portal_context_ref(
+ g_new0(struct connman_wispr_portal_context, 1));
}
static void free_connman_wispr_portal(gpointer data)
@@ -215,8 +247,8 @@ static void free_connman_wispr_portal(gpointer data)
if (!wispr_portal)
return;
- free_connman_wispr_portal_context(wispr_portal->ipv4_context);
- free_connman_wispr_portal_context(wispr_portal->ipv6_context);
+ wispr_portal_context_unref(wispr_portal->ipv4_context);
+ wispr_portal_context_unref(wispr_portal->ipv6_context);
g_free(wispr_portal);
}
@@ -452,7 +484,7 @@ static void portal_manage_status(GWebResult *result,
connman_info("Client-Timezone: %s", str);
if (!enable_online_to_ready_transition)
- free_connman_wispr_portal_context(wp_context);
+ wispr_portal_context_unref(wp_context);
__connman_service_ipconfig_indicate_state(service,
CONNMAN_SERVICE_STATE_ONLINE, type);
@@ -616,7 +648,7 @@ static void wispr_portal_request_wispr_login(struct connman_service *service,
return;
}
- free_connman_wispr_portal_context(wp_context);
+ wispr_portal_context_unref(wp_context);
return;
}
@@ -952,7 +984,7 @@ static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context)
if (wp_context->token == 0) {
err = -EINVAL;
- free_connman_wispr_portal_context(wp_context);
+ wispr_portal_context_unref(wp_context);
}
} else if (wp_context->timeout == 0) {
wp_context->timeout = g_idle_add(no_proxy_callback, wp_context);
@@ -1001,7 +1033,7 @@ int __connman_wispr_start(struct connman_service *service,
/* If there is already an existing context, we wipe it */
if (wp_context)
- free_connman_wispr_portal_context(wp_context);
+ wispr_portal_context_unref(wp_context);
wp_context = create_wispr_portal_context();
if (!wp_context)
--
cgit
|