]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
ucode-mod-uline: fix crash on cleanup
authorFelix Fietkau <nbd@nbd.name>
Wed, 30 Apr 2025 08:40:38 +0000 (10:40 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 30 Apr 2025 09:04:14 +0000 (11:04 +0200)
- only run a single poll in the uloop_fd cb to avoid use-after-free on close
- delete the uloop_fd on close
- when calling into ucode, fetch the vm pointer before the call in order
  to avoid accessing the stale uline context

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/utils/ucode-mod-uline/src/ucode.c

index 353d6bba548c04da0d17afbdacff512772b74748..7d7753a6d858853620be98138790d5571fa84af6 100644 (file)
@@ -306,15 +306,16 @@ cb_prepare(struct uc_uline_state *us, const char *name)
 static uc_value_t *
 cb_call_ret(struct uc_uline_state *us, size_t args, ...)
 {
+       uc_vm_t *vm = us->vm;
        va_list ap;
 
        va_start(ap, args);
        for (size_t i = 0; i < args; i++)
-               uc_vm_stack_push(us->vm, ucv_get(va_arg(ap, void *)));
+               uc_vm_stack_push(vm, ucv_get(va_arg(ap, void *)));
        va_end(ap);
 
-       if (uc_vm_call(us->vm, true, args) == EXCEPTION_NONE)
-               return uc_vm_stack_pop(us->vm);
+       if (uc_vm_call(vm, true, args) == EXCEPTION_NONE)
+               return uc_vm_stack_pop(vm);
 
        return NULL;
 }
@@ -369,21 +370,19 @@ static void uc_uline_poll_cb(struct uloop_fd *fd, unsigned int events)
        struct uc_uline_state *us = container_of(fd, struct uc_uline_state, fd);
        uc_value_t *val;
 
-       while (!uloop_cancelled && us->poll_cb) {
-               uline_poll(&us->s);
+       uline_poll(&us->s);
 
-               val = us->line;
-               if (!val)
-                       break;
+       val = us->line;
+       if (!val)
+               return;
 
-               us->line = NULL;
-               if (!ucv_is_callable(us->poll_cb))
-                       return;
+       us->line = NULL;
+       if (!ucv_is_callable(us->poll_cb))
+               return;
 
-               uc_vm_stack_push(us->vm, ucv_get(us->res));
-               uc_vm_stack_push(us->vm, ucv_get(us->poll_cb));
-               cb_call(us, 1, val);
-       }
+       uc_vm_stack_push(us->vm, ucv_get(us->res));
+       uc_vm_stack_push(us->vm, ucv_get(us->poll_cb));
+       cb_call(us, 1, val);
 }
 
 static bool
@@ -543,6 +542,7 @@ static void free_state(void *ptr)
        if (!us)
                return;
 
+       uloop_fd_delete(&us->fd);
        registry = uc_vm_registry_get(us->vm, "uline.registry");
        ucv_array_set(registry, us->registry_index, NULL);
        uline_free(&us->s);