summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau2025-04-30 08:40:38 +0000
committerFelix Fietkau2025-04-30 09:04:14 +0000
commitd07c48fa091d09f3bf5247799e08ef722b932f3c (patch)
tree19d087ea0234663095adabd8d96f0ac80e4b4599
parentb9685dcf3de53294017b99952dc7eb6245938422 (diff)
downloadopenwrt-d07c48fa091d09f3bf5247799e08ef722b932f3c.tar.gz
ucode-mod-uline: fix crash on cleanup
- 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>
-rw-r--r--package/utils/ucode-mod-uline/src/ucode.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/package/utils/ucode-mod-uline/src/ucode.c b/package/utils/ucode-mod-uline/src/ucode.c
index 353d6bba54..7d7753a6d8 100644
--- a/package/utils/ucode-mod-uline/src/ucode.c
+++ b/package/utils/ucode-mod-uline/src/ucode.c
@@ -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);