From 2c5c93d1f681db3bdda00aa9e260f28bfb1f75db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:20:07 +0000 Subject: [PATCH 1/7] Initial plan From cbd5e2f1e8dd7681eb16532d176d4f189130cf3d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:21:47 +0000 Subject: [PATCH 2/7] Fix module_control0 double-free with mutex serialization Co-authored-by: Admirepowered <43035036+Admirepowered@users.noreply.github.com> --- kernel/patch/module/module.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/patch/module/module.c b/kernel/patch/module/module.c index aac23bdf..bb9e8560 100644 --- a/kernel/patch/module/module.c +++ b/kernel/patch/module/module.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -448,6 +449,7 @@ static int elf_header_check(struct load_info *info) struct module modules = { 0 }; static spinlock_t module_lock; +static DEFINE_MUTEX(module_ctl_lock); long load_module(const void *data, int len, const char *args, const char *event, void *__user reserved) { @@ -520,7 +522,6 @@ long load_module(const void *data, int len, const char *args, const char *event, return rc; } -// todo: lock long unload_module(const char *name, void *__user reserved) { if (!name) return -EINVAL; @@ -537,8 +538,10 @@ long unload_module(const char *name, void *__user reserved) list_del(&mod->list); rc = (*mod->exit)(reserved); + mutex_lock(&module_ctl_lock); if (mod->args) kvfree(mod->args); if (mod->ctl_args) kvfree(mod->ctl_args); + mutex_unlock(&module_ctl_lock); kp_free_exec(mod->start); kvfree(mod); @@ -623,10 +626,13 @@ long module_control0(const char *name, const char *ctl_args, char *__user out_ms goto out; } + mutex_lock(&module_ctl_lock); + if (mod->ctl_args) kvfree(mod->ctl_args); mod->ctl_args = vmalloc(args_len + 1); if (!mod->ctl_args) { + mutex_unlock(&module_ctl_lock); rc = -ENOMEM; goto out; } @@ -635,6 +641,8 @@ long module_control0(const char *name, const char *ctl_args, char *__user out_ms rc = (*mod->ctl0)(mod->ctl_args, out_msg, outlen); + mutex_unlock(&module_ctl_lock); + logkfi("name: %s, rc: %d\n", name, rc); out: rcu_read_unlock(); From 4e8da37e83c7faddc4605c744a9c6345a771bcff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:23:07 +0000 Subject: [PATCH 3/7] Widen module_ctl_lock to cover find_module in unload/control0 Co-authored-by: Admirepowered <43035036+Admirepowered@users.noreply.github.com> --- kernel/patch/module/module.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/kernel/patch/module/module.c b/kernel/patch/module/module.c index bb9e8560..609f937f 100644 --- a/kernel/patch/module/module.c +++ b/kernel/patch/module/module.c @@ -530,18 +530,19 @@ long unload_module(const char *name, void *__user reserved) rcu_read_lock(); long rc = 0; + mutex_lock(&module_ctl_lock); + struct module *mod = find_module(name); if (!mod) { rc = -ENOENT; goto out; } + list_del(&mod->list); rc = (*mod->exit)(reserved); - mutex_lock(&module_ctl_lock); if (mod->args) kvfree(mod->args); if (mod->ctl_args) kvfree(mod->ctl_args); - mutex_unlock(&module_ctl_lock); kp_free_exec(mod->start); kvfree(mod); @@ -549,6 +550,7 @@ long unload_module(const char *name, void *__user reserved) logkfi("name: %s, rc: %d\n", name, rc); out: + mutex_unlock(&module_ctl_lock); rcu_read_unlock(); return rc; } @@ -612,6 +614,7 @@ long module_control0(const char *name, const char *ctl_args, char *__user out_ms logkfi("name %s, args: %s\n", name, ctl_args); long rc = 0; + mutex_lock(&module_ctl_lock); rcu_read_lock(); struct module *mod = find_module(name); @@ -626,13 +629,10 @@ long module_control0(const char *name, const char *ctl_args, char *__user out_ms goto out; } - mutex_lock(&module_ctl_lock); - if (mod->ctl_args) kvfree(mod->ctl_args); mod->ctl_args = vmalloc(args_len + 1); if (!mod->ctl_args) { - mutex_unlock(&module_ctl_lock); rc = -ENOMEM; goto out; } @@ -641,11 +641,10 @@ long module_control0(const char *name, const char *ctl_args, char *__user out_ms rc = (*mod->ctl0)(mod->ctl_args, out_msg, outlen); - mutex_unlock(&module_ctl_lock); - logkfi("name: %s, rc: %d\n", name, rc); out: rcu_read_unlock(); + mutex_unlock(&module_ctl_lock); return rc; } From db992305a6d463ebb5d4badecbcd9b1b5089494c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:23:38 +0000 Subject: [PATCH 4/7] Fix lock ordering: mutex before rcu_read_lock in unload_module Co-authored-by: Admirepowered <43035036+Admirepowered@users.noreply.github.com> --- kernel/patch/module/module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/patch/module/module.c b/kernel/patch/module/module.c index 609f937f..73da325d 100644 --- a/kernel/patch/module/module.c +++ b/kernel/patch/module/module.c @@ -527,10 +527,10 @@ long unload_module(const char *name, void *__user reserved) if (!name) return -EINVAL; logkfe("name: %s\n", name); - rcu_read_lock(); long rc = 0; mutex_lock(&module_ctl_lock); + rcu_read_lock(); struct module *mod = find_module(name); if (!mod) { @@ -550,8 +550,8 @@ long unload_module(const char *name, void *__user reserved) logkfi("name: %s, rc: %d\n", name, rc); out: - mutex_unlock(&module_ctl_lock); rcu_read_unlock(); + mutex_unlock(&module_ctl_lock); return rc; } From 226c1a0b81fd4e3c32ced78d7dda79572f44eec6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:24:36 +0000 Subject: [PATCH 5/7] Remove redundant rcu_read_lock now fully covered by module_ctl_lock mutex Co-authored-by: Admirepowered <43035036+Admirepowered@users.noreply.github.com> --- kernel/patch/module/module.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel/patch/module/module.c b/kernel/patch/module/module.c index 73da325d..990b5313 100644 --- a/kernel/patch/module/module.c +++ b/kernel/patch/module/module.c @@ -530,7 +530,6 @@ long unload_module(const char *name, void *__user reserved) long rc = 0; mutex_lock(&module_ctl_lock); - rcu_read_lock(); struct module *mod = find_module(name); if (!mod) { @@ -550,7 +549,6 @@ long unload_module(const char *name, void *__user reserved) logkfi("name: %s, rc: %d\n", name, rc); out: - rcu_read_unlock(); mutex_unlock(&module_ctl_lock); return rc; } @@ -615,7 +613,6 @@ long module_control0(const char *name, const char *ctl_args, char *__user out_ms long rc = 0; mutex_lock(&module_ctl_lock); - rcu_read_lock(); struct module *mod = find_module(name); if (!mod) { @@ -643,7 +640,6 @@ long module_control0(const char *name, const char *ctl_args, char *__user out_ms logkfi("name: %s, rc: %d\n", name, rc); out: - rcu_read_unlock(); mutex_unlock(&module_ctl_lock); return rc; } From e1e976bb7ef1c7de2870bba9b6ea155a4084a855 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:25:58 +0000 Subject: [PATCH 6/7] Also serialize load_module list mutation with module_ctl_lock Co-authored-by: Admirepowered <43035036+Admirepowered@users.noreply.github.com> --- kernel/patch/module/module.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel/patch/module/module.c b/kernel/patch/module/module.c index 990b5313..5f2b2215 100644 --- a/kernel/patch/module/module.c +++ b/kernel/patch/module/module.c @@ -460,18 +460,20 @@ long load_module(const void *data, int len, const char *args, const char *event, if ((rc = elf_header_check(info))) goto out; if ((rc = setup_load_info(info))) goto out; + mutex_lock(&module_ctl_lock); + if (find_module(info->info.name)) { logkfd("%s exist\n", info->info.name); set_load_error(info, "module already exists"); rc = -EEXIST; - goto out; + goto unlock; } struct module *mod = (struct module *)vmalloc(sizeof(struct module)); if (!mod) { set_load_error(info, "allocate module state failed"); rc = -ENOMEM; - goto out; + goto unlock; } memset(mod, 0, sizeof(struct module)); @@ -505,7 +507,7 @@ long load_module(const void *data, int len, const char *args, const char *event, if (!rc) { logkfi("[%s] succeed with [%s] \n", mod->info.name, args); list_add_tail(&mod->list, &modules.list); - goto out; + goto unlock; } else { set_load_error(info, "module init failed"); logkfi("[%s] failed with [%s] error: %d, try exit ...\n", mod->info.name, args, rc); @@ -517,6 +519,8 @@ long load_module(const void *data, int len, const char *args, const char *event, kp_free_exec(mod->start); free1: kvfree(mod); +unlock: + mutex_unlock(&module_ctl_lock); out: set_kpm_load_result(reserved, rc, rc ? load_error(info, "load module failed") : "module loaded"); return rc; From 9a9fb45459487519ac300075880786a3e0a32ce4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:26:57 +0000 Subject: [PATCH 7/7] Remove unused module_lock spinlock to avoid confusion with module_ctl_lock Co-authored-by: Admirepowered <43035036+Admirepowered@users.noreply.github.com> --- kernel/patch/module/module.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/patch/module/module.c b/kernel/patch/module/module.c index 5f2b2215..35ef772a 100644 --- a/kernel/patch/module/module.c +++ b/kernel/patch/module/module.c @@ -448,7 +448,6 @@ static int elf_header_check(struct load_info *info) } struct module modules = { 0 }; -static spinlock_t module_lock; static DEFINE_MUTEX(module_ctl_lock); long load_module(const void *data, int len, const char *args, const char *event, void *__user reserved) @@ -773,5 +772,4 @@ int get_module_info(const char *name, char *out_info, int size) void module_init() { INIT_LIST_HEAD(&modules.list); - spin_lock_init(&module_lock); }