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;