]> git.ipfire.org Git - thirdparty/kmod.git/blame_incremental - libkmod/libkmod-module.c
ci: move compression variants further down
[thirdparty/kmod.git] / libkmod / libkmod-module.c
... / ...
CommitLineData
1// SPDX-License-Identifier: LGPL-2.1-or-later
2/*
3 * Copyright (C) 2011-2013 ProFUSION embedded systems
4 */
5
6#include <assert.h>
7#include <ctype.h>
8#include <dirent.h>
9#include <errno.h>
10#include <fnmatch.h>
11#include <inttypes.h>
12#include <limits.h>
13#include <stdarg.h>
14#include <stddef.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19#include <sys/mman.h>
20#include <sys/stat.h>
21#include <sys/syscall.h>
22#include <sys/types.h>
23#include <sys/wait.h>
24
25#include <shared/strbuf.h>
26#include <shared/util.h>
27
28#include "libkmod.h"
29#include "libkmod-internal.h"
30
31enum kmod_module_builtin {
32 KMOD_MODULE_BUILTIN_UNKNOWN,
33 KMOD_MODULE_BUILTIN_NO,
34 KMOD_MODULE_BUILTIN_YES,
35};
36
37struct kmod_module {
38 struct kmod_ctx *ctx;
39 char *hashkey;
40 char *name;
41 char *path;
42 struct kmod_list *dep;
43 char *options;
44 const char *install_commands; /* owned by kmod_config */
45 const char *remove_commands; /* owned by kmod_config */
46 char *alias; /* only set if this module was created from an alias */
47 struct kmod_file *file;
48 int refcount;
49 struct {
50 bool dep : 1;
51 bool options : 1;
52 bool install_commands : 1;
53 bool remove_commands : 1;
54 } init;
55
56 /*
57 * mark if module is builtin, i.e. it's present on modules.builtin
58 * file. This is set as soon as it is needed or as soon as we know
59 * about it, i.e. the module was created from builtin lookup.
60 */
61 enum kmod_module_builtin builtin;
62
63 /*
64 * private field used by kmod_module_get_probe_list() to detect
65 * dependency loops
66 */
67 bool visited : 1;
68
69 /*
70 * set by kmod_module_get_probe_list: indicates for probe_insert()
71 * whether the module's command and softdep should be ignored
72 */
73 bool ignorecmd : 1;
74
75 /*
76 * set by kmod_module_get_probe_list: indicates whether this is the
77 * module the user asked for or its dependency, or whether this
78 * is a softdep only
79 */
80 bool required : 1;
81};
82
83static inline const char *path_join(const char *path, size_t prefixlen, char buf[PATH_MAX])
84{
85 size_t pathlen;
86
87 if (path[0] == '/')
88 return path;
89
90 pathlen = strlen(path);
91 if (prefixlen + pathlen + 1 >= PATH_MAX)
92 return NULL;
93
94 memcpy(buf + prefixlen, path, pathlen + 1);
95 return buf;
96}
97
98static inline bool module_is_inkernel(struct kmod_module *mod)
99{
100 int state = kmod_module_get_initstate(mod);
101
102 if (state == KMOD_MODULE_LIVE || state == KMOD_MODULE_BUILTIN)
103 return true;
104
105 return false;
106}
107
108void kmod_module_parse_depline(struct kmod_module *mod, char *line)
109{
110 struct kmod_ctx *ctx = mod->ctx;
111 struct kmod_list *list = NULL;
112 const char *dirname;
113 char buf[PATH_MAX];
114 char *p, *saveptr;
115 size_t n = 0;
116 size_t dirnamelen;
117
118 if (mod->init.dep)
119 return;
120 assert(mod->dep == NULL);
121 mod->init.dep = true;
122
123 p = strchr(line, ':');
124 if (p == NULL)
125 return;
126
127 *p = '\0';
128 dirname = kmod_get_dirname(mod->ctx);
129 dirnamelen = strlen(dirname);
130 if (dirnamelen + 2 >= sizeof(buf))
131 return;
132
133 memcpy(buf, dirname, dirnamelen);
134 buf[dirnamelen] = '/';
135 dirnamelen++;
136 buf[dirnamelen] = '\0';
137
138 if (mod->path == NULL) {
139 const char *str = path_join(line, dirnamelen, buf);
140 if (str == NULL)
141 return;
142 mod->path = strdup(str);
143 if (mod->path == NULL)
144 return;
145 }
146
147 p++;
148 for (p = strtok_r(p, " \t", &saveptr); p != NULL;
149 p = strtok_r(NULL, " \t", &saveptr)) {
150 struct kmod_list *l_new;
151 struct kmod_module *depmod = NULL;
152 const char *path;
153 int err;
154
155 path = path_join(p, dirnamelen, buf);
156 if (path == NULL) {
157 ERR(ctx, "could not join path '%s' and '%s'.\n", dirname, p);
158 goto fail;
159 }
160
161 err = kmod_module_new_from_path(ctx, path, &depmod);
162 if (err < 0) {
163 ERR(ctx, "ctx=%p path=%s error=%s\n", ctx, path, strerror(-err));
164 goto fail;
165 }
166
167 DBG(ctx, "add dep: %s\n", path);
168
169 l_new = kmod_list_prepend(list, depmod);
170 if (l_new == NULL) {
171 ERR(ctx, "could not add dependency for %s\n", mod->name);
172 goto fail;
173 }
174 list = l_new;
175 n++;
176 }
177
178 DBG(ctx, "%zu dependencies for %s\n", n, mod->name);
179
180 mod->dep = list;
181 return;
182
183fail:
184 kmod_module_unref_list(list);
185 mod->init.dep = false;
186}
187
188void kmod_module_set_visited(struct kmod_module *mod, bool visited)
189{
190 mod->visited = visited;
191}
192
193void kmod_module_set_builtin(struct kmod_module *mod, bool builtin)
194{
195 mod->builtin = builtin ? KMOD_MODULE_BUILTIN_YES : KMOD_MODULE_BUILTIN_NO;
196}
197
198void kmod_module_set_required(struct kmod_module *mod, bool required)
199{
200 mod->required = required;
201}
202
203bool kmod_module_is_builtin(struct kmod_module *mod)
204{
205 if (mod->builtin == KMOD_MODULE_BUILTIN_UNKNOWN) {
206 kmod_module_set_builtin(mod, kmod_lookup_alias_is_builtin(mod->ctx,
207 mod->name));
208 }
209
210 return mod->builtin == KMOD_MODULE_BUILTIN_YES;
211}
212/*
213 * Memory layout with alias:
214 *
215 * struct kmod_module {
216 * hashkey -----.
217 * alias -----. |
218 * name ----. | |
219 * } | | |
220 * name <----------' | |
221 * alias <-----------' |
222 * name\alias <--------'
223 *
224 * Memory layout without alias:
225 *
226 * struct kmod_module {
227 * hashkey ---.
228 * alias -----|----> NULL
229 * name ----. |
230 * } | |
231 * name <----------'-'
232 *
233 * @key is "name\alias" or "name" (in which case alias == NULL)
234 */
235/* TODO: rework to create the hash within this function and remove the _maybe_unused_
236 * workaround */
237static int kmod_module_new(struct kmod_ctx *ctx, const char *key,
238 _maybe_unused_ const char *name, size_t namelen,
239 const char *alias, size_t aliaslen, struct kmod_module **mod)
240{
241 struct kmod_module *m;
242 size_t keylen;
243 int err;
244
245 m = kmod_pool_get_module(ctx, key);
246 if (m != NULL) {
247 *mod = kmod_module_ref(m);
248 return 0;
249 }
250
251 if (alias == NULL)
252 keylen = namelen;
253 else
254 keylen = namelen + aliaslen + 1;
255
256 m = malloc(sizeof(*m) + (alias == NULL ? 1 : 2) * (keylen + 1));
257 if (m == NULL)
258 return -ENOMEM;
259
260 memset(m, 0, sizeof(*m));
261
262 m->ctx = kmod_ref(ctx);
263 m->name = (char *)m + sizeof(*m);
264 memcpy(m->name, key, keylen + 1);
265 if (alias == NULL) {
266 m->hashkey = m->name;
267 m->alias = NULL;
268 } else {
269 m->name[namelen] = '\0';
270 m->alias = m->name + namelen + 1;
271 m->hashkey = m->name + keylen + 1;
272 memcpy(m->hashkey, key, keylen + 1);
273 }
274
275 m->refcount = 1;
276 err = kmod_pool_add_module(ctx, m, m->hashkey);
277 if (err < 0) {
278 free(m);
279 return err;
280 }
281 *mod = m;
282
283 return 0;
284}
285
286KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx, const char *name,
287 struct kmod_module **mod)
288{
289 size_t namelen;
290 char name_norm[PATH_MAX];
291
292 if (ctx == NULL || name == NULL || mod == NULL)
293 return -ENOENT;
294
295 modname_normalize(name, name_norm, &namelen);
296
297 return kmod_module_new(ctx, name_norm, name_norm, namelen, NULL, 0, mod);
298}
299
300int kmod_module_new_from_alias(struct kmod_ctx *ctx, const char *alias, const char *name,
301 struct kmod_module **mod)
302{
303 char key[PATH_MAX];
304 size_t namelen = strlen(name);
305 size_t aliaslen = strlen(alias);
306
307 if (namelen + aliaslen + 2 > sizeof(key))
308 return -ENAMETOOLONG;
309
310 memcpy(key, name, namelen);
311 memcpy(key + namelen + 1, alias, aliaslen + 1);
312 key[namelen] = '\\';
313
314 return kmod_module_new(ctx, key, name, namelen, alias, aliaslen, mod);
315}
316
317KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx, const char *path,
318 struct kmod_module **mod)
319{
320 struct kmod_module *m;
321 int err;
322 struct stat st;
323 char name[PATH_MAX];
324 char *abspath;
325 size_t namelen;
326
327 if (ctx == NULL || path == NULL || mod == NULL)
328 return -ENOENT;
329
330 abspath = path_make_absolute_cwd(path);
331 if (abspath == NULL) {
332 DBG(ctx, "no absolute path for %s\n", path);
333 return -ENOMEM;
334 }
335
336 err = stat(abspath, &st);
337 if (err < 0) {
338 err = -errno;
339 DBG(ctx, "stat %s: %m\n", path);
340 free(abspath);
341 return err;
342 }
343
344 if (path_to_modname(path, name, &namelen) == NULL) {
345 DBG(ctx, "could not get modname from path %s\n", path);
346 free(abspath);
347 return -ENOENT;
348 }
349
350 err = kmod_module_new(ctx, name, name, namelen, NULL, 0, &m);
351 if (err < 0) {
352 free(abspath);
353 return err;
354 }
355 if (m->path == NULL)
356 m->path = abspath;
357 else if (streq(m->path, abspath))
358 free(abspath);
359 else {
360 kmod_module_unref(m);
361 ERR(ctx,
362 "kmod_module '%s' already exists with different path: new-path='%s' old-path='%s'\n",
363 name, abspath, m->path);
364 free(abspath);
365 return -EEXIST;
366 }
367
368 m->builtin = KMOD_MODULE_BUILTIN_NO;
369 *mod = m;
370
371 return 0;
372}
373
374KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
375{
376 if (mod == NULL)
377 return NULL;
378
379 if (--mod->refcount > 0)
380 return mod;
381
382 DBG(mod->ctx, "kmod_module %p released\n", mod);
383
384 kmod_pool_del_module(mod->ctx, mod, mod->hashkey);
385 kmod_module_unref_list(mod->dep);
386
387 if (mod->file)
388 kmod_file_unref(mod->file);
389
390 kmod_unref(mod->ctx);
391 free(mod->options);
392 free(mod->path);
393 free(mod);
394 return NULL;
395}
396
397KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
398{
399 if (mod == NULL)
400 return NULL;
401
402 mod->refcount++;
403
404 return mod;
405}
406
407typedef _nonnull_all_ int (*lookup_func)(struct kmod_ctx *ctx, const char *name,
408 struct kmod_list **list);
409
410static int __kmod_module_new_from_lookup(struct kmod_ctx *ctx, const lookup_func lookup[],
411 size_t lookup_count, const char *s,
412 struct kmod_list **list)
413{
414 unsigned int i;
415
416 for (i = 0; i < lookup_count; i++) {
417 int err;
418
419 err = lookup[i](ctx, s, list);
420 if (err < 0 && err != -ENOSYS)
421 return err;
422 else if (*list != NULL)
423 return 0;
424 }
425
426 return 0;
427}
428
429KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx, const char *given_alias,
430 struct kmod_list **list)
431{
432 static const lookup_func lookup[] = {
433 kmod_lookup_alias_from_config,
434 kmod_lookup_alias_from_moddep_file,
435 kmod_lookup_alias_from_symbols_file,
436 kmod_lookup_alias_from_commands,
437 kmod_lookup_alias_from_aliases_file,
438 kmod_lookup_alias_from_builtin_file,
439 kmod_lookup_alias_from_kernel_builtin_file,
440 };
441 char alias[PATH_MAX];
442 int err;
443
444 if (ctx == NULL || given_alias == NULL)
445 return -ENOENT;
446
447 if (list == NULL || *list != NULL) {
448 ERR(ctx, "An empty list is needed to create lookup\n");
449 return -ENOSYS;
450 }
451
452 if (alias_normalize(given_alias, alias, NULL) < 0) {
453 DBG(ctx, "invalid alias: %s\n", given_alias);
454 return -EINVAL;
455 }
456
457 DBG(ctx, "input alias=%s, normalized=%s\n", given_alias, alias);
458
459 err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup), alias, list);
460
461 DBG(ctx, "lookup=%s found=%d\n", alias, err >= 0 && *list);
462
463 if (err < 0) {
464 kmod_module_unref_list(*list);
465 *list = NULL;
466 }
467
468 return err;
469}
470
471KMOD_EXPORT int kmod_module_new_from_name_lookup(struct kmod_ctx *ctx,
472 const char *modname,
473 struct kmod_module **mod)
474{
475 static const lookup_func lookup[] = {
476 kmod_lookup_alias_from_moddep_file,
477 kmod_lookup_alias_from_builtin_file,
478 kmod_lookup_alias_from_kernel_builtin_file,
479 };
480 char name_norm[PATH_MAX];
481 struct kmod_list *list = NULL;
482 int err;
483
484 if (ctx == NULL || modname == NULL || mod == NULL)
485 return -ENOENT;
486
487 modname_normalize(modname, name_norm, NULL);
488
489 DBG(ctx, "input modname=%s, normalized=%s\n", modname, name_norm);
490
491 err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup), name_norm,
492 &list);
493
494 DBG(ctx, "lookup=%s found=%d\n", name_norm, err >= 0 && list);
495
496 if (err >= 0 && list != NULL)
497 *mod = kmod_module_get_module(list);
498
499 kmod_module_unref_list(list);
500
501 return err;
502}
503
504KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list)
505{
506 kmod_list_release(list, kmod_module_unref);
507
508 return 0;
509}
510
511KMOD_EXPORT int kmod_module_get_filtered_blacklist(const struct kmod_ctx *ctx,
512 const struct kmod_list *input,
513 struct kmod_list **output)
514{
515 return kmod_module_apply_filter(ctx, KMOD_FILTER_BLACKLIST, input, output);
516}
517
518static void module_get_dependencies_noref(struct kmod_module *mod)
519{
520 if (!mod->init.dep) {
521 /* lazy init */
522 char *line = kmod_search_moddep(mod->ctx, mod->name);
523
524 if (line != NULL) {
525 kmod_module_parse_depline(mod, line);
526 free(line);
527 }
528 }
529}
530
531KMOD_EXPORT struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod)
532{
533 struct kmod_list *l, *l_new, *list_new = NULL;
534
535 if (mod == NULL)
536 return NULL;
537
538 module_get_dependencies_noref((struct kmod_module *)mod);
539
540 kmod_list_foreach(l, mod->dep) {
541 l_new = kmod_list_append(list_new, kmod_module_ref(l->data));
542 if (l_new == NULL) {
543 kmod_module_unref(l->data);
544 goto fail;
545 }
546
547 list_new = l_new;
548 }
549
550 return list_new;
551
552fail:
553 ERR(mod->ctx, "out of memory\n");
554 kmod_module_unref_list(list_new);
555 return NULL;
556}
557
558KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *entry)
559{
560 if (entry == NULL)
561 return NULL;
562
563 return kmod_module_ref(entry->data);
564}
565
566KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
567{
568 if (mod == NULL)
569 return NULL;
570
571 return mod->name;
572}
573
574KMOD_EXPORT const char *kmod_module_get_path(const struct kmod_module *mod)
575{
576 if (mod == NULL)
577 return NULL;
578
579 DBG(mod->ctx, "name='%s' path='%s'\n", mod->name, mod->path);
580
581 if (mod->path != NULL)
582 return mod->path;
583 if (mod->init.dep)
584 return NULL;
585
586 /* lazy init */
587 module_get_dependencies_noref((struct kmod_module *)mod);
588
589 return mod->path;
590}
591
592extern long delete_module(const char *name, unsigned int flags);
593
594KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod, unsigned int flags)
595{
596 unsigned int libkmod_flags = flags & 0xff;
597
598 int err;
599
600 if (mod == NULL)
601 return -ENOENT;
602
603 /* Filter out other flags and force ONONBLOCK */
604 flags &= KMOD_REMOVE_FORCE;
605 flags |= KMOD_REMOVE_NOWAIT;
606
607 err = delete_module(mod->name, flags);
608 if (err != 0) {
609 err = -errno;
610 if (!(libkmod_flags & KMOD_REMOVE_NOLOG))
611 ERR(mod->ctx, "could not remove '%s': %m\n", mod->name);
612 }
613
614 return err;
615}
616
617extern long init_module(const void *mem, unsigned long len, const char *args);
618
619static int do_finit_module(struct kmod_module *mod, unsigned int flags, const char *args)
620{
621 enum kmod_file_compression_type compression, kernel_compression;
622 unsigned int kernel_flags = 0;
623 int err;
624
625 /*
626 * When module is not compressed or its compression type matches the
627 * one in use by the kernel, there is no need to read the file
628 * in userspace. Otherwise, reuse ENOSYS to trigger the same fallback
629 * as when finit_module() is not supported.
630 */
631 compression = kmod_file_get_compression(mod->file);
632 kernel_compression = kmod_get_kernel_compression(mod->ctx);
633 if (!(compression == KMOD_FILE_COMPRESSION_NONE ||
634 compression == kernel_compression))
635 return -ENOSYS;
636
637 if (compression != KMOD_FILE_COMPRESSION_NONE)
638 kernel_flags |= MODULE_INIT_COMPRESSED_FILE;
639
640 if (flags & KMOD_INSERT_FORCE_VERMAGIC)
641 kernel_flags |= MODULE_INIT_IGNORE_VERMAGIC;
642 if (flags & KMOD_INSERT_FORCE_MODVERSION)
643 kernel_flags |= MODULE_INIT_IGNORE_MODVERSIONS;
644
645 err = finit_module(kmod_file_get_fd(mod->file), args, kernel_flags);
646 if (err < 0)
647 err = -errno;
648
649 return err;
650}
651
652static int do_init_module(struct kmod_module *mod, unsigned int flags, const char *args)
653{
654 _cleanup_free_ const void *stripped = NULL;
655 struct kmod_elf *elf;
656 const void *mem;
657 off_t size;
658 int err;
659
660 if (flags & (KMOD_INSERT_FORCE_VERMAGIC | KMOD_INSERT_FORCE_MODVERSION)) {
661 err = kmod_file_get_elf(mod->file, &elf);
662 if (err)
663 return err;
664
665 err = kmod_elf_strip(elf, flags, &stripped);
666 if (err) {
667 ERR(mod->ctx, "Failed to strip version information: %s\n",
668 strerror(-err));
669 return err;
670 }
671 mem = stripped;
672 } else {
673 err = kmod_file_load_contents(mod->file);
674 if (err)
675 return err;
676
677 mem = kmod_file_get_contents(mod->file);
678 }
679 size = kmod_file_get_size(mod->file);
680
681 err = init_module(mem, size, args);
682 if (err < 0)
683 err = -errno;
684
685 return err;
686}
687
688KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod, unsigned int flags,
689 const char *options)
690{
691 int err;
692 const char *path;
693 const char *args = options ? options : "";
694
695 if (mod == NULL)
696 return -ENOENT;
697
698 path = kmod_module_get_path(mod);
699 if (path == NULL) {
700 ERR(mod->ctx, "could not find module by name='%s'\n", mod->name);
701 return -ENOENT;
702 }
703
704 if (!mod->file) {
705 err = kmod_file_open(mod->ctx, path, &mod->file);
706 if (err)
707 return err;
708 }
709
710 err = do_finit_module(mod, flags, args);
711 if (err == -ENOSYS)
712 err = do_init_module(mod, flags, args);
713
714 if (err < 0)
715 INFO(mod->ctx, "Failed to insert module '%s': %s\n", path, strerror(-err));
716
717 return err;
718}
719
720static bool module_is_blacklisted(const struct kmod_module *mod)
721{
722 const struct kmod_ctx *ctx = mod->ctx;
723 const struct kmod_config *config = kmod_get_config(ctx);
724 const struct kmod_list *bl = config->blacklists;
725 const struct kmod_list *l;
726
727 kmod_list_foreach(l, bl) {
728 const char *modname = kmod_blacklist_get_modname(l);
729
730 if (streq(modname, mod->name))
731 return true;
732 }
733
734 return false;
735}
736
737KMOD_EXPORT int kmod_module_apply_filter(const struct kmod_ctx *ctx,
738 enum kmod_filter filter_type,
739 const struct kmod_list *input,
740 struct kmod_list **output)
741{
742 const struct kmod_list *li;
743
744 if (ctx == NULL || output == NULL)
745 return -ENOENT;
746
747 *output = NULL;
748 if (input == NULL)
749 return 0;
750
751 kmod_list_foreach(li, input) {
752 struct kmod_module *mod = li->data;
753 struct kmod_list *node;
754
755 if ((filter_type & KMOD_FILTER_BLACKLIST) && module_is_blacklisted(mod))
756 continue;
757
758 if ((filter_type & KMOD_FILTER_BUILTIN) && kmod_module_is_builtin(mod))
759 continue;
760
761 node = kmod_list_append(*output, mod);
762 if (node == NULL)
763 goto fail;
764
765 *output = node;
766 kmod_module_ref(mod);
767 }
768
769 return 0;
770
771fail:
772 kmod_module_unref_list(*output);
773 *output = NULL;
774 return -ENOMEM;
775}
776
777static int command_do(struct kmod_module *mod, const char *type, const char *cmd)
778{
779 const char *modname = kmod_module_get_name(mod);
780 int err;
781
782 DBG(mod->ctx, "%s %s\n", type, cmd);
783
784 setenv("MODPROBE_MODULE", modname, 1);
785 err = system(cmd);
786 unsetenv("MODPROBE_MODULE");
787
788 if (err == -1) {
789 ERR(mod->ctx, "Could not run %s command '%s' for module %s: %m\n", type,
790 cmd, modname);
791 return -EINVAL;
792 }
793
794 if (WEXITSTATUS(err)) {
795 ERR(mod->ctx, "Error running %s command '%s' for module %s: retcode %d\n",
796 type, cmd, modname, WEXITSTATUS(err));
797 return -EINVAL;
798 }
799
800 return 0;
801}
802
803struct probe_insert_cb {
804 int (*run_install)(struct kmod_module *m, const char *cmd, void *data);
805 void *data;
806};
807
808static int module_do_install_commands(struct kmod_module *mod, const char *options,
809 struct probe_insert_cb *cb)
810{
811 const char *command = kmod_module_get_install_commands(mod);
812 char *p;
813 _cleanup_free_ char *cmd;
814 int err;
815 size_t cmdlen, options_len, varlen;
816
817 assert(command);
818
819 if (options == NULL)
820 options = "";
821
822 options_len = strlen(options);
823 cmdlen = strlen(command);
824 varlen = strlen("$CMDLINE_OPTS");
825
826 cmd = memdup(command, cmdlen + 1);
827 if (cmd == NULL)
828 return -ENOMEM;
829
830 while ((p = strstr(cmd, "$CMDLINE_OPTS")) != NULL) {
831 size_t prefixlen = p - cmd;
832 size_t suffixlen = cmdlen - prefixlen - varlen;
833 size_t slen = cmdlen - varlen + options_len;
834 char *suffix = p + varlen;
835 _clang_suppress_alloc_ char *s = malloc(slen + 1);
836 if (!s)
837 return -ENOMEM;
838
839 memcpy(s, cmd, p - cmd);
840 memcpy(s + prefixlen, options, options_len);
841 memcpy(s + prefixlen + options_len, suffix, suffixlen);
842 s[slen] = '\0';
843
844 free(cmd);
845 cmd = s;
846 cmdlen = slen;
847 }
848
849 if (cb->run_install != NULL)
850 err = cb->run_install(mod, cmd, cb->data);
851 else
852 err = command_do(mod, "install", cmd);
853
854 return err;
855}
856
857static char *module_options_concat(const char *opt, const char *xopt)
858{
859 // TODO: we might need to check if xopt overrides options on opt
860 size_t optlen = opt == NULL ? 0 : strlen(opt);
861 size_t xoptlen = xopt == NULL ? 0 : strlen(xopt);
862 char *r;
863
864 if (optlen == 0 && xoptlen == 0)
865 return NULL;
866
867 r = malloc(optlen + xoptlen + 2);
868
869 if (opt != NULL) {
870 memcpy(r, opt, optlen);
871 r[optlen] = ' ';
872 optlen++;
873 }
874
875 if (xopt != NULL)
876 memcpy(r + optlen, xopt, xoptlen);
877
878 r[optlen + xoptlen] = '\0';
879
880 return r;
881}
882
883static int __kmod_module_get_probe_list(struct kmod_module *mod, bool required,
884 bool ignorecmd, struct kmod_list **list);
885
886/* re-entrant */
887static int __kmod_module_fill_softdep(struct kmod_module *mod, struct kmod_list **list)
888{
889 struct kmod_list *pre = NULL, *post = NULL, *l;
890 int err;
891
892 err = kmod_module_get_softdeps(mod, &pre, &post);
893 if (err < 0) {
894 ERR(mod->ctx, "could not get softdep: %s\n", strerror(-err));
895 goto fail;
896 }
897
898 kmod_list_foreach(l, pre) {
899 struct kmod_module *m = l->data;
900 err = __kmod_module_get_probe_list(m, false, false, list);
901 if (err < 0)
902 goto fail;
903 }
904
905 l = kmod_list_append(*list, kmod_module_ref(mod));
906 if (l == NULL) {
907 kmod_module_unref(mod);
908 err = -ENOMEM;
909 goto fail;
910 }
911 *list = l;
912 mod->ignorecmd = (pre != NULL || post != NULL);
913
914 kmod_list_foreach(l, post) {
915 struct kmod_module *m = l->data;
916 err = __kmod_module_get_probe_list(m, false, false, list);
917 if (err < 0)
918 goto fail;
919 }
920
921fail:
922 kmod_module_unref_list(pre);
923 kmod_module_unref_list(post);
924
925 return err;
926}
927
928/* re-entrant */
929static int __kmod_module_get_probe_list(struct kmod_module *mod, bool required,
930 bool ignorecmd, struct kmod_list **list)
931{
932 struct kmod_list *dep, *l;
933 int err = 0;
934
935 if (mod->visited) {
936 DBG(mod->ctx, "Ignore module '%s': already visited\n", mod->name);
937 return 0;
938 }
939 mod->visited = true;
940
941 dep = kmod_module_get_dependencies(mod);
942 if (required) {
943 /*
944 * Called from kmod_module_probe_insert_module(); set the
945 * ->required flag on mod and all its dependencies before
946 * they are possibly visited through some softdeps.
947 */
948 mod->required = true;
949 kmod_list_foreach(l, dep) {
950 struct kmod_module *m = l->data;
951 m->required = true;
952 }
953 }
954
955 kmod_list_foreach(l, dep) {
956 struct kmod_module *m = l->data;
957 err = __kmod_module_fill_softdep(m, list);
958 if (err < 0)
959 goto finish;
960 }
961
962 if (ignorecmd) {
963 l = kmod_list_append(*list, kmod_module_ref(mod));
964 if (l == NULL) {
965 kmod_module_unref(mod);
966 err = -ENOMEM;
967 goto finish;
968 }
969 *list = l;
970 mod->ignorecmd = true;
971 } else
972 err = __kmod_module_fill_softdep(mod, list);
973
974finish:
975 kmod_module_unref_list(dep);
976 return err;
977}
978
979static int kmod_module_get_probe_list(struct kmod_module *mod, bool ignorecmd,
980 struct kmod_list **list)
981{
982 int err;
983
984 assert(mod != NULL);
985 assert(list != NULL && *list == NULL);
986
987 /*
988 * Make sure we don't get screwed by previous calls to this function
989 */
990 kmod_set_modules_visited(mod->ctx, false);
991 kmod_set_modules_required(mod->ctx, false);
992
993 err = __kmod_module_get_probe_list(mod, true, ignorecmd, list);
994 if (err < 0) {
995 kmod_module_unref_list(*list);
996 *list = NULL;
997 }
998
999 return err;
1000}
1001
1002KMOD_EXPORT int kmod_module_probe_insert_module(
1003 struct kmod_module *mod, unsigned int flags, const char *extra_options,
1004 int (*run_install)(struct kmod_module *m, const char *cmd, void *data),
1005 const void *data,
1006 void (*print_action)(struct kmod_module *m, bool install, const char *options))
1007{
1008 struct kmod_list *list = NULL, *l;
1009 struct probe_insert_cb cb;
1010 int err;
1011
1012 if (mod == NULL)
1013 return -ENOENT;
1014
1015 if (!(flags & KMOD_PROBE_IGNORE_LOADED) && module_is_inkernel(mod)) {
1016 if (flags & KMOD_PROBE_FAIL_ON_LOADED)
1017 return -EEXIST;
1018 else
1019 return 0;
1020 }
1021
1022 if (module_is_blacklisted(mod)) {
1023 if (mod->alias != NULL && (flags & KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY))
1024 return KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY;
1025
1026 if (flags & KMOD_PROBE_APPLY_BLACKLIST_ALL)
1027 return KMOD_PROBE_APPLY_BLACKLIST_ALL;
1028
1029 if (flags & KMOD_PROBE_APPLY_BLACKLIST)
1030 return KMOD_PROBE_APPLY_BLACKLIST;
1031 }
1032
1033 err = kmod_module_get_probe_list(mod, !!(flags & KMOD_PROBE_IGNORE_COMMAND),
1034 &list);
1035 if (err < 0)
1036 return err;
1037
1038 if (flags & KMOD_PROBE_APPLY_BLACKLIST_ALL) {
1039 struct kmod_list *filtered = NULL;
1040
1041 err = kmod_module_apply_filter(mod->ctx, KMOD_FILTER_BLACKLIST, list,
1042 &filtered);
1043 if (err < 0)
1044 return err;
1045
1046 kmod_module_unref_list(list);
1047 if (filtered == NULL)
1048 return KMOD_PROBE_APPLY_BLACKLIST_ALL;
1049
1050 list = filtered;
1051 }
1052
1053 cb.run_install = run_install;
1054 cb.data = (void *)data;
1055
1056 kmod_list_foreach(l, list) {
1057 struct kmod_module *m = l->data;
1058 const char *moptions = kmod_module_get_options(m);
1059 const char *cmd = kmod_module_get_install_commands(m);
1060 char *options;
1061
1062 if (!(flags & KMOD_PROBE_IGNORE_LOADED) && module_is_inkernel(m)) {
1063 DBG(mod->ctx, "Ignoring module '%s': already loaded\n", m->name);
1064 err = -EEXIST;
1065 goto finish_module;
1066 }
1067
1068 options =
1069 module_options_concat(moptions, m == mod ? extra_options : NULL);
1070
1071 if (cmd != NULL && !m->ignorecmd) {
1072 if (print_action != NULL)
1073 print_action(m, true, options ?: "");
1074
1075 if (!(flags & KMOD_PROBE_DRY_RUN))
1076 err = module_do_install_commands(m, options, &cb);
1077 } else {
1078 if (print_action != NULL)
1079 print_action(m, false, options ?: "");
1080
1081 if (!(flags & KMOD_PROBE_DRY_RUN))
1082 err = kmod_module_insert_module(m, flags, options);
1083 }
1084
1085 free(options);
1086
1087finish_module:
1088 /*
1089 * Treat "already loaded" error. If we were told to stop on
1090 * already loaded and the module being loaded is not a softdep
1091 * or dep, bail out. Otherwise, just ignore and continue.
1092 *
1093 * We need to check here because of race conditions. We
1094 * checked first if module was already loaded but it may have
1095 * been loaded between the check and the moment we try to
1096 * insert it.
1097 */
1098 if (err == -EEXIST && m == mod && (flags & KMOD_PROBE_FAIL_ON_LOADED))
1099 break;
1100
1101 /*
1102 * Ignore errors from softdeps
1103 */
1104 if (err == -EEXIST || !m->required)
1105 err = 0;
1106
1107 else if (err < 0)
1108 break;
1109 }
1110
1111 kmod_module_unref_list(list);
1112 return err;
1113}
1114
1115KMOD_EXPORT const char *kmod_module_get_options(const struct kmod_module *mod)
1116{
1117 if (mod == NULL)
1118 return NULL;
1119
1120 if (!mod->init.options) {
1121 /* lazy init */
1122 struct kmod_module *m = (struct kmod_module *)mod;
1123 const struct kmod_list *l;
1124 const struct kmod_config *config;
1125 char *opts = NULL;
1126 size_t optslen = 0;
1127
1128 config = kmod_get_config(mod->ctx);
1129
1130 kmod_list_foreach(l, config->options) {
1131 const char *modname = kmod_option_get_modname(l);
1132 const char *str;
1133 size_t len;
1134 void *tmp;
1135
1136 DBG(mod->ctx, "modname=%s mod->name=%s mod->alias=%s\n", modname,
1137 mod->name, mod->alias);
1138 if (!(streq(modname, mod->name) ||
1139 (mod->alias != NULL && streq(modname, mod->alias))))
1140 continue;
1141
1142 DBG(mod->ctx, "passed = modname=%s mod->name=%s mod->alias=%s\n",
1143 modname, mod->name, mod->alias);
1144 str = kmod_option_get_options(l);
1145 len = strlen(str);
1146 if (len < 1)
1147 continue;
1148
1149 tmp = realloc(opts, optslen + len + 2);
1150 if (tmp == NULL) {
1151 free(opts);
1152 goto failed;
1153 }
1154
1155 opts = tmp;
1156
1157 if (optslen > 0) {
1158 opts[optslen] = ' ';
1159 optslen++;
1160 }
1161
1162 memcpy(opts + optslen, str, len);
1163 optslen += len;
1164 opts[optslen] = '\0';
1165 }
1166
1167 m->init.options = true;
1168 m->options = opts;
1169 }
1170
1171 return mod->options;
1172
1173failed:
1174 ERR(mod->ctx, "out of memory\n");
1175 return NULL;
1176}
1177
1178KMOD_EXPORT const char *kmod_module_get_install_commands(const struct kmod_module *mod)
1179{
1180 if (mod == NULL)
1181 return NULL;
1182
1183 if (!mod->init.install_commands) {
1184 /* lazy init */
1185 struct kmod_module *m = (struct kmod_module *)mod;
1186 const struct kmod_list *l;
1187 const struct kmod_config *config;
1188
1189 config = kmod_get_config(mod->ctx);
1190
1191 kmod_list_foreach(l, config->install_commands) {
1192 const char *modname = kmod_command_get_modname(l);
1193
1194 if (fnmatch(modname, mod->name, 0) != 0)
1195 continue;
1196
1197 m->install_commands = kmod_command_get_command(l);
1198
1199 /*
1200 * find only the first command, as modprobe from
1201 * module-init-tools does
1202 */
1203 break;
1204 }
1205
1206 m->init.install_commands = true;
1207 }
1208
1209 return mod->install_commands;
1210}
1211
1212void kmod_module_set_install_commands(struct kmod_module *mod, const char *cmd)
1213{
1214 mod->init.install_commands = true;
1215 mod->install_commands = cmd;
1216}
1217
1218static struct kmod_list *lookup_dep(struct kmod_ctx *ctx, const char *const *array,
1219 unsigned int count)
1220{
1221 struct kmod_list *ret = NULL;
1222 unsigned i;
1223
1224 for (i = 0; i < count; i++) {
1225 const char *depname = array[i];
1226 struct kmod_list *lst = NULL;
1227 int err;
1228
1229 err = kmod_module_new_from_lookup(ctx, depname, &lst);
1230 if (err < 0) {
1231 ERR(ctx, "failed to lookup dependency '%s', continuing anyway.\n",
1232 depname);
1233 continue;
1234 } else if (lst != NULL)
1235 ret = kmod_list_append_list(ret, lst);
1236 }
1237 return ret;
1238}
1239
1240KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod,
1241 struct kmod_list **pre, struct kmod_list **post)
1242{
1243 const struct kmod_list *l;
1244 const struct kmod_config *config;
1245
1246 if (mod == NULL || pre == NULL || post == NULL)
1247 return -ENOENT;
1248
1249 assert(*pre == NULL);
1250 assert(*post == NULL);
1251
1252 config = kmod_get_config(mod->ctx);
1253
1254 kmod_list_foreach(l, config->softdeps) {
1255 const char *modname = kmod_softdep_get_name(l);
1256 const char *const *array;
1257 unsigned count;
1258
1259 if (fnmatch(modname, mod->name, 0) != 0)
1260 continue;
1261
1262 array = kmod_softdep_get_pre(l, &count);
1263 *pre = lookup_dep(mod->ctx, array, count);
1264 array = kmod_softdep_get_post(l, &count);
1265 *post = lookup_dep(mod->ctx, array, count);
1266
1267 /*
1268 * find only the first command, as modprobe from
1269 * module-init-tools does
1270 */
1271 break;
1272 }
1273
1274 return 0;
1275}
1276
1277KMOD_EXPORT int kmod_module_get_weakdeps(const struct kmod_module *mod,
1278 struct kmod_list **weak)
1279{
1280 const struct kmod_list *l;
1281 const struct kmod_config *config;
1282
1283 if (mod == NULL || weak == NULL)
1284 return -ENOENT;
1285
1286 assert(*weak == NULL);
1287
1288 config = kmod_get_config(mod->ctx);
1289
1290 kmod_list_foreach(l, config->weakdeps) {
1291 const char *modname = kmod_weakdep_get_name(l);
1292 const char *const *array;
1293 unsigned count;
1294
1295 if (fnmatch(modname, mod->name, 0) != 0)
1296 continue;
1297
1298 array = kmod_weakdep_get_weak(l, &count);
1299 *weak = lookup_dep(mod->ctx, array, count);
1300
1301 /*
1302 * find only the first command, as modprobe from
1303 * module-init-tools does
1304 */
1305 break;
1306 }
1307
1308 return 0;
1309}
1310
1311KMOD_EXPORT const char *kmod_module_get_remove_commands(const struct kmod_module *mod)
1312{
1313 if (mod == NULL)
1314 return NULL;
1315
1316 if (!mod->init.remove_commands) {
1317 /* lazy init */
1318 struct kmod_module *m = (struct kmod_module *)mod;
1319 const struct kmod_list *l;
1320 const struct kmod_config *config;
1321
1322 config = kmod_get_config(mod->ctx);
1323
1324 kmod_list_foreach(l, config->remove_commands) {
1325 const char *modname = kmod_command_get_modname(l);
1326
1327 if (fnmatch(modname, mod->name, 0) != 0)
1328 continue;
1329
1330 m->remove_commands = kmod_command_get_command(l);
1331
1332 /*
1333 * find only the first command, as modprobe from
1334 * module-init-tools does
1335 */
1336 break;
1337 }
1338
1339 m->init.remove_commands = true;
1340 }
1341
1342 return mod->remove_commands;
1343}
1344
1345void kmod_module_set_remove_commands(struct kmod_module *mod, const char *cmd)
1346{
1347 mod->init.remove_commands = true;
1348 mod->remove_commands = cmd;
1349}
1350
1351KMOD_EXPORT int kmod_module_new_from_loaded(struct kmod_ctx *ctx, struct kmod_list **list)
1352{
1353 struct kmod_list *l = NULL;
1354 FILE *fp;
1355 char line[4096];
1356
1357 if (ctx == NULL || list == NULL)
1358 return -ENOENT;
1359
1360 fp = fopen("/proc/modules", "re");
1361 if (fp == NULL) {
1362 int err = -errno;
1363 ERR(ctx, "could not open /proc/modules: %m\n");
1364 return err;
1365 }
1366
1367 while (fgets(line, sizeof(line), fp)) {
1368 struct kmod_module *m;
1369 struct kmod_list *node;
1370 int err;
1371 size_t len = strlen(line);
1372 char *saveptr, *name = strtok_r(line, " \t", &saveptr);
1373
1374 err = kmod_module_new_from_name(ctx, name, &m);
1375 if (err < 0) {
1376 ERR(ctx, "could not get module from name '%s': %s\n", name,
1377 strerror(-err));
1378 goto eat_line;
1379 }
1380
1381 node = kmod_list_append(l, m);
1382 if (node)
1383 l = node;
1384 else {
1385 ERR(ctx, "out of memory\n");
1386 kmod_module_unref(m);
1387 }
1388eat_line:
1389 while (len > 0 && line[len - 1] != '\n' && fgets(line, sizeof(line), fp))
1390 len = strlen(line);
1391 }
1392
1393 fclose(fp);
1394 *list = l;
1395
1396 return 0;
1397}
1398
1399KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate state)
1400{
1401 switch (state) {
1402 case KMOD_MODULE_BUILTIN:
1403 return "builtin";
1404 case KMOD_MODULE_LIVE:
1405 return "live";
1406 case KMOD_MODULE_COMING:
1407 return "coming";
1408 case KMOD_MODULE_GOING:
1409 return "going";
1410 default:
1411 return NULL;
1412 }
1413}
1414
1415KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod)
1416{
1417 char path[PATH_MAX], buf[32];
1418 int fd, err, pathlen;
1419
1420 if (mod == NULL)
1421 return -ENOENT;
1422
1423 /* remove const: this can only change internal state */
1424 if (kmod_module_is_builtin((struct kmod_module *)mod))
1425 return KMOD_MODULE_BUILTIN;
1426
1427 pathlen = snprintf(path, sizeof(path), "/sys/module/%s/initstate", mod->name);
1428 if (pathlen >= (int)sizeof(path)) {
1429 /* Too long path was truncated */
1430 return -ENAMETOOLONG;
1431 }
1432 fd = open(path, O_RDONLY | O_CLOEXEC);
1433 if (fd < 0) {
1434 err = -errno;
1435 DBG(mod->ctx, "could not open '%s': %m\n", path);
1436
1437 if (pathlen > (int)strlen("/initstate")) {
1438 struct stat st;
1439 path[pathlen - strlen("/initstate")] = '\0';
1440 if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
1441 return KMOD_MODULE_COMING;
1442
1443 err = -errno;
1444 DBG(mod->ctx, "could not open '%s': %m\n", path);
1445 }
1446 return err;
1447 }
1448
1449 err = read_str_safe(fd, buf, sizeof(buf));
1450 close(fd);
1451 if (err < 0) {
1452 ERR(mod->ctx, "could not read from '%s': %s\n", path, strerror(-err));
1453 return err;
1454 }
1455
1456 if (streq(buf, "live\n"))
1457 return KMOD_MODULE_LIVE;
1458 else if (streq(buf, "coming\n"))
1459 return KMOD_MODULE_COMING;
1460 else if (streq(buf, "going\n"))
1461 return KMOD_MODULE_GOING;
1462
1463 ERR(mod->ctx, "unknown %s: '%s'\n", path, buf);
1464 return -EINVAL;
1465}
1466
1467KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
1468{
1469 FILE *fp;
1470 char line[4096];
1471 int lineno = 0;
1472 long size = -ENOENT;
1473 int dfd, cfd;
1474
1475 if (mod == NULL)
1476 return -ENOENT;
1477
1478 /* try to open the module dir in /sys. If this fails, don't
1479 * bother trying to find the size as we know the module isn't
1480 * loaded.
1481 */
1482 snprintf(line, sizeof(line), "/sys/module/%s", mod->name);
1483 dfd = open(line, O_RDONLY | O_CLOEXEC);
1484 if (dfd < 0)
1485 return -errno;
1486
1487 /* available as of linux 3.3.x */
1488 cfd = openat(dfd, "coresize", O_RDONLY | O_CLOEXEC);
1489 if (cfd >= 0) {
1490 if (read_str_long(cfd, &size, 10) < 0)
1491 ERR(mod->ctx, "failed to read coresize from %s\n", line);
1492 close(cfd);
1493 goto done;
1494 }
1495
1496 /* fall back on parsing /proc/modules */
1497 fp = fopen("/proc/modules", "re");
1498 if (fp == NULL) {
1499 int err = -errno;
1500 ERR(mod->ctx, "could not open /proc/modules: %m\n");
1501 close(dfd);
1502 return err;
1503 }
1504
1505 while (fgets(line, sizeof(line), fp)) {
1506 size_t len = strlen(line);
1507 char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
1508 long value;
1509
1510 lineno++;
1511 if (tok == NULL || !streq(tok, mod->name))
1512 goto eat_line;
1513
1514 tok = strtok_r(NULL, " \t", &saveptr);
1515 if (tok == NULL) {
1516 ERR(mod->ctx, "invalid line format at /proc/modules:%d\n", lineno);
1517 break;
1518 }
1519
1520 errno = 0;
1521 value = strtol(tok, &endptr, 10);
1522 if (endptr == tok || *endptr != '\0' || errno == ERANGE || value < 0) {
1523 ERR(mod->ctx, "invalid line format at /proc/modules:%d\n", lineno);
1524 break;
1525 }
1526
1527 size = value;
1528 break;
1529eat_line:
1530 while (len > 0 && line[len - 1] != '\n' && fgets(line, sizeof(line), fp))
1531 len = strlen(line);
1532 }
1533 fclose(fp);
1534
1535done:
1536 close(dfd);
1537 return size;
1538}
1539
1540KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod)
1541{
1542 char path[PATH_MAX];
1543 long refcnt;
1544 int fd, err;
1545
1546 if (mod == NULL)
1547 return -ENOENT;
1548
1549 snprintf(path, sizeof(path), "/sys/module/%s/refcnt", mod->name);
1550 fd = open(path, O_RDONLY | O_CLOEXEC);
1551 if (fd < 0) {
1552 err = -errno;
1553 DBG(mod->ctx, "could not open '%s': %m\n", path);
1554 return err;
1555 }
1556
1557 err = read_str_long(fd, &refcnt, 10);
1558 close(fd);
1559 if (err < 0) {
1560 ERR(mod->ctx, "could not read integer from '%s': '%s'\n", path,
1561 strerror(-err));
1562 return err;
1563 }
1564
1565 return (int)refcnt;
1566}
1567
1568KMOD_EXPORT struct kmod_list *kmod_module_get_holders(const struct kmod_module *mod)
1569{
1570 char dname[PATH_MAX];
1571 struct kmod_list *list = NULL;
1572 struct dirent *dent;
1573 DIR *d;
1574
1575 if (mod == NULL || mod->ctx == NULL)
1576 return NULL;
1577
1578 snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name);
1579
1580 d = opendir(dname);
1581 if (d == NULL) {
1582 ERR(mod->ctx, "could not open '%s': %m\n", dname);
1583 return NULL;
1584 }
1585
1586 for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
1587 struct kmod_module *holder;
1588 struct kmod_list *l;
1589 int err;
1590
1591 if (dent->d_name[0] == '.') {
1592 if (dent->d_name[1] == '\0' ||
1593 (dent->d_name[1] == '.' && dent->d_name[2] == '\0'))
1594 continue;
1595 }
1596
1597 err = kmod_module_new_from_name(mod->ctx, dent->d_name, &holder);
1598 if (err < 0) {
1599 ERR(mod->ctx, "could not create module for '%s': %s\n",
1600 dent->d_name, strerror(-err));
1601 goto fail;
1602 }
1603
1604 l = kmod_list_append(list, holder);
1605 if (l != NULL) {
1606 list = l;
1607 } else {
1608 ERR(mod->ctx, "out of memory\n");
1609 kmod_module_unref(holder);
1610 goto fail;
1611 }
1612 }
1613
1614 closedir(d);
1615 return list;
1616
1617fail:
1618 closedir(d);
1619 kmod_module_unref_list(list);
1620 return NULL;
1621}
1622
1623struct kmod_module_section {
1624 unsigned long address;
1625 char name[];
1626};
1627
1628static void kmod_module_section_free(struct kmod_module_section *section)
1629{
1630 free(section);
1631}
1632
1633KMOD_EXPORT struct kmod_list *kmod_module_get_sections(const struct kmod_module *mod)
1634{
1635 char dname[PATH_MAX];
1636 struct kmod_list *list = NULL;
1637 struct dirent *dent;
1638 DIR *d;
1639 int dfd;
1640
1641 if (mod == NULL)
1642 return NULL;
1643
1644 snprintf(dname, sizeof(dname), "/sys/module/%s/sections", mod->name);
1645
1646 d = opendir(dname);
1647 if (d == NULL) {
1648 ERR(mod->ctx, "could not open '%s': %m\n", dname);
1649 return NULL;
1650 }
1651
1652 dfd = dirfd(d);
1653
1654 for (dent = readdir(d); dent; dent = readdir(d)) {
1655 struct kmod_module_section *section;
1656 struct kmod_list *l;
1657 unsigned long address;
1658 size_t namesz;
1659 int fd, err;
1660
1661 if (dent->d_name[0] == '.') {
1662 if (dent->d_name[1] == '\0' ||
1663 (dent->d_name[1] == '.' && dent->d_name[2] == '\0'))
1664 continue;
1665 }
1666
1667 fd = openat(dfd, dent->d_name, O_RDONLY | O_CLOEXEC);
1668 if (fd < 0) {
1669 ERR(mod->ctx, "could not open '%s/%s': %m\n", dname, dent->d_name);
1670 goto fail;
1671 }
1672
1673 err = read_str_ulong(fd, &address, 16);
1674 close(fd);
1675 if (err < 0) {
1676 ERR(mod->ctx, "could not read long from '%s/%s': %s\n", dname,
1677 dent->d_name, strerror(-err));
1678 goto fail;
1679 }
1680
1681 namesz = strlen(dent->d_name) + 1;
1682 section = malloc(sizeof(*section) + namesz);
1683
1684 if (section == NULL) {
1685 ERR(mod->ctx, "out of memory\n");
1686 goto fail;
1687 }
1688
1689 section->address = address;
1690 memcpy(section->name, dent->d_name, namesz);
1691
1692 l = kmod_list_append(list, section);
1693 if (l != NULL) {
1694 list = l;
1695 } else {
1696 ERR(mod->ctx, "out of memory\n");
1697 free(section);
1698 goto fail;
1699 }
1700 }
1701
1702 closedir(d);
1703 return list;
1704
1705fail:
1706 closedir(d);
1707 kmod_module_unref_list(list);
1708 return NULL;
1709}
1710
1711KMOD_EXPORT const char *kmod_module_section_get_name(const struct kmod_list *entry)
1712{
1713 struct kmod_module_section *section;
1714
1715 if (entry == NULL)
1716 return NULL;
1717
1718 section = entry->data;
1719 return section->name;
1720}
1721
1722KMOD_EXPORT unsigned long kmod_module_section_get_address(const struct kmod_list *entry)
1723{
1724 struct kmod_module_section *section;
1725
1726 if (entry == NULL)
1727 return (unsigned long)-1;
1728
1729 section = entry->data;
1730 return section->address;
1731}
1732
1733KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
1734{
1735 kmod_list_release(list, kmod_module_section_free);
1736}
1737
1738static int kmod_module_get_elf(const struct kmod_module *mod, struct kmod_elf **elf)
1739{
1740 if (mod->file == NULL) {
1741 const char *path = kmod_module_get_path(mod);
1742 int ret;
1743
1744 if (path == NULL)
1745 return -ENOENT;
1746
1747 ret = kmod_file_open(mod->ctx, path, &((struct kmod_module *)mod)->file);
1748 if (ret)
1749 return ret;
1750 }
1751
1752 return kmod_file_get_elf(mod->file, elf);
1753}
1754
1755struct kmod_module_info {
1756 char *key;
1757 char value[];
1758};
1759
1760static struct kmod_module_info *kmod_module_info_new(const char *key, size_t keylen,
1761 const char *value, size_t valuelen)
1762{
1763 struct kmod_module_info *info;
1764
1765 info = malloc(sizeof(struct kmod_module_info) + keylen + valuelen + 2);
1766 if (info == NULL)
1767 return NULL;
1768
1769 info->key = (char *)info + sizeof(struct kmod_module_info) + valuelen + 1;
1770 memcpy(info->key, key, keylen);
1771 info->key[keylen] = '\0';
1772 if (value)
1773 memcpy(info->value, value, valuelen);
1774 info->value[valuelen] = '\0';
1775 return info;
1776}
1777
1778static void kmod_module_info_free(struct kmod_module_info *info)
1779{
1780 free(info);
1781}
1782
1783static struct kmod_list *kmod_module_info_append(struct kmod_list **list, const char *key,
1784 size_t keylen, const char *value,
1785 size_t valuelen)
1786{
1787 struct kmod_module_info *info;
1788 struct kmod_list *n;
1789
1790 info = kmod_module_info_new(key, keylen, value, valuelen);
1791 if (info == NULL)
1792 return NULL;
1793 n = kmod_list_append(*list, info);
1794 if (n != NULL)
1795 *list = n;
1796 else
1797 kmod_module_info_free(info);
1798 return n;
1799}
1800
1801static bool kmod_module_strbuf_pushhex(struct strbuf *sbuf, const char *hex, size_t len)
1802{
1803 static const char digits[] = "0123456789ABCDEF";
1804 const size_t line_limit = 20;
1805
1806 for (size_t i = 0; i < len; i++) {
1807 if (!strbuf_pushchar(sbuf, digits[(hex[i] >> 4) & 0x0F]) ||
1808 !strbuf_pushchar(sbuf, digits[hex[i] & 0x0F]))
1809 return false;
1810
1811 if (i < len - 1) {
1812 if (!strbuf_pushchar(sbuf, ':'))
1813 return false;
1814
1815 if ((i + 1) % line_limit == 0 && !strbuf_pushchars(sbuf, "\n\t\t"))
1816 return false;
1817 }
1818 }
1819
1820 return true;
1821}
1822
1823static struct kmod_list *kmod_module_info_append_hex(struct kmod_list **list,
1824 const char *key, size_t keylen,
1825 const char *value, size_t valuelen)
1826{
1827 struct kmod_list *n;
1828
1829 if (valuelen > 0) {
1830 DECLARE_STRBUF_WITH_STACK(sbuf, 512);
1831 const char *hex;
1832
1833 /* Display as 01:12:DE:AD:BE:EF:... */
1834 if (!kmod_module_strbuf_pushhex(&sbuf, value, valuelen))
1835 goto list_error;
1836 hex = strbuf_str(&sbuf);
1837
1838 n = kmod_module_info_append(list, key, keylen, hex, strlen(hex));
1839 if (n == NULL)
1840 goto list_error;
1841 } else {
1842 n = kmod_module_info_append(list, key, keylen, NULL, 0);
1843 if (n == NULL)
1844 goto list_error;
1845 }
1846
1847 return n;
1848
1849list_error:
1850 return NULL;
1851}
1852
1853KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod,
1854 struct kmod_list **list)
1855{
1856 struct kmod_elf *elf;
1857 char **strings;
1858 int i, count, ret = -ENOMEM;
1859 struct kmod_signature_info sig_info = {};
1860
1861 if (mod == NULL || list == NULL)
1862 return -ENOENT;
1863
1864 assert(*list == NULL);
1865
1866 /* remove const: this can only change internal state */
1867 if (kmod_module_is_builtin((struct kmod_module *)mod)) {
1868 count = kmod_builtin_get_modinfo(mod->ctx, kmod_module_get_name(mod),
1869 &strings);
1870 if (count < 0)
1871 return count;
1872 } else {
1873 ret = kmod_module_get_elf(mod, &elf);
1874 if (ret)
1875 return ret;
1876
1877 count = kmod_elf_get_modinfo_strings(elf, &strings);
1878 if (count < 0)
1879 return count;
1880 }
1881
1882 for (i = 0; i < count; i++) {
1883 struct kmod_list *n;
1884 const char *key, *value;
1885 size_t keylen, valuelen;
1886
1887 key = strings[i];
1888 value = strchr(key, '=');
1889 if (value == NULL) {
1890 keylen = strlen(key);
1891 valuelen = 0;
1892 value = key;
1893 } else {
1894 keylen = value - key;
1895 value++;
1896 valuelen = strlen(value);
1897 }
1898
1899 n = kmod_module_info_append(list, key, keylen, value, valuelen);
1900 if (n == NULL)
1901 goto list_error;
1902 }
1903
1904 if (mod->file && kmod_module_signature_info(mod->file, &sig_info)) {
1905 struct kmod_list *n;
1906
1907 n = kmod_module_info_append(list, "sig_id", strlen("sig_id"),
1908 sig_info.id_type, strlen(sig_info.id_type));
1909 if (n == NULL)
1910 goto list_error;
1911 count++;
1912
1913 n = kmod_module_info_append(list, "signer", strlen("signer"),
1914 sig_info.signer, sig_info.signer_len);
1915 if (n == NULL)
1916 goto list_error;
1917 count++;
1918
1919 n = kmod_module_info_append_hex(list, "sig_key", strlen("sig_key"),
1920 sig_info.key_id, sig_info.key_id_len);
1921 if (n == NULL)
1922 goto list_error;
1923 count++;
1924
1925 n = kmod_module_info_append(list, "sig_hashalgo", strlen("sig_hashalgo"),
1926 sig_info.hash_algo,
1927 strlen(sig_info.hash_algo));
1928 if (n == NULL)
1929 goto list_error;
1930 count++;
1931
1932 /*
1933 * Omit sig_info.algo for now, as these
1934 * are currently constant.
1935 */
1936 n = kmod_module_info_append_hex(list, "signature", strlen("signature"),
1937 sig_info.sig, sig_info.sig_len);
1938
1939 if (n == NULL)
1940 goto list_error;
1941 count++;
1942 }
1943 ret = count;
1944
1945list_error:
1946 /* aux structures freed in normal case also */
1947 kmod_module_signature_info_free(&sig_info);
1948
1949 if (ret < 0) {
1950 kmod_module_info_free_list(*list);
1951 *list = NULL;
1952 }
1953 free(strings);
1954 return ret;
1955}
1956
1957KMOD_EXPORT const char *kmod_module_info_get_key(const struct kmod_list *entry)
1958{
1959 struct kmod_module_info *info;
1960
1961 if (entry == NULL)
1962 return NULL;
1963
1964 info = entry->data;
1965 return info->key;
1966}
1967
1968KMOD_EXPORT const char *kmod_module_info_get_value(const struct kmod_list *entry)
1969{
1970 struct kmod_module_info *info;
1971
1972 if (entry == NULL)
1973 return NULL;
1974
1975 info = entry->data;
1976 return info->value;
1977}
1978
1979KMOD_EXPORT void kmod_module_info_free_list(struct kmod_list *list)
1980{
1981 kmod_list_release(list, kmod_module_info_free);
1982}
1983
1984struct kmod_module_version {
1985 uint64_t crc;
1986 char symbol[];
1987};
1988
1989static struct kmod_module_version *kmod_module_versions_new(uint64_t crc,
1990 const char *symbol)
1991{
1992 struct kmod_module_version *mv;
1993 size_t symbollen = strlen(symbol) + 1;
1994
1995 mv = malloc(sizeof(struct kmod_module_version) + symbollen);
1996 if (mv == NULL)
1997 return NULL;
1998
1999 mv->crc = crc;
2000 memcpy(mv->symbol, symbol, symbollen);
2001 return mv;
2002}
2003
2004static void kmod_module_version_free(struct kmod_module_version *version)
2005{
2006 free(version);
2007}
2008
2009KMOD_EXPORT int kmod_module_get_versions(const struct kmod_module *mod,
2010 struct kmod_list **list)
2011{
2012 struct kmod_elf *elf;
2013 struct kmod_modversion *versions;
2014 int i, count, ret = 0;
2015
2016 if (mod == NULL || list == NULL)
2017 return -ENOENT;
2018
2019 assert(*list == NULL);
2020
2021 ret = kmod_module_get_elf(mod, &elf);
2022 if (ret)
2023 return ret;
2024
2025 count = kmod_elf_get_modversions(elf, &versions);
2026 if (count < 0)
2027 return count;
2028
2029 for (i = 0; i < count; i++) {
2030 struct kmod_module_version *mv;
2031 struct kmod_list *n;
2032
2033 mv = kmod_module_versions_new(versions[i].crc, versions[i].symbol);
2034 if (mv == NULL) {
2035 kmod_module_versions_free_list(*list);
2036 *list = NULL;
2037 ret = -ENOMEM;
2038 goto list_error;
2039 }
2040
2041 n = kmod_list_append(*list, mv);
2042 if (n != NULL)
2043 *list = n;
2044 else {
2045 kmod_module_version_free(mv);
2046 kmod_module_versions_free_list(*list);
2047 *list = NULL;
2048 ret = -ENOMEM;
2049 goto list_error;
2050 }
2051 }
2052 ret = count;
2053
2054list_error:
2055 free(versions);
2056 return ret;
2057}
2058
2059KMOD_EXPORT const char *kmod_module_version_get_symbol(const struct kmod_list *entry)
2060{
2061 struct kmod_module_version *version;
2062
2063 if (entry == NULL || entry->data == NULL)
2064 return NULL;
2065
2066 version = entry->data;
2067 return version->symbol;
2068}
2069
2070KMOD_EXPORT uint64_t kmod_module_version_get_crc(const struct kmod_list *entry)
2071{
2072 struct kmod_module_version *version;
2073
2074 if (entry == NULL || entry->data == NULL)
2075 return 0;
2076
2077 version = entry->data;
2078 return version->crc;
2079}
2080
2081KMOD_EXPORT void kmod_module_versions_free_list(struct kmod_list *list)
2082{
2083 kmod_list_release(list, kmod_module_version_free);
2084}
2085
2086struct kmod_module_symbol {
2087 uint64_t crc;
2088 char symbol[];
2089};
2090
2091static struct kmod_module_symbol *kmod_module_symbols_new(uint64_t crc, const char *symbol)
2092{
2093 struct kmod_module_symbol *mv;
2094 size_t symbollen = strlen(symbol) + 1;
2095
2096 mv = malloc(sizeof(struct kmod_module_symbol) + symbollen);
2097 if (mv == NULL)
2098 return NULL;
2099
2100 mv->crc = crc;
2101 memcpy(mv->symbol, symbol, symbollen);
2102 return mv;
2103}
2104
2105static void kmod_module_symbol_free(struct kmod_module_symbol *symbol)
2106{
2107 free(symbol);
2108}
2109
2110KMOD_EXPORT int kmod_module_get_symbols(const struct kmod_module *mod,
2111 struct kmod_list **list)
2112{
2113 struct kmod_elf *elf;
2114 struct kmod_modversion *symbols;
2115 int i, count, ret = 0;
2116
2117 if (mod == NULL || list == NULL)
2118 return -ENOENT;
2119
2120 assert(*list == NULL);
2121
2122 ret = kmod_module_get_elf(mod, &elf);
2123 if (ret)
2124 return ret;
2125
2126 count = kmod_elf_get_symbols(elf, &symbols);
2127 if (count < 0)
2128 return count;
2129
2130 for (i = 0; i < count; i++) {
2131 struct kmod_module_symbol *mv;
2132 struct kmod_list *n;
2133
2134 mv = kmod_module_symbols_new(symbols[i].crc, symbols[i].symbol);
2135 if (mv == NULL) {
2136 kmod_module_symbols_free_list(*list);
2137 *list = NULL;
2138 ret = -ENOMEM;
2139 goto list_error;
2140 }
2141
2142 n = kmod_list_append(*list, mv);
2143 if (n != NULL)
2144 *list = n;
2145 else {
2146 kmod_module_symbol_free(mv);
2147 kmod_module_symbols_free_list(*list);
2148 *list = NULL;
2149 ret = -ENOMEM;
2150 goto list_error;
2151 }
2152 }
2153 ret = count;
2154
2155list_error:
2156 free(symbols);
2157 return ret;
2158}
2159
2160KMOD_EXPORT const char *kmod_module_symbol_get_symbol(const struct kmod_list *entry)
2161{
2162 struct kmod_module_symbol *symbol;
2163
2164 if (entry == NULL || entry->data == NULL)
2165 return NULL;
2166
2167 symbol = entry->data;
2168 return symbol->symbol;
2169}
2170
2171KMOD_EXPORT uint64_t kmod_module_symbol_get_crc(const struct kmod_list *entry)
2172{
2173 struct kmod_module_symbol *symbol;
2174
2175 if (entry == NULL || entry->data == NULL)
2176 return 0;
2177
2178 symbol = entry->data;
2179 return symbol->crc;
2180}
2181
2182KMOD_EXPORT void kmod_module_symbols_free_list(struct kmod_list *list)
2183{
2184 kmod_list_release(list, kmod_module_symbol_free);
2185}
2186
2187struct kmod_module_dependency_symbol {
2188 uint64_t crc;
2189 uint8_t bind;
2190 char symbol[];
2191};
2192
2193// clang-format off
2194static struct kmod_module_dependency_symbol *kmod_module_dependency_symbols_new(uint64_t crc, uint8_t bind, const char *symbol)
2195// clang-format on
2196{
2197 struct kmod_module_dependency_symbol *mv;
2198 size_t symbollen = strlen(symbol) + 1;
2199
2200 mv = malloc(sizeof(struct kmod_module_dependency_symbol) + symbollen);
2201 if (mv == NULL)
2202 return NULL;
2203
2204 mv->crc = crc;
2205 mv->bind = bind;
2206 memcpy(mv->symbol, symbol, symbollen);
2207 return mv;
2208}
2209
2210static void kmod_module_dependency_symbol_free(
2211 struct kmod_module_dependency_symbol *dependency_symbol)
2212{
2213 free(dependency_symbol);
2214}
2215
2216KMOD_EXPORT int kmod_module_get_dependency_symbols(const struct kmod_module *mod,
2217 struct kmod_list **list)
2218{
2219 struct kmod_elf *elf;
2220 struct kmod_modversion *symbols;
2221 int i, count, ret = 0;
2222
2223 if (mod == NULL || list == NULL)
2224 return -ENOENT;
2225
2226 assert(*list == NULL);
2227
2228 ret = kmod_module_get_elf(mod, &elf);
2229 if (ret)
2230 return ret;
2231
2232 count = kmod_elf_get_dependency_symbols(elf, &symbols);
2233 if (count < 0)
2234 return count;
2235
2236 for (i = 0; i < count; i++) {
2237 struct kmod_module_dependency_symbol *mv;
2238 struct kmod_list *n;
2239
2240 mv = kmod_module_dependency_symbols_new(symbols[i].crc, symbols[i].bind,
2241 symbols[i].symbol);
2242 if (mv == NULL) {
2243 kmod_module_dependency_symbols_free_list(*list);
2244 *list = NULL;
2245 ret = -ENOMEM;
2246 goto list_error;
2247 }
2248
2249 n = kmod_list_append(*list, mv);
2250 if (n != NULL)
2251 *list = n;
2252 else {
2253 kmod_module_dependency_symbol_free(mv);
2254 kmod_module_dependency_symbols_free_list(*list);
2255 *list = NULL;
2256 ret = -ENOMEM;
2257 goto list_error;
2258 }
2259 }
2260 ret = count;
2261
2262list_error:
2263 free(symbols);
2264 return ret;
2265}
2266
2267// clang-format off
2268KMOD_EXPORT const char *kmod_module_dependency_symbol_get_symbol(const struct kmod_list *entry)
2269// clang-format on
2270{
2271 struct kmod_module_dependency_symbol *dependency_symbol;
2272
2273 if (entry == NULL || entry->data == NULL)
2274 return NULL;
2275
2276 dependency_symbol = entry->data;
2277 return dependency_symbol->symbol;
2278}
2279
2280KMOD_EXPORT uint64_t kmod_module_dependency_symbol_get_crc(const struct kmod_list *entry)
2281{
2282 struct kmod_module_dependency_symbol *dependency_symbol;
2283
2284 if (entry == NULL || entry->data == NULL)
2285 return 0;
2286
2287 dependency_symbol = entry->data;
2288 return dependency_symbol->crc;
2289}
2290
2291KMOD_EXPORT int kmod_module_dependency_symbol_get_bind(const struct kmod_list *entry)
2292{
2293 struct kmod_module_dependency_symbol *dependency_symbol;
2294
2295 if (entry == NULL || entry->data == NULL)
2296 return 0;
2297
2298 dependency_symbol = entry->data;
2299 return dependency_symbol->bind;
2300}
2301
2302KMOD_EXPORT void kmod_module_dependency_symbols_free_list(struct kmod_list *list)
2303{
2304 kmod_list_release(list, kmod_module_dependency_symbol_free);
2305}