kmodloader: support duplicate module names and aliases
authorTony Ambardar <itugrok@yahoo.com>
Sat, 27 Jan 2024 11:41:56 +0000 (03:41 -0800)
committerTony Ambardar <itugrok@yahoo.com>
Sat, 2 Mar 2024 21:56:56 +0000 (13:56 -0800)
Allow duplicate keys in the 'modules' avl tree, fixing an indirect memory
leak observed during testing. Given avl keys treat '_' and '-' equally,
some modules may have aliases duplicating their own names under this
mapping, so skip adding these redundant avl tree nodes in alloc_module().

With the above support, update 'modinfo' to print details for all modules
matching the cmdline name, rather than only the first. This is the expected
behaviour and consistent with upstream. The behaviour of other kmodloader
applets, such as boot-time loading or modprobe, remains unchanged.

Signed-off-by: Tony Ambardar <itugrok@yahoo.com>
kmodloader.c

index b705c0cb76220b0bf3e38e7a1c1199a68edc4b53..865f2e2eab5ebc32ee993b68a3e473e3e76fc8b8 100644 (file)
@@ -290,6 +290,8 @@ alloc_module_node(const char *name, struct module *m, bool is_alias)
        return mn;
 }
 
+static int avl_modcmp(const void *k1, const void *k2, void *ptr);
+
 static struct module *
 alloc_module(const char *name, const char * const *aliases, int naliases, const char *depends, int size)
 {
@@ -319,7 +321,8 @@ alloc_module(const char *name, const char * const *aliases, int naliases, const
        m->refcnt = 0;
        alloc_module_node(m->name, m, false);
        for (i = 0; i < naliases; i++)
-               alloc_module_node(aliases[i], m, true);
+               if (avl_modcmp(m->name, aliases[i], NULL))
+                       alloc_module_node(aliases[i], m, true);
 
        return m;
 }
@@ -1030,7 +1033,7 @@ static int main_lsmod(int argc, char **argv)
 
 static int main_modinfo(int argc, char **argv)
 {
-       struct module *m;
+       struct module_node *mn;
        int rv = -1;
        char *name;
 
@@ -1044,14 +1047,19 @@ static int main_modinfo(int argc, char **argv)
                return -1;
 
        name = get_module_name(argv[1]);
-       m = find_module(name);
-       if (!m) {
+       mn = avl_find_element(&modules, name, mn, avl);
+       if (!mn) {
                ULOG_ERR("cannot find module - %s\n", argv[1]);
                goto err;
        }
 
-       print_modinfo(m);
-
+       if (!mn->avl.leader)
+               print_modinfo(mn->m);
+       else
+               do {
+                       print_modinfo(mn->m);
+                       mn = (struct module_node *) mn->avl.list.next;
+               } while (!avl_modcmp(name, mn->avl.key, NULL));
        rv = 0;
 err:
        free_modules();
@@ -1366,7 +1374,7 @@ int main(int argc, char **argv)
 {
        char *exec = basename(*argv);
 
-       avl_init(&modules, avl_modcmp, false, NULL);
+       avl_init(&modules, avl_modcmp, true, NULL);
        if (!strcmp(exec, "insmod"))
                return main_insmod(argc, argv);