Source-Changes-HG archive

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

[src/pgoyette-compat]: src/sys Remove fixed limit on number of modules which ...



details:   https://anonhg.NetBSD.org/src/rev/975995d90952
branches:  pgoyette-compat
changeset: 321142:975995d90952
user:      pgoyette <pgoyette%NetBSD.org@localhost>
date:      Sun Apr 01 23:06:11 2018 +0000

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

diffstat:

 sys/kern/kern_module.c |  79 ++++++++++++++++++++++++++++++++++---------------
 sys/kern/sys_module.c  |  25 ++++++++++++---
 sys/sys/module.h       |   5 +-
 3 files changed, 76 insertions(+), 33 deletions(-)

diffs (277 lines):

diff -r b01ecb9b5537 -r 975995d90952 sys/kern/kern_module.c
--- a/sys/kern/kern_module.c    Sun Apr 01 10:47:53 2018 +0000
+++ b/sys/kern/kern_module.c    Sun Apr 01 23:06:11 2018 +0000
@@ -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 @@
 
                /* 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 @@
 }
 
 /*
+ * 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 @@
         * 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 @@
                        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 @@
                        if ((mod2 = module_lookup(*aliasp++)) != NULL) {
                                if (modp != NULL)
                                        *modp = mod2;
-                               return EEXIST;
+                               error = EEXIST;
+                               goto fail;
                        }
                }
        }
@@ -877,7 +898,7 @@
        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_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 @@
         * 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 @@
                        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 @@
                                    buf, error);
                                goto fail;
                        }
-                       mod->mod_required[mod->mod_nrequired++] = mod2;
+                       *mod->mod_required[mod->mod_nrequired++] = mod2;
                }
        }
 
@@ -1248,6 +1270,9 @@
                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_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);
diff -r b01ecb9b5537 -r 975995d90952 sys/kern/sys_module.c
--- a/sys/kern/sys_module.c     Sun Apr 01 10:47:53 2018 +0000
+++ b/sys/kern/sys_module.c     Sun Apr 01 23:06:11 2018 +0000
@@ -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 @@
 }
 
 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 @@
        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 @@
                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 @@
                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);
diff -r b01ecb9b5537 -r 975995d90952 sys/sys/module.h
--- a/sys/sys/module.h  Sun Apr 01 10:47:53 2018 +0000
+++ b/sys/sys/module.h  Sun Apr 01 23:06:11 2018 +0000
@@ -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 @@
        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;



Home | Main Index | Thread Index | Old Index