Module Name:    src
Committed By:   pgoyette
Date:           Sun Apr  1 23:06:11 UTC 2018

Modified Files:
        src/sys/kern [pgoyette-compat]: kern_module.c sys_module.c
        src/sys/sys [pgoyette-compat]: module.h

Log Message:
Remove fixed limit on number of modules which can be "required" by
a module.  Instead, allocate the array dynamically, and expand it
when needed.

XXX Note the modctl(2)'s MODCTL_STAT routine needs to be updated
(and versioned) to handle the unlimited size.  For now, the kernel
will simply truncate the required list if it doesn't fit in the
existing export structure.


To generate a diff of this commit:
cvs rdiff -u -r1.130.2.6 -r1.130.2.7 src/sys/kern/kern_module.c
cvs rdiff -u -r1.23.2.4 -r1.23.2.5 src/sys/kern/sys_module.c
cvs rdiff -u -r1.41.14.6 -r1.41.14.7 src/sys/sys/module.h

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.130.2.6 src/sys/kern/kern_module.c:1.130.2.7
--- src/sys/kern/kern_module.c:1.130.2.6	Sat Mar 31 08:34:17 2018
+++ src/sys/kern/kern_module.c	Sun Apr  1 23:06:11 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_module.c,v 1.130.2.6 2018/03/31 08:34:17 pgoyette Exp $	*/
+/*	$NetBSD: kern_module.c,v 1.130.2.7 2018/04/01 23:06:11 pgoyette 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.130.2.6 2018/03/31 08:34:17 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.130.2.7 2018/04/01 23:06:11 pgoyette Exp $");
 
 #define _MODULE_INTERNAL
 
@@ -765,8 +765,8 @@ module_enqueue(module_t *mod)
 
 		/* Add references to the requisite modules. */
 		for (i = 0; i < mod->mod_nrequired; i++) {
-			KASSERT(mod->mod_required[i] != NULL);
-			mod->mod_required[i]->mod_refcnt++;
+			KASSERT((*mod->mod_required)[i] != NULL);
+			(*mod->mod_required)[i]->mod_refcnt++;
 		}
 	}
 	module_count++;
@@ -774,6 +774,31 @@ module_enqueue(module_t *mod)
 }
 
 /*
+ * Our array of required module pointers starts with zero entries.  If we
+ * need to add a new entry, and the list is already full, we reallocate a
+ * larger array, adding MAXMODDEPS entries.
+ */
+static void
+alloc_required(module_t *mod)
+{
+	module_t *(*new)[], *(*old)[];
+	int areq;
+	int i;
+
+	if (mod->mod_nrequired >= mod->mod_arequired) {
+		areq = mod->mod_arequired + MAXMODDEPS;
+		old= mod->mod_required;
+		new= kmem_alloc(areq * sizeof(module_t *), KM_SLEEP);
+		for (i = 0; i< mod->mod_arequired; i++)
+			(*old)[i] = (*new)[i];
+		mod->mod_required = new;
+		if (old)
+			kmem_free(old, mod->mod_arequired * sizeof(module_t *));
+		mod->mod_arequired = areq;
+	}
+}
+
+/*
  * module_do_builtin:
  *
  *	Initialize a module from the list of modules that are
@@ -830,6 +855,7 @@ module_do_builtin(const module_t *pmod, 
 	 * Initialize pre-requisites.
 	 */
 	if (mi->mi_required != NULL) {
+		mod->mod_arequired = 0;
 		for (s = mi->mi_required; *s != '\0'; s = p) {
 			if (*s == ',')
 				s++;
@@ -840,17 +866,11 @@ module_do_builtin(const module_t *pmod, 
 			strlcpy(buf, s, len);
 			if (buf[0] == '\0')
 				break;
-			if (mod->mod_nrequired == MAXMODDEPS - 1) {
-				module_error("%s: too many required modules "
-				    "%d >= %d", pmod->mod_info->mi_name,
-				    mod->mod_nrequired, MAXMODDEPS - 1);
-				return EINVAL;
-			}
+			alloc_required(mod);
 			error = module_do_builtin(mod, buf, &mod2, NULL);
-			if (error != 0) {
-				return error;
-			}
-			mod->mod_required[mod->mod_nrequired++] = mod2;
+			if (error != 0)
+				goto fail;
+			*mod->mod_required[mod->mod_nrequired++] = mod2;
 		}
 	}
 
@@ -863,7 +883,8 @@ module_do_builtin(const module_t *pmod, 
 			if ((mod2 = module_lookup(*aliasp++)) != NULL) {
 				if (modp != NULL)
 					*modp = mod2;
-				return EEXIST;
+				error = EEXIST;
+				goto fail;
 			}
 		}
 	}
