tech-kern archive

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

Re: Proposal, again: Disable autoload of compat_xyz modules



In article <20190927125444.GB12813%pony.stderr.spb.ru@localhost>,
Valery Ushakov  <uwe%stderr.spb.ru@localhost> wrote:
>
>May be we should take a look at how SNMP did tables in MIB, b/c we are
>trying to create just such a table indexed by module name.

I think it is simpler than that.

>
>Also, I'm not that sure about autoload of compat stuff especially
>since iirc it currently implies auto-unload too.  I vaguely remember
>when I was debugging something in sh3 kobj_machdep.c I had some
>printfs there that made the autoloads visibile and (iirc) each vi
>invocation would trigger an autoload of compat ioctl code (which
>wouldn't recognize the ioctl, and that would be auto-unloaded a few
>seconds later).
>
>-uwe


Here's what I've implemented:

kern.module.noautoload="compat_linux* compat_[0-4]?"

This disables autoload for all compat_linux modules as well
as compat_netbsd < NetBSD-5.0

Comments?

christos

Index: kern_exec.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_exec.c,v
retrieving revision 1.481
diff -u -u -r1.481 kern_exec.c
--- kern_exec.c	17 Sep 2019 15:19:27 -0000	1.481
+++ kern_exec.c	28 Sep 2019 01:27:00 -0000
@@ -626,6 +626,8 @@
 		"exec_ecoff",
 		"compat_aoutm68k",
 		"compat_netbsd32",
+		"compat_linux",
+		"compat_linux32",
 		"compat_sunos",
 		"compat_sunos32",
 		"compat_ultrix",
Index: kern_module.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_module.c,v
retrieving revision 1.138
diff -u -u -r1.138 kern_module.c
--- kern_module.c	8 Aug 2019 18:08:41 -0000	1.138
+++ kern_module.c	28 Sep 2019 01:27:00 -0000
@@ -53,10 +53,16 @@
 #include <sys/module.h>
 #include <sys/kthread.h>
 #include <sys/sysctl.h>
+#include <sys/queue.h>
 #include <sys/lock.h>
 
 #include <uvm/uvm_extern.h>
 
+#ifndef MODULE_NOAUTOLOAD
+// Disable compat_linux and compat_linux32 by default for now
+#define MODULE_NOAUTOLOAD "compat_linux*"
+#endif
+
 struct vm_map *module_map;
 const char *module_machine;
 char	module_base[MODULE_BASE_SIZE];
@@ -93,6 +99,7 @@
 u_int		module_gen = 1;
 static kcondvar_t module_thread_cv;
 static kmutex_t module_thread_lock;
+static kmutex_t module_noautoload_lock;
 static int	module_thread_ticks;
 int (*module_load_vfs_vec)(const char *, int, bool, module_t *,
 			   prop_dictionary_t *) = (void *)eopnotsupp;
@@ -120,6 +127,8 @@
 static void	module_enqueue(module_t *);
 
 static bool	module_merge_dicts(prop_dictionary_t, const prop_dictionary_t);
+static bool	module_allow_autoload(const char *);
+static void	module_noautoload_update(const char *);
 
 static void	sysctl_module_setup(void);
 static int	sysctl_module_autotime(SYSCTLFN_PROTO);
@@ -412,6 +421,7 @@
 	}
 	cv_init(&module_thread_cv, "mod_unld");
 	mutex_init(&module_thread_lock, MUTEX_DEFAULT, IPL_NONE);
+	mutex_init(&module_noautoload_lock, MUTEX_DEFAULT, IPL_NONE);
 	TAILQ_INIT(&modcblist);
 
 #ifdef MODULAR	/* XXX */
@@ -444,6 +454,8 @@
 	module_netbsd = module_newmodule(MODULE_SOURCE_KERNEL);
 	module_netbsd->mod_refcnt = 1;
 	module_netbsd->mod_info = &module_netbsd_modinfo;
