DragonFlyBSD Kernel Audit
DF-0162 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/kern_module.c b/sys/kern/kern_module.c
--- a/sys/kern/kern_module.c
+++ b/sys/kern/kern_module.c
@@ -138,7 +138,15 @@
     newmod->handler = data->evhand ? data->evhand : modevent_nop;
     newmod->arg = data->priv;
     bzero(&newmod->data, sizeof(newmod->data));
+    /*
+     * Serialize against sys_modnext/modfnext/modstat/modfind readers,
+     * which walk `modules` under mod_token.  Otherwise the TAILQ
+     * pointers we are about to mutate can be observed in an
+     * inconsistent state, corrupting the list.  (DF-0162)
+     */
+    lwkt_gettoken(&mod_token);
     TAILQ_INSERT_TAIL(&modules, newmod, link);
+    lwkt_reltoken(&mod_token);
 
     if (container == NULL)
 	container = linker_current_file;
@@ -175,7 +183,13 @@
 
     rc = --mod->refs;
     if (rc == 0) {
+	/*
+	 * Serialize against sys_modnext/modfnext/modstat/modfind readers
+	 * walking `modules` under mod_token.  (DF-0162)
+	 */
+	lwkt_gettoken(&mod_token);
 	TAILQ_REMOVE(&modules, mod, link);
+	lwkt_reltoken(&mod_token);
 	if (mod->file) {
 	    TAILQ_REMOVE(&mod->file->modules, mod, flink);
 	}