kmodloader: fix memory leak in print_modinfo
[project/ubox.git] / kmodloader.c
1 /*
2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15 #define _GNU_SOURCE
16 #include <sys/syscall.h>
17 #include <sys/mman.h>
18 #include <sys/utsname.h>
19
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/syscall.h>
23 #include <sys/types.h>
24 #include <values.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <libgen.h>
31 #include <glob.h>
32 #include <elf.h>
33 #include <ctype.h>
34
35 #include <libubox/avl.h>
36 #include <libubox/avl-cmp.h>
37 #include <libubox/utils.h>
38 #include <libubox/ulog.h>
39 #include <libubox/kvlist.h>
40 #include <libubox/list.h>
41
42 #define DEF_MOD_PATH "/modules/%s/"
43 #define MOD_BUILTIN "modules.builtin"
44 #define MOD_BUILTIN_MODINFO "modules.builtin.modinfo"
45 /* duplicated from in-kernel include/linux/module.h */
46 #define MODULE_NAME_LEN (64 - sizeof(unsigned long))
47
48 struct param {
49 char *name;
50 char *desc;
51 char *type;
52 struct list_head list;
53 };
54
55 enum {
56 BUILTIN,
57 SCANNED,
58 PROBE,
59 LOADED,
60 BLACKLISTED,
61 };
62
63 struct module {
64 char *name;
65 char *depends;
66 char *opts;
67
68 int size;
69 int usage;
70 int state;
71 int error;
72 int refcnt; /* number of references from module_node.m */
73 };
74
75 struct module_node {
76 struct avl_node avl;
77 struct module *m;
78 bool is_alias;
79 };
80
81 static struct avl_tree modules;
82 static KVLIST(options, kvlist_strlen);
83
84 static char **module_folders = NULL;
85
86 static void free_module(struct module *m);
87
88 static int init_module_folders(void)
89 {
90 int n = 0;
91 struct stat st;
92 struct utsname ver;
93 char *s, *e, *p, path[330], ldpath[256];
94
95 e = ldpath;
96 s = getenv("LD_LIBRARY_PATH");
97
98 if (s)
99 e += snprintf(ldpath, sizeof(ldpath), "%s:", s);
100
101 e += snprintf(e, sizeof(ldpath) - (e - ldpath), "/lib");
102
103 uname(&ver);
104
105 for (s = p = ldpath; p <= e; p++) {
106 if (*p != ':' && *p != '\0')
107 continue;
108
109 *p = 0;
110 snprintf(path, sizeof(path), "%s" DEF_MOD_PATH, s, ver.release);
111
112 if (!stat(path, &st) && S_ISDIR(st.st_mode)) {
113 module_folders = realloc(module_folders, sizeof(p) * (n + 2));
114
115 if (!module_folders) {
116 ULOG_ERR("out of memory\n");
117 return -1;
118 }
119
120 module_folders[n++] = strdup(path);
121 }
122
123 s = p + 1;
124 }
125
126 if (!module_folders) {
127 ULOG_ERR("no module folders for kernel version %s found\n", ver.release);
128 return -1;
129 }
130
131 module_folders[n] = NULL;
132 return 0;
133 }
134
135 static struct module *find_module(const char *name)
136 {
137 struct module_node *mn;
138 mn = avl_find_element(&modules, name, mn, avl);
139 if (mn)
140 return mn->m;
141 else
142 return NULL;
143 }
144
145 static void free_modules(void)
146 {
147 struct module_node *mn, *tmp;
148
149 avl_remove_all_elements(&modules, mn, avl, tmp) {
150 struct module *m = mn->m;
151
152 m->refcnt -= 1;
153 if (m->refcnt == 0)
154 free_module(m);
155 free(mn);
156 }
157 }
158
159 static char* get_module_path(char *name)
160 {
161 char **p;
162 static char path[256];
163 struct stat s;
164
165 if (!stat(name, &s) && S_ISREG(s.st_mode))
166 return name;
167
168 for (p = module_folders; *p; p++) {
169 snprintf(path, sizeof(path), "%s%s.ko", *p, name);
170 if (!stat(path, &s) && S_ISREG(s.st_mode))
171 return path;
172 }
173
174 return NULL;
175 }
176
177 static char* get_module_name(char *path)
178 {
179 static char name[MODULE_NAME_LEN];
180 char *t;
181
182 strncpy(name, basename(path), sizeof(name) - 1);
183
184 t = strstr(name, ".ko");
185 if (t)
186 *t = '\0';
187
188 return name;
189 }
190
191 static int elf64_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
192 {
193 const char *secnames;
194 Elf64_Ehdr *e;
195 Elf64_Shdr *sh;
196 int i;
197
198 e = (Elf64_Ehdr *) map;
199 sh = (Elf64_Shdr *) (map + e->e_shoff);
200
201 secnames = map + sh[e->e_shstrndx].sh_offset;
202 for (i = 0; i < e->e_shnum; i++) {
203 if (!strcmp(section, secnames + sh[i].sh_name)) {
204 *size = sh[i].sh_size;
205 *offset = sh[i].sh_offset;
206 return 0;
207 }
208 }
209
210 return -1;
211 }
212
213 static int elf32_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
214 {
215 const char *secnames;
216 Elf32_Ehdr *e;
217 Elf32_Shdr *sh;
218 int i;
219
220 e = (Elf32_Ehdr *) map;
221 sh = (Elf32_Shdr *) (map + e->e_shoff);
222
223 secnames = map + sh[e->e_shstrndx].sh_offset;
224 for (i = 0; i < e->e_shnum; i++) {
225 if (!strcmp(section, secnames + sh[i].sh_name)) {
226 *size = sh[i].sh_size;
227 *offset = sh[i].sh_offset;
228 return 0;
229 }
230 }
231
232 return -1;
233 }
234
235 static int elf_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
236 {
237 int clazz = map[EI_CLASS];
238 int endian = map[EI_DATA];
239
240 #if __BYTE_ORDER == __LITTLE_ENDIAN
241 if (endian != ELFDATA2LSB)
242 #elif __BYTE_ORDER == __BIG_ENDIAN
243 if (endian != ELFDATA2MSB)
244 #else
245 #error "unsupported endian"
246 #endif
247 {
248 ULOG_ERR("invalid endianess: %d\n", endian);
249 return -1;
250 }
251
252 if (clazz == ELFCLASS32)
253 return elf32_find_section(map, section, offset, size);
254 else if (clazz == ELFCLASS64)
255 return elf64_find_section(map, section, offset, size);
256
257 ULOG_ERR("unknown elf format %d\n", clazz);
258
259 return -1;
260 }
261
262 static struct module_node *
263 alloc_module_node(const char *name, struct module *m, bool is_alias)
264 {
265 struct module_node *mn;
266 char *_name;
267
268 mn = calloc_a(sizeof(*mn),
269 &_name, strlen(name) + 1);
270 if (mn) {
271 mn->avl.key = strcpy(_name, name);
272 mn->m = m;
273 mn->is_alias = is_alias;
274 avl_insert(&modules, &mn->avl);
275 m->refcnt += 1;
276 }
277 return mn;
278 }
279
280 static struct module *
281 alloc_module(const char *name, const char * const *aliases, int naliases, const char *depends, int size)
282 {
283 struct module *m;
284 char *_name, *_dep;
285 int i;
286
287 m = calloc_a(sizeof(*m),
288 &_name, strlen(name) + 1,
289 &_dep, depends ? strlen(depends) + 2 : 0);
290 if (!m)
291 return NULL;
292
293 m->name = strcpy(_name, name);
294 m->opts = 0;
295
296 if (depends) {
297 m->depends = strcpy(_dep, depends);
298 while (*_dep) {
299 if (*_dep == ',')
300 *_dep = '\0';
301 _dep++;
302 }
303 }
304 m->size = size;
305
306 m->refcnt = 0;
307 alloc_module_node(m->name, m, false);
308 for (i = 0; i < naliases; i++)
309 alloc_module_node(aliases[i], m, true);
310
311 return m;
312 }
313
314 static void free_module(struct module *m)
315 {
316 if (m->opts)
317 free(m->opts);
318 free(m);
319 }
320
321 static int scan_loaded_modules(void)
322 {
323 size_t buf_len = 0;
324 char *buf = NULL;
325 int rv = -1;
326 FILE *fp;
327
328 fp = fopen("/proc/modules", "r");
329 if (!fp) {
330 ULOG_ERR("failed to open /proc/modules\n");
331 return -1;
332 }
333
334 while (getline(&buf, &buf_len, fp) > 0) {
335 struct module m;
336 struct module *n;
337
338 m.name = strtok(buf, " ");
339 m.size = atoi(strtok(NULL, " "));
340 m.usage = atoi(strtok(NULL, " "));
341 m.depends = strtok(NULL, " ");
342
343 if (!m.name || !m.depends)
344 continue;
345
346 n = find_module(m.name);
347 if (!n) {
348 /* possibly a module outside /lib/modules/<ver>/ */
349 n = alloc_module(m.name, NULL, 0, m.depends, m.size);
350 }
351 if (!n) {
352 ULOG_ERR("Failed to allocate memory for module\n");
353 goto out;
354 }
355
356 n->usage = m.usage;
357 n->state = LOADED;
358 }
359 rv = 0;
360 out:
361 free(buf);
362 fclose(fp);
363
364 return rv;
365 }
366
367 static char *mmap_modinfo(const char *module, const char *name, struct stat *s, unsigned int *offset, unsigned int *size)
368 {
369 const bool is_builtin = (module == NULL);
370 const char *mpath = NULL;
371 char *map = MAP_FAILED;
372 char path[350], **f;
373 int fd = -1;
374
375 if (is_builtin)
376 for (f = module_folders; *f; f++) {
377 snprintf(path, sizeof(path), "%s%s", *f, MOD_BUILTIN_MODINFO);
378 if (!stat(path, s) && S_ISREG(s->st_mode)) {
379 mpath = path;
380 break;
381 }
382 }
383 else
384 mpath = module;
385
386 if (!mpath) {
387 ULOG_ERR("cannot find modinfo path of module - %s\n", name);
388 goto out;
389 }
390
391 fd = open(mpath, O_RDONLY);
392 if (fd < 0) {
393 ULOG_ERR("failed to open %s\n", mpath);
394 goto out;
395 }
396
397 if (fstat(fd, s) == -1) {
398 ULOG_ERR("failed to stat %s\n", mpath);
399 goto out;
400 }
401
402 map = mmap(NULL, s->st_size, PROT_READ, MAP_PRIVATE, fd, 0);
403 if (map == MAP_FAILED) {
404 ULOG_ERR("failed to mmap %s\n", mpath);
405 goto out;
406 }
407
408 if (is_builtin) {
409 *offset = 0;
410 *size = s->st_size;
411 } else if (elf_find_section(map, ".modinfo", offset, size)) {
412 ULOG_ERR("failed to load the .modinfo section from %s\n", mpath);
413 munmap(map, s->st_size);
414 map = MAP_FAILED;
415 }
416
417 out:
418 if (fd >= 0)
419 close(fd);
420 return map;
421 }
422
423 static struct module* get_module_info(const char *module, const char *name)
424 {
425 const bool is_builtin = (module == NULL);
426 unsigned int offset, size;
427 char *map, *strings, *dep = NULL;
428 const char **aliases = NULL;
429 const char **aliasesr;
430 int naliases = 0;
431 struct module *m = NULL;
432 struct stat s;
433
434 map = mmap_modinfo(module, name, &s, &offset, &size);
435 if (map == MAP_FAILED)
436 goto out;
437
438 strings = map + offset;
439 while (true) {
440 char *sep;
441 int len;
442
443 while (!strings[0])
444 strings++;
445 if (strings >= map + offset + size)
446 break;
447 if (is_builtin) {
448 sep = strstr(strings, ".");
449 if (!sep)
450 break;
451 if (strlen(name) == (sep - strings) &&
452 !strncmp(strings, name, sep - strings))
453 strings = sep + 1;
454 else
455 goto next_string;
456 }
457 sep = strstr(strings, "=");
458 if (!sep)
459 break;
460 len = sep - strings;
461 sep++;
462 if (!strncmp(strings, "depends=", len + 1))
463 dep = sep;
464 else if (!strncmp(strings, "alias=", len + 1)) {
465 aliasesr = realloc(aliases, sizeof(sep) * (naliases + 1));
466 if (!aliasesr) {
467 ULOG_ERR("out of memory\n");
468 goto out;
469 }
470
471 aliases = aliasesr;
472 aliases[naliases++] = sep;
473 }
474 next_string:
475 strings = &sep[strlen(sep)];
476 }
477
478 m = alloc_module(name, aliases, naliases, dep, is_builtin ? 0 : s.st_size);
479
480 if (m)
481 m->state = is_builtin ? BUILTIN : SCANNED;
482
483 out:
484 if (map != MAP_FAILED)
485 munmap(map, s.st_size);
486
487 free(aliases);
488
489 return m;
490 }
491
492 static int scan_builtin_modules(void)
493 {
494 char **p, path[350];
495 size_t buf_len = 0;
496 char *buf = NULL;
497 struct stat st;
498 FILE *fp = NULL;
499 int rv = -1;
500
501 if (!module_folders && init_module_folders())
502 return -1;
503 for (p = module_folders; *p; p++) {
504 snprintf(path, sizeof(path), "%s%s", *p, MOD_BUILTIN);
505 if (!stat(path, &st) && S_ISREG(st.st_mode)) {
506 fp = fopen(path, "r");
507 if (fp)
508 break;
509 }
510 }
511 if (!fp)
512 return 0; /* OK if modules.builtin unavailable */
513
514 while (getline(&buf, &buf_len, fp) > 0) {
515 struct module *m;
516 char *name;
517
518 name = get_module_name(buf);
519 if (!name)
520 continue;
521 m = find_module(name);
522 if (m && !strcmp(m->name, name)) {
523 ULOG_WARN("found duplicate builtin module %s\n", name);
524 continue;
525 }
526 m = get_module_info(NULL, name);
527 if (!m) {
528 ULOG_ERR("failed to find info for builtin module %s\n", name);
529 goto err;
530 }
531 }
532
533 rv = 0;
534 err:
535 free(buf);
536 fclose(fp);
537
538 return rv;
539 }
540
541 static int scan_module_folder(const char *dir)
542 {
543 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
544 char *path;
545 glob_t gl;
546 int j, rv = 0;
547
548 path = alloca(strlen(dir) + sizeof("*.ko") + 1);
549 sprintf(path, "%s*.ko", dir);
550
551 if (glob(path, gl_flags, NULL, &gl) < 0)
552 return -1;
553
554 for (j = 0; j < gl.gl_pathc; j++) {
555 char *name = get_module_name(gl.gl_pathv[j]);
556 struct module *m;
557 char *opts;
558
559 if (!name)
560 continue;
561
562 m = find_module(name);
563 if (m)
564 continue;
565
566 m = get_module_info(gl.gl_pathv[j], name);
567 if (!m) {
568 rv |= -1;
569 continue;
570 }
571
572 opts = kvlist_get(&options, name);
573 if (!opts)
574 continue;
575
576 if (*opts == '\x01')
577 m->state = BLACKLISTED;
578 else
579 m->opts = strdup(opts);
580 }
581
582 globfree(&gl);
583
584 return rv;
585 }
586
587 static int scan_module_folders(void)
588 {
589 int rv = 0;
590 char **p;
591
592 if (init_module_folders())
593 return -1;
594
595 for (p = module_folders; *p; p++)
596 rv |= scan_module_folder(*p);
597
598 return rv;
599 }
600
601 static int print_modinfo(const struct module *m)
602 {
603 const bool is_builtin = (m->state == BUILTIN);
604 unsigned int offset, size;
605 struct param *p;
606 struct stat s;
607 char *map, *strings, *mpath;
608 int rv = -1;
609
610 LIST_HEAD(params);
611
612 mpath = get_module_path(m->name);
613 map = mmap_modinfo(mpath, m->name, &s, &offset, &size);
614 if (map == MAP_FAILED)
615 goto out;
616
617 strings = map + offset;
618 if (is_builtin)
619 printf("name:\t\t%s\n", m->name);
620 printf("filename:\t%s\n", is_builtin ? "(builtin)" : mpath);
621 while (true) {
622 char *pname, *pdata;
623 char *dup = NULL;
624 char *sep, *sep2;
625
626 while (!strings[0])
627 strings++;
628 if (strings >= map + offset + size)
629 break;
630 if (is_builtin) {
631 sep = strstr(strings, ".");
632 if (!sep)
633 break;
634 if (strlen(m->name) == (sep - strings) &&
635 !strncmp(strings, m->name, sep - strings))
636 strings = sep + 1;
637 else
638 goto next_string;
639 }
640 sep = strstr(strings, "=");
641 if (!sep)
642 break;
643 dup = strndup(strings, sep - strings);
644 sep++;
645 if (strncmp(strings, "parm", 4)) {
646 if (strlen(dup) < 7)
647 printf("%s:\t\t%s\n", dup, sep);
648 else
649 printf("%s:\t%s\n", dup, sep);
650 } else {
651 sep2 = strstr(sep, ":");
652 if (!sep2) {
653 free(dup);
654 break;
655 }
656
657 pname = strndup(sep, sep2 - sep);
658 sep2++;
659 pdata = strdup(sep2);
660
661 list_for_each_entry(p, &params, list)
662 if (!strcmp(pname, p->name))
663 break;
664
665 if (list_entry_is_h(p, &params, list)) {
666 p = alloca(sizeof(*p));
667 p->name = pname;
668 p->desc = p->type = NULL;
669 list_add(&p->list, &params);
670 } else {
671 free(pname);
672 }
673
674 if (!strcmp(dup, "parmtype"))
675 p->type = pdata;
676 else
677 p->desc = pdata;
678 }
679
680 free(dup);
681 next_string:
682 strings = &sep[strlen(sep)];
683 }
684
685 list_for_each_entry(p, &params, list) {
686 printf("parm:\t\t%s", p->name);
687 if (p->desc)
688 printf(":%s", p->desc);
689 if (p->type)
690 printf(" (%s)", p->type);
691 printf("\n");
692 free(p->name);
693 free(p->desc);
694 free(p->type);
695 }
696
697 rv = 0;
698
699 out:
700 if (map != MAP_FAILED)
701 munmap(map, s.st_size);
702
703 return rv;
704 }
705
706 static int deps_available(struct module *m, int verbose)
707 {
708 char *dep;
709 int err = 0;
710
711 if (!m->depends || !strcmp(m->depends, "-") || !strcmp(m->depends, ""))
712 return 0;
713
714 dep = m->depends;
715
716 while (*dep) {
717 m = find_module(dep);
718
719 if (verbose && !m)
720 ULOG_ERR("missing dependency %s\n", dep);
721 if (verbose && m && (m->state != LOADED))
722 ULOG_ERR("dependency not loaded %s\n", dep);
723 if (!m || (m->state != LOADED))
724 err++;
725 dep += strlen(dep) + 1;
726 }
727
728 return err;
729 }
730
731 static int insert_module(char *path, const char *options)
732 {
733 void *data = 0;
734 struct stat s;
735 int fd, ret = -1;
736
737 if (!path) {
738 ULOG_ERR("Path not specified\n");
739 return ret;
740 }
741
742 if (stat(path, &s)) {
743 ULOG_ERR("missing module %s\n", path);
744 return ret;
745 }
746
747 fd = open(path, O_RDONLY);
748 if (fd < 0) {
749 ULOG_ERR("cannot open %s\n", path);
750 return ret;
751 }
752
753 data = malloc(s.st_size);
754 if (!data) {
755 ULOG_ERR("out of memory\n");
756 goto out;
757 }
758
759 if (read(fd, data, s.st_size) == s.st_size) {
760 ret = syscall(__NR_init_module, data, (unsigned long) s.st_size, options);
761 if (errno == EEXIST)
762 ret = 0;
763 }
764 else
765 ULOG_ERR("failed to read full module %s\n", path);
766
767 out:
768 close(fd);
769 free(data);
770
771 return ret;
772 }
773
774 static void load_moddeps(struct module *_m)
775 {
776 char *dep;
777 struct module *m;
778
779 if (!strcmp(_m->depends, "-") || !strcmp(_m->depends, ""))
780 return;
781
782 dep = _m->depends;
783
784 while (*dep) {
785 m = find_module(dep);
786
787 if (!m)
788 ULOG_ERR("failed to find dependency %s\n", dep);
789 if (m && (m->state != LOADED)) {
790 m->state = PROBE;
791 load_moddeps(m);
792 }
793
794 dep = dep + strlen(dep) + 1;
795 }
796 }
797
798 static int load_modprobe(bool allow_load_retry)
799 {
800 int loaded, skipped, failed;
801 struct module_node *mn;
802 struct module *m;
803 bool load_retry = false;
804 static bool first_iteration = true;
805
806 avl_for_each_element(&modules, mn, avl) {
807 if (mn->is_alias)
808 continue;
809 m = mn->m;
810 if (m->state == PROBE)
811 load_moddeps(m);
812 }
813
814 do {
815 loaded = 0;
816 skipped = 0;
817 failed = 0;
818 avl_for_each_element(&modules, mn, avl) {
819 if (mn->is_alias)
820 continue;
821 m = mn->m;
822 if ((m->state == PROBE) && (!deps_available(m, 0)) && (!m->error || load_retry)) {
823 if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
824 m->state = LOADED;
825 m->error = 0;
826 loaded++;
827 continue;
828 }
829
830 m->error = 1;
831 }
832
833 if (m->error)
834 failed++;
835 else if (m->state == PROBE)
836 skipped++;
837 }
838
839 if (allow_load_retry) {
840 /* if we can't load anything else let's try to load failed modules */
841 load_retry = loaded ? (failed && !skipped) : (failed && !load_retry && !first_iteration);
842 }
843
844 first_iteration = false;
845 } while (loaded || load_retry);
846
847 return skipped + failed;
848 }
849
850 static int print_insmod_usage(void)
851 {
852 ULOG_INFO("Usage:\n\tinsmod filename [args]\n");
853
854 return -1;
855 }
856
857 static int print_modprobe_usage(void)
858 {
859 ULOG_INFO(
860 "Usage:\n"
861 "\tmodprobe [-q] [-v] filename\n"
862 "\tmodprobe -a [-q] [-v] filename [filename...]\n"
863 );
864
865 return -1;
866 }
867
868 static int print_usage(char *arg)
869 {
870 ULOG_INFO("Usage:\n\t%s module\n", arg);
871
872 return -1;
873 }
874
875 static int main_insmod(int argc, char **argv)
876 {
877 char *name, *cur, *options;
878 int i, ret, len;
879
880 if (argc < 2)
881 return print_insmod_usage();
882
883 name = get_module_name(argv[1]);
884 if (!name) {
885 ULOG_ERR("cannot find module - %s\n", argv[1]);
886 return -1;
887 }
888
889 if (scan_loaded_modules())
890 return -1;
891
892 if (find_module(name)) {
893 ULOG_ERR("module is already loaded - %s\n", name);
894 return -1;
895
896 }
897
898 free_modules();
899
900 for (len = 0, i = 2; i < argc; i++)
901 len += strlen(argv[i]) + 1;
902
903 options = malloc(len);
904 if (!options) {
905 ULOG_ERR("out of memory\n");
906 ret = -1;
907 goto err;
908 }
909
910 options[0] = 0;
911 cur = options;
912 for (i = 2; i < argc; i++) {
913 if (options[0]) {
914 *cur = ' ';
915 cur++;
916 }
917 cur += sprintf(cur, "%s", argv[i]);
918 }
919
920 if (init_module_folders()) {
921 fprintf(stderr, "Failed to find the folder holding the modules\n");
922 ret = -1;
923 goto err;
924 }
925
926 if (get_module_path(argv[1])) {
927 name = argv[1];
928 } else if (!get_module_path(name)) {
929 fprintf(stderr, "Failed to find %s. Maybe it is a built in module ?\n", name);
930 ret = -1;
931 goto err;
932 }
933
934 ret = insert_module(get_module_path(name), options);
935 if (ret)
936 ULOG_ERR("failed to insert %s\n", get_module_path(name));
937
938 err:
939 free(options);
940 return ret;
941 }
942
943 static int main_rmmod(int argc, char **argv)
944 {
945 struct module *m;
946 char *name;
947 int ret;
948
949 if (argc != 2)
950 return print_usage("rmmod");
951
952 if (scan_loaded_modules())
953 return -1;
954
955 if (scan_builtin_modules())
956 return -1;
957
958 name = get_module_name(argv[1]);
959 m = find_module(name);
960 if (!m) {
961 ULOG_ERR("module is not loaded\n");
962 return -1;
963 }
964 if (m->state == BUILTIN) {
965 ULOG_ERR("module is builtin\n");
966 return -1;
967 }
968 ret = syscall(__NR_delete_module, m->name, 0);
969
970 if (ret)
971 ULOG_ERR("unloading the module failed\n");
972
973 free_modules();
974
975 return ret;
976 }
977
978 static int main_lsmod(int argc, char **argv)
979 {
980 struct module_node *mn;
981 struct module *m;
982 char *dep;
983
984 if (scan_loaded_modules())
985 return -1;
986
987 avl_for_each_element(&modules, mn, avl) {
988 if (mn->is_alias)
989 continue;
990 m = mn->m;
991 if (m->state == LOADED) {
992 printf("%-20s%8d%3d ",
993 m->name, m->size, m->usage);
994 if (m->depends && strcmp(m->depends, "-") && strcmp(m->depends, "")) {
995 dep = m->depends;
996 while (*dep) {
997 printf("%s", dep);
998 dep = dep + strlen(dep) + 1;
999 if (*dep)
1000 printf(",");
1001 }
1002 }
1003 printf("\n");
1004 }
1005 }
1006
1007 free_modules();
1008
1009 return 0;
1010 }
1011
1012 static int main_modinfo(int argc, char **argv)
1013 {
1014 struct module *m;
1015 char *name;
1016
1017 if (argc != 2)
1018 return print_usage("modinfo");
1019
1020 if (scan_module_folders())
1021 return -1;
1022
1023 if (scan_builtin_modules())
1024 return -1;
1025
1026 name = get_module_name(argv[1]);
1027 m = find_module(name);
1028 if (!m) {
1029 ULOG_ERR("cannot find module - %s\n", argv[1]);
1030 return -1;
1031 }
1032
1033 print_modinfo(m);
1034
1035 return 0;
1036 }
1037
1038 static int main_modprobe(int argc, char **argv)
1039 {
1040 struct module_node *mn;
1041 struct module *m;
1042 int exit_code = 0;
1043 int load_fail;
1044 int log_level = LOG_WARNING;
1045 int opt;
1046 bool quiet = false;
1047 bool use_all = false;
1048
1049 while ((opt = getopt(argc, argv, "aqv")) != -1 ) {
1050 switch (opt) {
1051 case 'a':
1052 use_all = true;
1053 break;
1054 case 'q': /* shhhh! */
1055 quiet = true;
1056 break;
1057 case 'v':
1058 log_level = LOG_DEBUG;
1059 break;
1060 default: /* '?' */
1061 return print_modprobe_usage();
1062 break;
1063 }
1064 }
1065
1066 if (optind >= argc)
1067 return print_modprobe_usage(); /* expected module after options */
1068
1069 /* after print_modprobe_usage() so it won't be filtered out */
1070 ulog_threshold(log_level);
1071
1072 if (scan_module_folders())
1073 return -1;
1074
1075 if (scan_loaded_modules())
1076 return -1;
1077
1078 if (scan_builtin_modules())
1079 return -1;
1080
1081 do {
1082 char *name;
1083
1084 name = get_module_name(argv[optind]);
1085 m = find_module(name);
1086
1087 if (m && m->state == BLACKLISTED) {
1088 if (!quiet)
1089 ULOG_INFO("%s is blacklisted\n", name);
1090 } else if (m && m->state == LOADED) {
1091 if (!quiet)
1092 ULOG_INFO("%s is already loaded\n", name);
1093 } else if (m && m->state == BUILTIN) {
1094 if (!quiet)
1095 ULOG_INFO("%s is builtin\n", name);
1096 } else if (!m) {
1097 if (!quiet)
1098 ULOG_ERR("failed to find a module named %s\n", name);
1099 exit_code = -1;
1100 } else {
1101 m->state = PROBE;
1102 }
1103
1104 optind++;
1105 } while (use_all && optind < argc);
1106
1107 load_fail = load_modprobe(true);
1108 if (load_fail) {
1109 ULOG_ERR("%d module%s could not be probed\n",
1110 load_fail, (load_fail == 1) ? ("") : ("s"));
1111
1112 avl_for_each_element(&modules, mn, avl) {
1113 if (mn->is_alias)
1114 continue;
1115 m = mn->m;
1116 if ((m->state == PROBE) || m->error)
1117 ULOG_ERR("- %s\n", m->name);
1118 }
1119
1120 exit_code = -1;
1121 }
1122
1123 free_modules();
1124
1125 return exit_code;
1126 }
1127
1128 static int main_loader(int argc, char **argv)
1129 {
1130 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
1131 char *dir = "/etc/modules.d/";
1132 struct module_node *mn;
1133 struct module *m;
1134 glob_t gl;
1135 char *path;
1136 int ret = 0, fail, j;
1137
1138 if (argc > 1)
1139 dir = argv[1];
1140
1141 path = malloc(strlen(dir) + 2);
1142 if (!path) {
1143 ULOG_ERR("out of memory\n");
1144 return -1;
1145 }
1146
1147 strcpy(path, dir);
1148 strcat(path, "*");
1149
1150 if (scan_module_folders()) {
1151 ret = -1;
1152 goto free_path;
1153 }
1154
1155 if (scan_loaded_modules()) {
1156 ret = -1;
1157 goto free_path;
1158 }
1159
1160 ULOG_INFO("loading kernel modules from %s\n", path);
1161
1162 if (glob(path, gl_flags, NULL, &gl) < 0)
1163 goto out;
1164
1165 for (j = 0; j < gl.gl_pathc; j++) {
1166 FILE *fp = fopen(gl.gl_pathv[j], "r");
1167 size_t mod_len = 0;
1168 char *mod = NULL;
1169
1170 if (!fp) {
1171 ULOG_ERR("failed to open %s\n", gl.gl_pathv[j]);
1172 continue;
1173 }
1174
1175 while (getline(&mod, &mod_len, fp) > 0) {
1176 char *nl = strchr(mod, '\n');
1177 struct module *m;
1178 char *opts;
1179
1180 if (nl)
1181 *nl = '\0';
1182
1183 opts = strchr(mod, ' ');
1184 if (opts)
1185 *opts++ = '\0';
1186
1187 m = find_module(get_module_name(mod));
1188 if (!m || m->state == LOADED || m->state == BLACKLISTED)
1189 continue;
1190
1191 if (opts) {
1192 if (m->opts) {
1193 char *prev = m->opts;
1194
1195 fail = asprintf(&m->opts, "%s %s", prev, opts);
1196 free(prev);
1197 if (fail < 0) {
1198 ULOG_ERR("out of memory for opts %s\n", opts);
1199 free(mod);
1200 fclose(fp);
1201 ret = -1;
1202 goto out;
1203 }
1204 } else {
1205 m->opts = strdup(opts);
1206 }
1207 }
1208 m->state = PROBE;
1209 if (basename(gl.gl_pathv[j])[0] - '0' <= 9)
1210 load_modprobe(false);
1211
1212 }
1213 free(mod);
1214 fclose(fp);
1215 }
1216
1217 fail = load_modprobe(true);
1218
1219 if (fail) {
1220 ULOG_ERR("%d module%s could not be probed\n",
1221 fail, (fail == 1) ? ("") : ("s"));
1222
1223 avl_for_each_element(&modules, mn, avl) {
1224 if (mn->is_alias)
1225 continue;
1226 m = mn->m;
1227 if ((m->state == PROBE) || (m->error))
1228 ULOG_ERR("- %s - %d\n", m->name, deps_available(m, 1));
1229 }
1230 } else {
1231 ULOG_INFO("done loading kernel modules from %s\n", path);
1232 }
1233
1234 out:
1235 globfree(&gl);
1236 free_path:
1237 free(path);
1238
1239 return ret;
1240 }
1241
1242 static inline char weight(char c)
1243 {
1244 return c == '_' ? '-' : c;
1245 }
1246
1247 static int avl_modcmp(const void *k1, const void *k2, void *ptr)
1248 {
1249 const char *s1 = k1;
1250 const char *s2 = k2;
1251
1252 while (*s1 && (weight(*s1) == weight(*s2)))
1253 {
1254 s1++;
1255 s2++;
1256 }
1257
1258 return (unsigned char)weight(*s1) - (unsigned char)weight(*s2);
1259 }
1260
1261 static void
1262 load_options(void)
1263 {
1264 static char buf[512];
1265 char *s;
1266 FILE *f;
1267
1268 f = fopen("/etc/modules.conf", "r");
1269 if (!f)
1270 return;
1271
1272 while ((s = fgets(buf, sizeof(buf), f)) != NULL) {
1273 char *c, *cmd, *mod;
1274
1275 while (isspace(*s))
1276 s++;
1277
1278 c = strchr(s, '#');
1279 if (c)
1280 *c = 0;
1281
1282 while (isspace(*s))
1283 s++;
1284
1285 c = s + strlen(s);
1286 while (c > s && isspace(c[-1])) {
1287 c[-1] = 0;
1288 c--;
1289 }
1290
1291 cmd = strsep(&s, " \t");
1292 if (!cmd || !*cmd)
1293 continue;
1294
1295 while (isspace(*s))
1296 s++;
1297
1298 mod = strsep(&s, " \t");
1299 if (!mod || !*mod)
1300 continue;
1301
1302 if (!strcmp(cmd, "blacklist")) {
1303 kvlist_set(&options, mod, "\x01");
1304 continue;
1305 }
1306
1307 if (!strcmp(cmd, "options")) {
1308 char *prev = kvlist_get(&options, mod);
1309 char *val = NULL;
1310
1311 while (isspace(*s))
1312 s++;
1313
1314 if (!*s)
1315 continue;
1316
1317 if (prev && prev[0] == '\x01')
1318 continue;
1319
1320 if (!prev) {
1321 kvlist_set(&options, mod, s);
1322 continue;
1323 }
1324
1325 if (asprintf(&val, "%s %s", prev, s) < 0)
1326 continue;
1327
1328 kvlist_set(&options, mod, val);
1329 free(val);
1330 continue;
1331 }
1332 }
1333
1334 fclose(f);
1335 }
1336
1337 int main(int argc, char **argv)
1338 {
1339 char *exec = basename(*argv);
1340
1341 avl_init(&modules, avl_modcmp, false, NULL);
1342 if (!strcmp(exec, "insmod"))
1343 return main_insmod(argc, argv);
1344
1345 if (!strcmp(exec, "rmmod"))
1346 return main_rmmod(argc, argv);
1347
1348 if (!strcmp(exec, "lsmod"))
1349 return main_lsmod(argc, argv);
1350
1351 if (!strcmp(exec, "modinfo"))
1352 return main_modinfo(argc, argv);
1353
1354 load_options();
1355
1356 if (!strcmp(exec, "modprobe"))
1357 return main_modprobe(argc, argv);
1358
1359 ulog_open(ULOG_KMSG, LOG_USER, "kmodloader");
1360 return main_loader(argc, argv);
1361 }