[openwrt/openwrt] ucode-mod-uline: fix crash on cleanup

LEDE Commits lede-commits at lists.infradead.org
Wed Apr 30 02:04:29 PDT 2025


nbd pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/d07c48fa091d09f3bf5247799e08ef722b932f3c

commit d07c48fa091d09f3bf5247799e08ef722b932f3c
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Wed Apr 30 10:40:38 2025 +0200

    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 at nbd.name>
---
 package/utils/ucode-mod-uline/src/ucode.c | 30 +++++++++++++++---------------
 1 file 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);




More information about the lede-commits mailing list