kmodloader: fix TOCTOU problem with scan_builtin_modules
[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 fp = fopen(path, "r");
506 if (!fp)
507 continue;
508
509 if (!fstat(fileno(fp), &st) && S_ISREG(st.st_mode))
510 break;
511
512 /* Not regular file, close it and check next */
513 fclose(fp);
514 fp = NULL;
515 }
516 if (!fp)
517 return 0; /* OK if modules.builtin unavailable */
518
519 while (getline(&buf, &buf_len, fp) > 0) {
520 struct module *m;
521 char *name;
522
523 name = get_module_name(buf);
524 if (!name)
525 continue;
526 m = find_module(name);
527 if (m && !strcmp(m->name, name)) {
528 ULOG_WARN("found duplicate builtin module %s\n", name);
529 continue;
530 }
531 m = get_module_info(NULL, name);
532 if (!m) {
533 ULOG_ERR("failed to find info for builtin module %s\n", name);
534 goto err;
535 }
536 }
537
538 rv = 0;
539 err:
540 free(buf);
541 fclose(fp);
542
543 return rv;
544 }
545
546 static int scan_module_folder(const char *dir)
547 {
548 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
549 char *path;
550 glob_t gl;
551 int j, rv = 0;
552
553 path = alloca(strlen(dir) + sizeof("*.ko") + 1);
554 sprintf(path, "%s*.ko", dir);
555
556 if (glob(path, gl_flags, NULL, &gl) < 0)
557 return -1;
558
559 for (j = 0; j < gl.gl_pathc; j++) {
560 char *name = get_module_name(gl.gl_pathv[j]);
561 struct module *m;
562 char *opts;
563
564 if (!name)
565 continue;
566
567 m = find_module(name);
568 if (m)
569 continue;
570
571 m = get_module_info(gl.gl_pathv[j], name);
572 if (!m) {
573 rv |= -1;
574 continue;
575 }
576
577 opts = kvlist_get(&options, name);
578 if (!opts)
579 continue;
580
581 if (*opts == '\x01')
582 m->state = BLACKLISTED;
583 else
584 m->opts = strdup(opts);
585 }
586
587 globfree(&gl);
588
589 return rv;
590 }
591
592 static int scan_module_folders(void)
593 {
594 int rv = 0;
595 char **p;
596
597 if (init_module_folders())
598 return -1;
599
600 for (p = module_folders; *p; p++)
601 rv |= scan_module_folder(*p);
602
603 return rv;
604 }
605
606 static int print_modinfo(const struct module *m)
607 {
608 const bool is_builtin = (m->state == BUILTIN);
609 unsigned int offset, size;
610 struct param *p;
611 struct stat s;
612 char *map, *strings, *mpath;
613 int rv = -1;
614
615 LIST_HEAD(params);
616
617 mpath = get_module_path(m->name);
618 map = mmap_modinfo(mpath, m->name, &s, &offset, &size);
619 if (map == MAP_FAILED)
620 goto out;
621
622 strings = map + offset;
623 if (is_builtin)
624 printf("name:\t\t%s\n", m->name);
625 printf("filename:\t%s\n", is_builtin ? "(builtin)" : mpath);
626 while (true) {
627 char *pname, *pdata;
628 char *dup = NULL;
629 char *sep, *sep2;
630
631 while (!strings[0])
632 strings++;
633 if (strings >= map + offset + size)
634 break;
635 if (is_builtin) {
636 sep = strstr(strings, ".");
637 if (!sep)
638 break;
639 if (strlen(m->name) == (sep - strings) &&
640 !strncmp(strings, m->name, sep - strings))
641 strings = sep + 1;
642 else
643 goto next_string;
644 }
645 sep = strstr(strings, "=");
646 if (!sep)
647 break;
648 dup = strndup(strings, sep - strings);
649 sep++;
650 if (strncmp(strings, "parm", 4)) {
651 if (strlen(dup) < 7)
652 printf("%s:\t\t%s\n", dup, sep);
653 else
654 printf("%s:\t%s\n", dup, sep);
655 } else {
656 sep2 = strstr(sep, ":");
657 if (!sep2) {
658 free(dup);
659 break;
660 }
661
662 pname = strndup(sep, sep2 - sep);
663 sep2++;
664 pdata = strdup(sep2);
665
666 list_for_each_entry(p, &params, list)
667 if (!strcmp(pname, p->name))
668 break;
669
670 if (list_entry_is_h(p, &params, list)) {
671 p = alloca(sizeof(*p));
672 p->name = pname;
673 p->desc = p->type = NULL;
674 list_add(&p->list, &params);
675 } else {
676 free(pname);
677 }
678
679 if (!strcmp(dup, "parmtype"))
680 p->type = pdata;
681 else
682 p->desc = pdata;
683 }
684
685 free(dup);
686 next_string:
687 strings = &sep[strlen(sep)];
688 }
689
690 list_for_each_entry(p, &params, list) {
691 printf("parm:\t\t%s", p->name);
692 if (p->desc)
693 printf(":%s", p->desc);
694 if (p->type)
695 printf(" (%s)", p->type);
696 printf("\n");
697 free(p->name);
698 free(p->desc);
699 free(p->type);
700 }
701
702 rv = 0;
703
704 out:
705 if (map != MAP_FAILED)
706 munmap(map, s.st_size);
707
708 return rv;
709 }
710
711 static int deps_available(struct module *m, int verbose)
712 {
713 char *dep;
714 int err = 0;
715
716 if (!m->depends || !strcmp(m->depends, "-") || !strcmp(m->depends, ""))
717 return 0;
718
719 dep = m->depends;
720
721 while (*dep) {
722 m = find_module(dep);
723
724 if (verbose && !m)
725 ULOG_ERR("missing dependency %s\n", dep);
726 if (verbose && m && (m->state != LOADED))
727 ULOG_ERR("dependency not loaded %s\n", dep);
728 if (!m || (m->state != LOADED))
729 err++;
730 dep += strlen(dep) + 1;
731 }
732
733 return err;
734 }
735
736 static int insert_module(char *path, const char *options)
737 {
738 void *data = 0;
739 struct stat s;
740 int fd, ret = -1;
741
742 if (!path) {
743 ULOG_ERR("Path not specified\n");
744 return ret;
745 }
746
747 if (stat(path, &s)) {
748 ULOG_ERR("missing module %s\n", path);
749 return ret;
750 }
751
752 fd = open(path, O_RDONLY);
753 if (fd < 0) {
754 ULOG_ERR("cannot open %s\n", path);
755 return ret;
756 }
757
758 data = malloc(s.st_size);
759 if (!data) {
760 ULOG_ERR("out of memory\n");
761 goto out;
762 }
763
764 if (read(fd, data, s.st_size) == s.st_size) {
765 ret = syscall(__NR_init_module, data, (unsigned long) s.st_size, options);
766 if (errno == EEXIST)
767 ret = 0;
768 }
769 else
770 ULOG_ERR("failed to read full module %s\n", path);
771
772 out:
773 close(fd);
774 free(data);
775
776 return ret;
777 }
778
779 static void load_moddeps(struct module *_m)
780 {
781 char *dep;
782 struct module *m;
783
784 if (!strcmp(_m->depends, "-") || !strcmp(_m->depends, ""))
785 return;
786
787 dep = _m->depends;
788
789 while (*dep) {
790 m = find_module(dep);
791
792 if (!m)
793 ULOG_ERR("failed to find dependency %s\n", dep);
794 if (m && (m->state != LOADED)) {
795 m->state = PROBE;
796 load_moddeps(m);
797 }
798
799 dep = dep + strlen(dep) + 1;
800 }
801 }
802
803 static int load_modprobe(bool allow_load_retry)
804 {
805 int loaded, skipped, failed;
806 struct module_node *mn;
807 struct module *m;
808 bool load_retry = false;
809 static bool first_iteration = true;
810
811 avl_for_each_element(&modules, mn, avl) {
812 if (mn->is_alias)
813 continue;
814 m = mn->m;
815 if (m->state == PROBE)
816 load_moddeps(m);
817 }
818
819 do {
820 loaded = 0;
821 skipped = 0;
822 failed = 0;
823 avl_for_each_element(&modules, mn, avl) {
824 if (mn->is_alias)
825 continue;
826 m = mn->m;
827 if ((m->state == PROBE) && (!deps_available(m, 0)) && (!m->error || load_retry)) {
828 if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
829 m->state = LOADED;
830 m->error = 0;
831 loaded++;
832 continue;
833 }
834
835 m->error = 1;
836 }
837
838 if (m->error)
839 failed++;
840 else if (m->state == PROBE)
841 skipped++;
842 }
843
844 if (allow_load_retry) {
845 /* if we can't load anything else let's try to load failed modules */
846 load_retry = loaded ? (failed && !skipped) : (failed && !load_retry && !first_iteration);
847 }
848
849 first_iteration = false;
850 } while (loaded || load_retry);
851
852 return skipped + failed;
853 }
854
855 static int print_insmod_usage(void)
856 {
857 ULOG_INFO("Usage:\n\tinsmod filename [args]\n");
858
859 return -1;
860 }
861
862 static int print_modprobe_usage(void)
863 {
864 ULOG_INFO(
865 "Usage:\n"
866 "\tmodprobe [-q] [-v] filename\n"
867 "\tmodprobe -a [-q] [-v] filename [filename...]\n"
868 );
869
870 return -1;
871 }
872
873 static int print_usage(char *arg)
874 {
875 ULOG_INFO("Usage:\n\t%s module\n", arg);
876
877 return -1;
878 }
879
880 static int main_insmod(int argc, char **argv)
881 {
882 char *name, *cur, *options;
883 int i, ret, len;
884
885 if (argc < 2)
886 return print_insmod_usage();
887
888 name = get_module_name(argv[1]);
889 if (!name) {
890 ULOG_ERR("cannot find module - %s\n", argv[1]);
891 return -1;
892 }
893
894 if (scan_loaded_modules())
895 return -1;
896
897 if (find_module(name)) {
898 ULOG_ERR("module is already loaded - %s\n", name);
899 return -1;
900
901 }
902
903 free_modules();
904
905 for (len = 0, i = 2; i < argc; i++)
906 len += strlen(argv[i]) + 1;
907
908 options = malloc(len);
909 if (!options) {
910 ULOG_ERR("out of memory\n");
911 ret = -1;
912 goto err;
913 }
914
915 options[0] = 0;
916 cur = options;
917 for (i = 2; i < argc; i++) {
918 if (options[0]) {
919 *cur = ' ';
920 cur++;
921 }
922 cur += sprintf(cur, "%s", argv[i]);
923 }
924
925 if (init_module_folders()) {
926 fprintf(stderr, "Failed to find the folder holding the modules\n");
927 ret = -1;
928 goto err;
929 }
930
931 if (get_module_path(argv[1])) {
932 name = argv[1];
933 } else if (!get_module_path(name)) {
934 fprintf(stderr, "Failed to find %s. Maybe it is a built in module ?\n", name);
935 ret = -1;
936 goto err;
937 }
938
939 ret = insert_module(get_module_path(name), options);
940 if (ret)
941 ULOG_ERR("failed to insert %s\n", get_module_path(name));
942
943 err:
944 free(options);
945 return ret;
946 }
947
948 static int main_rmmod(int argc, char **argv)
949 {
950 struct module *m;
951 char *name;
952 int ret;
953
954 if (argc != 2)
955 return print_usage("rmmod");
956
957 if (scan_loaded_modules())
958 return -1;
959
960 if (scan_builtin_modules())
961 return -1;
962
963 name = get_module_name(argv[1]);
964 m = find_module(name);
965 if (!m) {
966 ULOG_ERR("module is not loaded\n");
967 return -1;
968 }
969 if (m->state == BUILTIN) {
970 ULOG_ERR("module is builtin\n");
971 return -1;
972 }
973 ret = syscall(__NR_delete_module, m->name, 0);
974
975 if (ret)
976 ULOG_ERR("unloading the module failed\n");
977
978 free_modules();
979
980 return ret;
981 }
982
983 static int main_lsmod(int argc, char **argv)
984 {
985 struct module_node *mn;
986 struct module *m;
987 char *dep;
988
989 if (scan_loaded_modules())
990 return -1;
991
992 avl_for_each_element(&modules, mn, avl) {
993 if (mn->is_alias)
994 continue;
995 m = mn->m;
996 if (m->state == LOADED) {
997 printf("%-20s%8d%3d ",
998 m->name, m->size, m->usage);
999 if (m->depends && strcmp(m->depends, "-") && strcmp(m->depends, "")) {
1000 dep = m->depends;
1001 while (*dep) {
1002 printf("%s", dep);
1003 dep = dep + strlen(dep) + 1;
1004 if (*dep)
1005 printf(",");
1006 }
1007 }
1008 printf("\n");
1009 }
1010 }
1011
1012 free_modules();
1013
1014 return 0;
1015 }
1016
1017 static int main_modinfo(int argc, char **argv)
1018 {
1019 struct module *m;
1020 char *name;
1021
1022 if (argc != 2)
1023 return print_usage("modinfo");
1024
1025 if (scan_module_folders())
1026 return -1;
1027
1028 if (scan_builtin_modules())
1029 return -1;
1030
1031 name = get_module_name(argv[1]);
1032 m = find_module(name);
1033 if (!m) {
1034 ULOG_ERR("cannot find module - %s\n", argv[1]);
1035 return -1;
1036 }
1037
1038 print_modinfo(m);
1039
1040 return 0;
1041 }
1042
1043 static int main_modprobe(int argc, char **argv)
1044 {
1045 struct module_node *mn;
1046 struct module *m;
1047 int exit_code = 0;
1048 int load_fail;
1049 int log_level = LOG_WARNING;
1050 int opt;
1051 bool quiet = false;
1052 bool use_all = false;
1053
1054 while ((opt = getopt(argc, argv, "aqv")) != -1 ) {
1055 switch (opt) {
1056 case 'a':
1057 use_all = true;
1058 break;
1059 case 'q': /* shhhh! */
1060 quiet = true;
1061 break;
1062 case 'v':
1063 log_level = LOG_DEBUG;
1064 break;
1065 default: /* '?' */
1066 return print_modprobe_usage();
1067 break;
1068 }
1069 }
1070
1071 if (optind >= argc)
1072 return print_modprobe_usage(); /* expected module after options */
1073
1074 /* after print_modprobe_usage() so it won't be filtered out */
1075 ulog_threshold(log_level);
1076
1077 if (scan_module_folders())
1078 return -1;
1079
1080 if (scan_loaded_modules())
1081 return -1;
1082
1083 if (scan_builtin_modules())
1084 return -1;
1085
1086 do {
1087 char *name;
1088
1089 name = get_module_name(argv[optind]);
1090 m = find_module(name);
1091
1092 if (m && m->state == BLACKLISTED) {
1093 if (!quiet)
1094 ULOG_INFO("%s is blacklisted\n", name);
1095 } else if (m && m->state == LOADED) {
1096 if (!quiet)
1097 ULOG_INFO("%s is already loaded\n", name);
1098 } else if (m && m->state == BUILTIN) {
1099 if (!quiet)
1100 ULOG_INFO("%s is builtin\n", name);
1101 } else if (!m) {
1102 if (!quiet)
1103 ULOG_ERR("failed to find a module named %s\n", name);
1104 exit_code = -1;
1105 } else {
1106 m->state = PROBE;
1107 }
1108
1109 optind++;
1110 } while (use_all && optind < argc);
1111
1112 load_fail = load_modprobe(true);
1113 if (load_fail) {
1114 ULOG_ERR("%d module%s could not be probed\n",
1115 load_fail, (load_fail == 1) ? ("") : ("s"));
1116
1117 avl_for_each_element(&modules, mn, avl) {
1118 if (mn->is_alias)
1119 continue;
1120 m = mn->m;
1121 if ((m->state == PROBE) || m->error)
1122 ULOG_ERR("- %s\n", m->name);
1123 }
1124
1125 exit_code = -1;
1126 }
1127
1128 free_modules();
1129
1130 return exit_code;
1131 }
1132
1133 static int main_loader(int argc, char **argv)
1134 {
1135 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
1136 char *dir = "/etc/modules.d/";
1137 struct module_node *mn;
1138 struct module *m;
1139 glob_t gl;
1140 char *path;
1141 int ret = 0, fail, j;
1142
1143 if (argc > 1)
1144 dir = argv[1];
1145
1146 path = malloc(strlen(dir) + 2);
1147 if (!path) {
1148 ULOG_ERR("out of memory\n");
1149 return -1;
1150 }
1151
1152 strcpy(path, dir);
1153 strcat(path, "*");
1154
1155 if (scan_module_folders()) {
1156 ret = -1;
1157 goto free_path;
1158 }
1159
1160 if (scan_loaded_modules()) {
1161 ret = -1;
1162 goto free_path;
1163 }
1164
1165 ULOG_INFO("loading kernel modules from %s\n", path);
1166
1167 if (glob(path, gl_flags, NULL, &gl) < 0)
1168 goto out;
1169
1170 for (j = 0; j < gl.gl_pathc; j++) {
1171 FILE *fp = fopen(gl.gl_pathv[j], "r");
1172 size_t mod_len = 0;
1173 char *mod = NULL;
1174
1175 if (!fp) {
1176 ULOG_ERR("failed to open %s\n", gl.gl_pathv[j]);
1177 continue;
1178 }
1179
1180 while (getline(&mod, &mod_len, fp) > 0) {
1181 char *nl = strchr(mod, '\n');
1182 struct module *m;
1183 char *opts;
1184
1185 if (nl)
1186 *nl = '\0';
1187
1188 opts = strchr(mod, ' ');
1189 if (opts)
1190 *opts++ = '\0';
1191
1192 m = find_module(get_module_name(mod));
1193 if (!m || m->state == LOADED || m->state == BLACKLISTED)
1194 continue;
1195
1196 if (opts) {
1197 if (m->opts) {
1198 char *prev = m->opts;
1199
1200 fail = asprintf(&m->opts, "%s %s", prev, opts);
1201 free(prev);
1202 if (fail < 0) {
1203 ULOG_ERR("out of memory for opts %s\n", opts);
1204 free(mod);
1205 fclose(fp);
1206 ret = -1;
1207 goto out;
1208 }
1209 } else {
1210 m->opts = strdup(opts);
1211 }
1212 }
1213 m->state = PROBE;
1214 if (basename(gl.gl_pathv[j])[0] - '0' <= 9)
1215 load_modprobe(false);
1216
1217 }
1218 free(mod);
1219 fclose(fp);
1220 }
1221
1222 fail = load_modprobe(true);
1223
1224 if (fail) {
1225 ULOG_ERR("%d module%s could not be probed\n",
1226 fail, (fail == 1) ? ("") : ("s"));
1227
1228 avl_for_each_element(&modules, mn, avl) {
1229 if (mn->is_alias)
1230 continue;
1231 m = mn->m;
1232 if ((m->state == PROBE) || (m->error))
1233 ULOG_ERR("- %s - %d\n", m->name, deps_available(m, 1));
1234 }
1235 } else {
1236 ULOG_INFO("done loading kernel modules from %s\n", path);
1237 }
1238
1239 out:
1240 globfree(&gl);
1241 free_path:
1242 free(path);
1243
1244 return ret;
1245 }
1246
1247 static inline char weight(char c)
1248 {
1249 return c == '_' ? '-' : c;
1250 }
1251
1252 static int avl_modcmp(const void *k1, const void *k2, void *ptr)
1253 {
1254 const char *s1 = k1;
1255 const char *s2 = k2;
1256
1257 while (*s1 && (weight(*s1) == weight(*s2)))
1258 {
1259 s1++;
1260 s2++;
1261 }
1262
1263 return (unsigned char)weight(*s1) - (unsigned char)weight(*s2);
1264 }
1265
1266 static void
1267 load_options(void)
1268 {
1269 static char buf[512];
1270 char *s;
1271 FILE *f;
1272
1273 f = fopen("/etc/modules.conf", "r");
1274 if (!f)
1275 return;
1276
1277 while ((s = fgets(buf, sizeof(buf), f)) != NULL) {
1278 char *c, *cmd, *mod;
1279
1280 while (isspace(*s))
1281 s++;
1282
1283 c = strchr(s, '#');
1284 if (c)
1285 *c = 0;
1286
1287 while (isspace(*s))
1288 s++;
1289
1290 c = s + strlen(s);
1291 while (c > s && isspace(c[-1])) {
1292 c[-1] = 0;
1293 c--;
1294 }
1295
1296 cmd = strsep(&s, " \t");
1297 if (!cmd || !*cmd)
1298 continue;
1299
1300 while (isspace(*s))
1301 s++;
1302
1303 mod = strsep(&s, " \t");
1304 if (!mod || !*mod)
1305 continue;
1306
1307 if (!strcmp(cmd, "blacklist")) {
1308 kvlist_set(&options, mod, "\x01");
1309 continue;
1310 }
1311
1312 if (!strcmp(cmd, "options")) {
1313 char *prev = kvlist_get(&options, mod);
1314 char *val = NULL;
1315
1316 while (isspace(*s))
1317 s++;
1318
1319 if (!*s)
1320 continue;
1321
1322 if (prev && prev[0] == '\x01')
1323 continue;
1324
1325 if (!prev) {
1326 kvlist_set(&options, mod, s);
1327 continue;
1328 }
1329
1330 if (asprintf(&val, "%s %s", prev, s) < 0)
1331 continue;
1332
1333 kvlist_set(&options, mod, val);
1334 free(val);
1335 continue;
1336 }
1337 }
1338
1339 fclose(f);
1340 }
1341
1342 int main(int argc, char **argv)
1343 {
1344 char *exec = basename(*argv);
1345
1346 avl_init(&modules, avl_modcmp, false, NULL);
1347 if (!strcmp(exec, "insmod"))
1348 return main_insmod(argc, argv);
1349
1350 if (!strcmp(exec, "rmmod"))
1351 return main_rmmod(argc, argv);
1352
1353 if (!strcmp(exec, "lsmod"))
1354 return main_lsmod(argc, argv);
1355
1356 if (!strcmp(exec, "modinfo"))
1357 return main_modinfo(argc, argv);
1358
1359 load_options();
1360
1361 if (!strcmp(exec, "modprobe"))
1362 return main_modprobe(argc, argv);
1363
1364 ulog_open(ULOG_KMSG, LOG_USER, "kmodloader");
1365 return main_loader(argc, argv);
1366 }