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