service: fix double-free in error path
[project/procd.git] / service / service.c
index 3ec24c3..bfc8d49 100644 (file)
@@ -117,10 +117,9 @@ service_update(struct service *s, struct blob_attr *config, struct blob_attr **t
        service_validate_del(s);
 
        if (tb[SERVICE_SET_TRIGGER] && blobmsg_data_len(tb[SERVICE_SET_TRIGGER])) {
-               s->trigger = malloc(blob_pad_len(tb[SERVICE_SET_TRIGGER]));
+               s->trigger = blob_memdup(tb[SERVICE_SET_TRIGGER]);
                if (!s->trigger)
                        return -1;
-               memcpy(s->trigger, tb[SERVICE_SET_TRIGGER], blob_pad_len(tb[SERVICE_SET_TRIGGER]));
                trigger_add(s->trigger, s);
        }
 
@@ -217,13 +216,13 @@ service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
        struct blob_attr *tb[__SERVICE_SET_MAX], *cur;
        struct service *s = NULL;
        const char *name;
-       int ret = UBUS_STATUS_INVALID_ARGUMENT;
        bool add = !strcmp(method, "add");
+       int ret;
 
        blobmsg_parse(service_set_attrs, __SERVICE_SET_MAX, tb, blob_data(msg), blob_len(msg));
        cur = tb[SERVICE_ATTR_NAME];
        if (!cur)
-               goto free;
+               return UBUS_STATUS_INVALID_ARGUMENT;
 
        name = blobmsg_data(cur);
 
@@ -240,15 +239,11 @@ service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
 
        ret = service_update(s, msg, tb, add);
        if (ret)
-               goto free;
+               return ret;
 
        avl_insert(&services, &s->avl);
 
        return 0;
-
-free:
-       free(msg);
-       return ret;
 }
 
 static void
@@ -259,15 +254,12 @@ service_dump(struct service *s, int verbose)
 
        c = blobmsg_open_table(&b, s->name);
 
-       if (avl_is_empty(&s->instances.avl)) {
-               blobmsg_close_table(&b, c);
-               return;
+       if (!avl_is_empty(&s->instances.avl)) {
+               i = blobmsg_open_table(&b, "instances");
+               vlist_for_each_element(&s->instances, in, node)
+                       instance_dump(&b, in, verbose);
+               blobmsg_close_table(&b, i);
        }
-
-       i = blobmsg_open_table(&b, "instances");
-       vlist_for_each_element(&s->instances, in, node)
-               instance_dump(&b, in, verbose);
-       blobmsg_close_table(&b, i);
        if (verbose && s->trigger)
                blobmsg_add_blob(&b, s->trigger);
        if (verbose && !list_empty(&s->validators))