Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern module(9): Don't autounload unaudited modules by de...



details:   https://anonhg.NetBSD.org/src/rev/5c0328cf88bf
branches:  trunk
changeset: 368907:5c0328cf88bf
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Fri Aug 12 15:17:10 2022 +0000

description:
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

diffstat:

 sys/kern/kern_module.c |  35 ++++++++++++++++++++++++++++-------
 1 files changed, 28 insertions(+), 7 deletions(-)

diffs (73 lines):

diff -r 3a2d77837fe6 -r 5c0328cf88bf sys/kern/kern_module.c
--- a/sys/kern/kern_module.c    Fri Aug 12 15:01:26 2022 +0000
+++ b/sys/kern/kern_module.c    Fri Aug 12 15:17:10 2022 +0000
@@ -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 @@
 #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 @@
                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 @@
                        }
 
                        /*
-                        * 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 "



Home | Main Index | Thread Index | Old Index