lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250918201109.24620-6-julian.lagattuta@gmail.com>
Date: Thu, 18 Sep 2025 16:11:08 -0400
From: julian-lagattuta <julian.lagattuta@...il.com>
To: Luis Chamberlain <mcgrof@...nel.org>,
	Petr Pavlu <petr.pavlu@...e.com>
Cc: Sami Tolvanen <samitolvanen@...gle.com>,
	Daniel Gomez <da.gomez@...sung.com>,
	linux-modules@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	julian-lagattuta <julian.lagattuta@...il.com>
Subject: [PATCH 2/6] module: detect if init crashed and unload

Store idempotent and init_pid in struct module.

Signed-off-by: julian-lagattuta <julian.lagattuta@...il.com>
---
 kernel/module/main.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/kernel/module/main.c b/kernel/module/main.c
index 413ac6ea3702..2277c53aef2e 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -752,6 +752,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 	char name[MODULE_NAME_LEN];
 	char buf[MODULE_FLAGS_BUF_SIZE];
 	int ret, forced = 0;
+	bool did_init_crash __maybe_unused = false;
 
 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
 		return -EPERM;
@@ -778,8 +779,11 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 	}
 
 	/* Doing init or already dying? */
-	if (mod->state != MODULE_STATE_LIVE) {
-		/* FIXME: if (force), slam module count damn the torpedoes */
+	if (mod->state == MODULE_STATE_GOING ||
+		(mod->state != MODULE_STATE_LIVE &&
+		!IS_ENABLED(CONFIG_MODULE_FORCE_UNLOAD))
+	) {
+		if (mod->state == MODULE_STATE_GOING)
 		pr_debug("%s already dying\n", mod->name);
 		ret = -EBUSY;
 		goto out;
@@ -795,6 +799,21 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 		}
 	}
 
+#ifdef CONFIG_MODULE_FORCE_UNLOAD
+	if (mod->state == MODULE_STATE_COMING) {
+		struct task_struct *init_process = get_pid_task(mod->init_pid, PIDTYPE_PID);
+
+		/* Did the init process die? */
+		if (init_process) {
+			put_task_struct(init_process);
+			ret = -EBUSY;
+			goto out;
+		} else {
+			did_init_crash = true;
+		}
+	}
+#endif
+
 	ret = try_stop_module(mod, flags, &forced);
 	if (ret != 0)
 		goto out;
@@ -1380,6 +1399,10 @@ static void free_module(struct module *mod)
 	mod->state = MODULE_STATE_UNFORMED;
 	mutex_unlock(&module_mutex);
 
+#ifdef CONFIG_MODULE_FORCE_UNLOAD
+	if (mod->init_pid)
+		put_pid(mod->init_pid);
+#endif
 	/* Arch-specific cleanup. */
 	module_arch_cleanup(mod);
 
@@ -3044,6 +3067,11 @@ static noinline int do_init_module(struct module *mod)
 	ftrace_free_mem(mod, mod->mem[MOD_INIT_TEXT].base,
 			mod->mem[MOD_INIT_TEXT].base + mod->mem[MOD_INIT_TEXT].size);
 	mutex_lock(&module_mutex);
+#ifdef CONFIG_MODULE_FORCE_UNLOAD
+	put_pid(mod->init_pid);
+	mod->init_pid = NULL;
+	mod->idempotent = NULL;
+#endif
 	/* Drop initial reference. */
 	module_put(mod);
 	trim_init_extable(mod);
@@ -3474,6 +3502,10 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	if (codetag_load_module(mod))
 		goto sysfs_cleanup;
 
+#ifdef CONFIG_MODULE_FORCE_UNLOAD
+	mod->init_pid = get_pid(task_pid(current));
+	mod->idempotent = info->idempotent;
+#endif
 	/* Get rid of temporary copy. */
 	free_copy(info, flags);
 
-- 
2.45.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