@@ -877,7 +898,7 @@ module_do_builtin(const module_t *pmod, 
 	if (error != 0) {
 		module_error("builtin module `%s' "
 		    "failed to init, error %d", mi->mi_name, error);
-		return error;
+		goto fail;
 	}
 
 	/* load always succeeds after this point */
@@ -889,6 +910,12 @@ module_do_builtin(const module_t *pmod, 
 	}
 	module_enqueue(mod);
 	return 0;
+
+ fail:
+	if (mod->mod_required)
+		kmem_free(mod->mod_required, mod->mod_arequired *
+		    sizeof(module_t *));
+	return error;
 }
 
 /*
@@ -1112,6 +1139,7 @@ module_do_load(const char *name, bool is
 	 * Now try to load any requisite modules.
 	 */
 	if (mi->mi_required != NULL) {
+		mod->mod_arequired = 0;
 		for (s = mi->mi_required; *s != '\0'; s = p) {
 			if (*s == ',')
 				s++;
@@ -1129,13 +1157,7 @@ module_do_load(const char *name, bool is
 			strlcpy(buf, s, len);
 			if (buf[0] == '\0')
 				break;
-			if (mod->mod_nrequired == MAXMODDEPS - 1) {
-				error = EINVAL;
-				module_error("too many required modules "
-				    "%d >= %d", mod->mod_nrequired,
-				    MAXMODDEPS - 1);
-				goto fail;
-			}
+			alloc_required(mod);
 			if (strcmp(buf, mi->mi_name) == 0) {
 				error = EDEADLK;
 				module_error("self-dependency detected for "
@@ -1150,7 +1172,7 @@ module_do_load(const char *name, bool is
 				    buf, error);
 				goto fail;
 			}
-			mod->mod_required[mod->mod_nrequired++] = mod2;
+			*mod->mod_required[mod->mod_nrequired++] = mod2;
 		}
 	}
 
@@ -1248,6 +1270,9 @@ module_do_load(const char *name, bool is
 		filedict = NULL;
 	}
 	TAILQ_REMOVE(pending, mod, mod_chain);
+	if (mod->mod_required)
+		kmem_free(mod->mod_required, mod->mod_arequired *
+		    sizeof(module_t));
 	kmem_free(mod, sizeof(*mod));
 	SLIST_REMOVE_HEAD(&pend_stack, pe_entry);
 	return error;
@@ -1303,14 +1328,18 @@ module_do_unload(const char *name, bool 
 	module_count--;
 	TAILQ_REMOVE(&module_list, mod, mod_chain);
 	for (i = 0; i < mod->mod_nrequired; i++) {
-		mod->mod_required[i]->mod_refcnt--;
+		(*mod->mod_required)[i]->mod_refcnt--;
 	}
 	module_print("unloaded module `%s'", name);
 	if (mod->mod_kobj != NULL) {
 		kobj_unload(mod->mod_kobj);
 	}
+	if (mod->mod_required)
+		kmem_free(mod->mod_required, mod->mod_arequired *
+		    sizeof(module_t));
 	if (mod->mod_source == MODULE_SOURCE_KERNEL) {
 		mod->mod_nrequired = 0; /* will be re-parsed */
+		mod->mod_arequired = 0;
 		if (load_requires_force)
 			module_require_force(mod);
 		TAILQ_INSERT_TAIL(&module_builtins, mod, mod_chain);

Index: src/sys/kern/sys_module.c
diff -u src/sys/kern/sys_module.c:1.23.2.4 src/sys/kern/sys_module.c:1.23.2.5
--- src/sys/kern/sys_module.c:1.23.2.4	Sun Apr  1 10:47:53 2018
+++ src/sys/kern/sys_module.c	Sun Apr  1 23:06:11 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_module.c,v 1.23.2.4 2018/04/01 10:47:53 pgoyette Exp $	*/
+/*	$NetBSD: sys_module.c,v 1.23.2.5 2018/04/01 23:06:11 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_module.c,v 1.23.2.4 2018/04/01 10:47:53 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_module.c,v 1.23.2.5 2018/04/01 23:06:11 pgoyette Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_modular.h"
@@ -111,7 +111,8 @@ out1:
 }
 
 static void
-copy_alias(modstat_t ms, const char * const *aliasp, modinfo_t mi, module_t mod)
+copy_alias(modstat_t *ms, const char * const *aliasp, modinfo_t *mi,
+    module_t *mod)
 {
 
 	strlcpy(ms->ms_name, *aliasp, sizeof(ms->ms_name));
@@ -130,10 +131,12 @@ handle_modctl_stat(struct iovec *iov, vo
 	vaddr_t addr;
 	size_t size;
 	size_t mslen;
+	size_t used;
 	int error;
 	int mscnt;
 	bool stataddr;
 	const char * const *aliasp;
+	const char *suffix = "...";
 
 	/* If not privileged, don't expose kernel addresses. */
 	error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
@@ -157,8 +160,14 @@ handle_modctl_stat(struct iovec *iov, vo
 		mi = mod->mod_info;
 		strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
 		if (mi->mi_required != NULL) {
-			strlcpy(ms->ms_required, mi->mi_required,
+			used = strlcpy(ms->ms_required, mi->mi_required,
 			    sizeof(ms->ms_required));
+			if (used >= sizeof(ms->ms_required)) {
+				ms->ms_required[sizeof(ms->ms_required) -
+				    strlen(suffix) - 1] = '\0';
+				strlcat(ms->ms_required, suffix,
+				    sizeof(ms->ms_required));
+			}
 		}
 		if (mod->mod_kobj != NULL && stataddr) {
 			kobj_stat(mod->mod_kobj, &addr, &size);
@@ -183,8 +192,12 @@ handle_modctl_stat(struct iovec *iov, vo
 		mi = mod->mod_info;
 		strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
 		if (mi->mi_required != NULL) {
-			strlcpy(ms->ms_required, mi->mi_required,
-			    sizeof(ms->ms_required));
+			*ms->ms_required = '\0';
+			used = strlcat(ms->ms_required, mi->mi_required,
+			    sizeof(ms->ms_required) - 6);
+			if (used > sizeof(ms->ms_required) - 6)
+				strlcat(ms->ms_required, ", ...",
+				    sizeof(ms->ms_required));
 		}
 		if (mod->mod_kobj != NULL && stataddr) {
 			kobj_stat(mod->mod_kobj, &addr, &size);

Index: src/sys/sys/module.h
diff -u src/sys/sys/module.h:1.41.14.6 src/sys/sys/module.h:1.41.14.7
--- src/sys/sys/module.h:1.41.14.6	Sun Mar 11 07:25:59 2018
+++ src/sys/sys/module.h	Sun Apr  1 23:06:11 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: module.h,v 1.41.14.6 2018/03/11 07:25:59 pgoyette Exp $	*/
+/*	$NetBSD: module.h,v 1.41.14.7 2018/04/01 23:06:11 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -87,8 +87,9 @@ typedef struct module {
 	const modinfo_t		*mod_info;
 	struct kobj		*mod_kobj;
 	TAILQ_ENTRY(module)	mod_chain;
-	struct module		*mod_required[MAXMODDEPS];
+	struct module		*(*mod_required)[MAXMODDEPS];
 	u_int			mod_nrequired;
+	u_int			mod_arequired;
 	modsrc_t		mod_source;
 	time_t			mod_autotime;
 	void 			*mod_ctf;

Reply via email to