summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Štetiar <ynezz@true.cz>2019-12-19 11:10:46 +0100
committerPetr Štetiar <ynezz@true.cz>2019-12-19 19:53:25 +0100
commitdac6c7c575ac2f8f04706a137e703deffbf88aa7 (patch)
tree5c707f76e029239aa3e153be5977d8983da364fd
parent060dfbb26da320ed8e897dd522278e7437ee8fe9 (diff)
downloadubus-dac6c7c575ac2f8f04706a137e703deffbf88aa7.tar.gz
ubusd_monitor: fix possible null pointer dereference
This dereference could possibly happen if the calloc call fails as the return value is unchecked. While at it refactor the code little bit to make it easier to follow, use safe list iterator and provide return value for ubusd_monitor_connect. Signed-off-by: Petr Štetiar <ynezz@true.cz>
-rw-r--r--ubusd_monitor.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/ubusd_monitor.c b/ubusd_monitor.c
index fcbc6a4..501e06d 100644
--- a/ubusd_monitor.c
+++ b/ubusd_monitor.c
@@ -29,7 +29,7 @@ ubusd_monitor_free(struct ubus_monitor *m)
free(m);
}
-static void
+static bool
ubusd_monitor_connect(struct ubus_client *cl, struct ubus_msg_buf *ub)
{
struct ubus_monitor *m;
@@ -37,22 +37,40 @@ ubusd_monitor_connect(struct ubus_client *cl, struct ubus_msg_buf *ub)
ubusd_monitor_disconnect(cl);
m = calloc(1, sizeof(*m));
+ if (!m)
+ return false;
+
m->cl = cl;
list_add(&m->list, &monitors);
+
+ return true;
}
-void
-ubusd_monitor_disconnect(struct ubus_client *cl)
+static struct ubus_monitor*
+ubusd_monitor_find(struct ubus_client *cl)
{
- struct ubus_monitor *m;
+ struct ubus_monitor *m, *tmp;
- list_for_each_entry(m, &monitors, list) {
+ list_for_each_entry_safe(m, tmp, &monitors, list) {
if (m->cl != cl)
continue;
- ubusd_monitor_free(m);
- return;
+ return m;
}
+
+ return NULL;
+}
+
+void
+ubusd_monitor_disconnect(struct ubus_client *cl)
+{
+ struct ubus_monitor *m;
+
+ m = ubusd_monitor_find(cl);
+ if (!m)
+ return;
+
+ ubusd_monitor_free(m);
}
void
@@ -92,13 +110,15 @@ ubusd_monitor_recv(struct ubus_client *cl, struct ubus_msg_buf *ub,
return UBUS_STATUS_PERMISSION_DENIED;
if (!strcmp(method, "add")) {
- ubusd_monitor_connect(cl, ub);
- return 0;
+ if (!ubusd_monitor_connect(cl, ub))
+ return UBUS_STATUS_UNKNOWN_ERROR;
+
+ return UBUS_STATUS_OK;
}
if (!strcmp(method, "remove")) {
ubusd_monitor_disconnect(cl);
- return 0;
+ return UBUS_STATUS_OK;
}
return UBUS_STATUS_METHOD_NOT_FOUND;