Module Name:    src
Committed By:   riastradh
Date:           Fri Aug 12 15:17:10 UTC 2022

Modified Files:
        src/sys/kern: kern_module.c

Log Message:
module(9): Don't autounload unaudited modules by default.

Modules that have not been audited for autounload safety don't
recognize the command MODULE_CMD_AUTOUNLOAD and return ENOTTY.  These
modules are not safe to autounload, so don't autounload them.  Since
unload is risky business (if not careful, can lead to use-after-free,
kernel memory corruption, &c.), it needs to be opt-in by default, not
opt-out.

Modules that have been audited can return 0 or EBUSY to explicitly
allow or deny autounload.  Users who want to live on the edge to try
to exercise module autounload even for unaudited modules -- and are
willing to accept the consequences, and maybe contribute to auditing!
-- can set the new sysctl knob kern.module.autounload_unsafe=1.

Discussed on tech-kern:
https://mail-index.netbsd.org/tech-kern/2022/08/08/msg028282.html


To generate a diff of this commit:
cvs rdiff -u -r1.157 -r1.158 src/sys/kern/kern_module.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_module.c
diff -u src/sys/kern/kern_module.c:1.157 src/sys/kern/kern_module.c:1.158
--- src/sys/kern/kern_module.c:1.157	Sun Aug  7 23:03:59 2022
+++ src/sys/kern/kern_module.c	Fri Aug 12 15:17:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_module.c,v 1.157 2022/08/07 23:03:59 riastradh Exp $	*/
+/*	$NetBSD: kern_module.c,v 1.158 2022/08/12 15:17:10 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.157 2022/08/07 23:03:59 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.158 2022/08/12 15:17:10 riastradh Exp $");
 
 #define _MODULE_INTERNAL
 
@@ -94,6 +94,7 @@ bool		module_autoload_on = true;
 #else
 bool		module_autoload_on = false;
 #endif
+bool		module_autounload_unsafe = 0;
 u_int		module_count;
 u_int		module_builtinlist;
 u_int		module_autotime = 10;
@@ -546,6 +547,12 @@ sysctl_module_setup(void)
 		CTL_CREATE, CTL_EOL);
 	sysctl_createv(&module_sysctllog, 0, &node, NULL,
 		CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+		CTLTYPE_BOOL, "autounload_unsafe",
+		SYSCTL_DESCR("Enable automatic unload of unaudited modules"),
+		NULL, 0, &module_autounload_unsafe, 0,
+		CTL_CREATE, CTL_EOL);
+	sysctl_createv(&module_sysctllog, 0, &node, NULL,
+		CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
 		CTLTYPE_BOOL, "verbose",
 		SYSCTL_DESCR("Enable verbose output"),
 		NULL, 0, &module_verbose_on, 0,
@@ -1672,14 +1679,28 @@ module_thread(void *cookie)
 			}
 
 			/*
-			 * If this module wants to avoid autounload then
-			 * skip it.  Some modules can ping-pong in and out
-			 * because their use is transient but often. 
-			 * Example: exec_script.
+			 * Ask the module if it can be safely unloaded.
+			 *
+			 * - Modules which have been audited to be OK
+			 *   with that will return 0.
+			 *
+			 * - Modules which have not been audited for
+			 *   safe autounload will return ENOTTY.
+			 *
+			 *   => With kern.module.autounload_unsafe=1,
+			 *      we treat ENOTTY as acceptance.
+			 *
+			 * - Some modules would ping-ping in and out
+			 *   because their use is transient but often.
+			 *   Example: exec_script.  Other modules may
+			 *   still be in use.  These modules can
+			 *   prevent autounload in all cases by
+			 *   returning EBUSY or some other error code.
 			 */
 			mi = mod->mod_info;
 			error = (*mi->mi_modcmd)(MODULE_CMD_AUTOUNLOAD, NULL);
-			if (error == 0 || error == ENOTTY) {
+			if (error == 0 ||
+			    (error == ENOTTY && module_autounload_unsafe)) {
 				(void)module_do_unload(mi->mi_name, false);
 			} else
 				module_print("module `%s' declined to be "

Reply via email to