+
+	module_noautoload_update(MODULE_NOAUTOLOAD);
 }
 
 /*
@@ -503,6 +515,100 @@
 	return (0);
 }
 
+struct noautoload {
+	const char *name;
+	SLIST_ENTRY(noautoload) next;
+};
+
+static SLIST_HEAD(, noautoload) noautoload_list =
+    SLIST_HEAD_INITIALIZER(noautoload_list);
+
+static char noautoload_buf[1024];
+static char noautoload_nbuf[sizeof(noautoload_buf)];
+
+static void
+module_noautoload_update(const char *cbuf)
+{
+	static const char SEP[] = " \t\n,";
+	struct noautoload *e, *te;
+	char buf[sizeof(noautoload_buf)];
+
+	strlcpy(buf, cbuf, sizeof(buf));
+
+	mutex_enter(&module_noautoload_lock);
+
+	SLIST_FOREACH_SAFE(e, &noautoload_list, next, te) {
+		SLIST_REMOVE(&noautoload_list, e, noautoload, next);
+		kmem_free(e, sizeof(*e));
+	}
+
+	noautoload_nbuf[0] = noautoload_buf[0] = '\0';
+
+	size_t pos = 0;
+	char *p, *str = buf;
+
+	while ((p = strsep(&str, SEP)) != NULL) {
+		size_t len = strlen(p);
+		if (len == 0)
+			break;
+		e = kmem_alloc(sizeof(*e), KM_SLEEP);
+		e->name = noautoload_nbuf + pos;
+		SLIST_INSERT_HEAD(&noautoload_list, e, next);
+
+		memcpy(noautoload_buf + pos, p, len);
+		memcpy(noautoload_nbuf + pos, p, len);
+		pos += len;
+		noautoload_buf[pos] = ' ';
+		noautoload_nbuf[pos] = '\0';
+		pos++;
+	}
+
+	if (pos)
+		noautoload_buf[pos - 1] = '\0';	/* space to NUL */
+
+	mutex_exit(&module_noautoload_lock);
+}
+
+static int
+sysctl_module_noautoload(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int error;
+	char newbuf[sizeof(noautoload_buf)];
+
+	strlcpy(newbuf, noautoload_buf, sizeof(newbuf));
+
+	node = *rnode;
+	node.sysctl_data = newbuf;
+	node.sysctl_size = sizeof(noautoload_buf);
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL || strcmp(newbuf, noautoload_buf) == 0)
+		return error;
+
+	module_noautoload_update(newbuf);
+
+	return 0;
+}
+
+
+static bool
+module_allow_autoload(const char *name)
+{
+	struct noautoload *e;
+
+	mutex_enter(&module_noautoload_lock);
+	SLIST_FOREACH(e, &noautoload_list, next) {
+		if (pmatch(name, e->name, NULL) > 0) {
+			mutex_exit(&module_noautoload_lock);
+			module_print("module `%s' matched `%s'"
+			    " and will not autoload", name, e->name);
+			return false;
+		}
+	}
+	mutex_exit(&module_noautoload_lock);
+	return true;
+}
+
 static void
 sysctl_module_setup(void)
 {
@@ -542,6 +648,12 @@
 		SYSCTL_DESCR("Auto-unload delay"),
 		sysctl_module_autotime, 0, &module_autotime, 0,
 		CTL_CREATE, CTL_EOL);
+	sysctl_createv(&module_sysctllog, 0, &node, NULL,
+		CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+		CTLTYPE_STRING, "noautoload",
+		SYSCTL_DESCR("List of module patterns not to be autoloaded"),
+		sysctl_module_noautoload, 0, NULL, sizeof(noautoload_buf),
+		CTL_CREATE, CTL_EOL);
 }
 
 /*
@@ -677,6 +789,9 @@
 {
 	int error;
 
+	if (!module_allow_autoload(filename))
+		return EACCES;
+
 	kernconfig_lock();
 
 	/* Nothing if the user has disabled it. */




Home | Main Index | Thread Index | Old Index