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