]> git.ipfire.org Git - thirdparty/kmod.git/blame - libkmod/libkmod-module.c
ci: move compression variants further down
[thirdparty/kmod.git] / libkmod / libkmod-module.c
CommitLineData
b5a2cd07 1// SPDX-License-Identifier: LGPL-2.1-or-later
8f788d58 2/*
e6b0e49b 3 * Copyright (C) 2011-2013 ProFUSION embedded systems
8f788d58
LDM
4 */
5
7636e72b 6#include <assert.h>
8f788d58 7#include <ctype.h>
c2e4286b
LDM
8#include <dirent.h>
9#include <errno.h>
10#include <fnmatch.h>
8f788d58 11#include <inttypes.h>
f12ae3c4 12#include <limits.h>
c2e4286b
LDM
13#include <stdarg.h>
14#include <stddef.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
8f788d58 19#include <sys/mman.h>
c2e4286b 20#include <sys/stat.h>
144d1826 21#include <sys/syscall.h>
c2e4286b 22#include <sys/types.h>
eff917c0 23#include <sys/wait.h>
144d1826 24
b6b27d37 25#include <shared/strbuf.h>
96573a02
LDM
26#include <shared/util.h>
27
8f788d58 28#include "libkmod.h"
83b855a6 29#include "libkmod-internal.h"
8f788d58 30
fd44a98a 31enum kmod_module_builtin {
115bcd52
EV
32 KMOD_MODULE_BUILTIN_UNKNOWN,
33 KMOD_MODULE_BUILTIN_NO,
34 KMOD_MODULE_BUILTIN_YES,
fd44a98a
HJ
35};
36
8f788d58
LDM
37struct kmod_module {
38 struct kmod_ctx *ctx;
8bdeca11 39 char *hashkey;
219f9c38 40 char *name;
f1fb6f85 41 char *path;
7636e72b 42 struct kmod_list *dep;
bd3f5535 43 char *options;
115bcd52
EV
44 const char *install_commands; /* owned by kmod_config */
45 const char *remove_commands; /* owned by kmod_config */
6ad5f263 46 char *alias; /* only set if this module was created from an alias */
1eff942e 47 struct kmod_file *file;
bd3f5535 48 int refcount;
7636e72b
LDM
49 struct {
50 bool dep : 1;
bd3f5535
GSB
51 bool options : 1;
52 bool install_commands : 1;
53 bool remove_commands : 1;
7636e72b 54 } init;
b1a51256 55
fd44a98a
HJ
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
b1a51256
LDM
63 /*
64 * private field used by kmod_module_get_probe_list() to detect
65 * dependency loops
66 */
ece09aac 67 bool visited : 1;
89e92487
LDM
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;
3805274b 74
450bd1b4
MM
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;
8f788d58
LDM
81};
82
115bcd52 83static inline const char *path_join(const char *path, size_t prefixlen, char buf[PATH_MAX])
e18ad35c
GSB
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
af9572c6
DR
98static inline bool module_is_inkernel(struct kmod_module *mod)
99{
100 int state = kmod_module_get_initstate(mod);
3805274b 101
115bcd52 102 if (state == KMOD_MODULE_LIVE || state == KMOD_MODULE_BUILTIN)
af9572c6 103 return true;
3805274b
LDM
104
105 return false;
af9572c6
DR
106}
107
be728dd3 108void kmod_module_parse_depline(struct kmod_module *mod, char *line)
7636e72b
LDM
109{
110 struct kmod_ctx *ctx = mod->ctx;
111 struct kmod_list *list = NULL;
e18ad35c
GSB
112 const char *dirname;
113 char buf[PATH_MAX];
7636e72b 114 char *p, *saveptr;
be728dd3 115 size_t n = 0;
e18ad35c 116 size_t dirnamelen;
7636e72b 117
b6a534f7 118 if (mod->init.dep)
be728dd3 119 return;
b6a534f7 120 assert(mod->dep == NULL);
7636e72b
LDM
121 mod->init.dep = true;
122
123 p = strchr(line, ':');
124 if (p == NULL)
be728dd3 125 return;
7636e72b 126
671d4894 127 *p = '\0';
e18ad35c
GSB
128 dirname = kmod_get_dirname(mod->ctx);
129 dirnamelen = strlen(dirname);
6c5e7997 130 if (dirnamelen + 2 >= sizeof(buf))
be728dd3 131 return;
28c175ed 132
e18ad35c
GSB
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)
be728dd3 141 return;
e18ad35c
GSB
142 mod->path = strdup(str);
143 if (mod->path == NULL)
be728dd3 144 return;
e18ad35c 145 }
671d4894 146
7636e72b 147 p++;
7636e72b 148 for (p = strtok_r(p, " \t", &saveptr); p != NULL;
115bcd52 149 p = strtok_r(NULL, " \t", &saveptr)) {
d090fb3a 150 struct kmod_list *l_new;
01f9bc6d 151 struct kmod_module *depmod = NULL;
e18ad35c 152 const char *path;
be728dd3 153 int err;
e18ad35c
GSB
154
155 path = path_join(p, dirnamelen, buf);
156 if (path == NULL) {
115bcd52 157 ERR(ctx, "could not join path '%s' and '%s'.\n", dirname, p);
e18ad35c
GSB
158 goto fail;
159 }
7636e72b 160
e18ad35c 161 err = kmod_module_new_from_path(ctx, path, &depmod);
7636e72b 162 if (err < 0) {
115bcd52 163 ERR(ctx, "ctx=%p path=%s error=%s\n", ctx, path, strerror(-err));
7636e72b
LDM
164 goto fail;
165 }
166
e18ad35c 167 DBG(ctx, "add dep: %s\n", path);
7636e72b 168
d090fb3a
TS
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;
a0fc0594 175 n++;
7636e72b
LDM
176 }
177
be728dd3 178 DBG(ctx, "%zu dependencies for %s\n", n, mod->name);
7636e72b
LDM
179
180 mod->dep = list;
be728dd3 181 return;
7636e72b
LDM
182
183fail:
184 kmod_module_unref_list(list);
185 mod->init.dep = false;
7636e72b
LDM
186}
187
ece09aac
LDM
188void kmod_module_set_visited(struct kmod_module *mod, bool visited)
189{
190 mod->visited = visited;
191}
192
3805274b
LDM
193void kmod_module_set_builtin(struct kmod_module *mod, bool builtin)
194{
115bcd52 195 mod->builtin = builtin ? KMOD_MODULE_BUILTIN_YES : KMOD_MODULE_BUILTIN_NO;
3805274b
LDM
196}
197
450bd1b4
MM
198void kmod_module_set_required(struct kmod_module *mod, bool required)
199{
200 mod->required = required;
201}
202
fd44a98a
HJ
203bool kmod_module_is_builtin(struct kmod_module *mod)
204{
205 if (mod->builtin == KMOD_MODULE_BUILTIN_UNKNOWN) {
115bcd52
EV
206 kmod_module_set_builtin(mod, kmod_lookup_alias_is_builtin(mod->ctx,
207 mod->name));
fd44a98a
HJ
208 }
209
210 return mod->builtin == KMOD_MODULE_BUILTIN_YES;
211}
9c7f3ad0
LDM
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 */
52e20d50
EV
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)
9c7f3ad0
LDM
240{
241 struct kmod_module *m;
242 size_t keylen;
808eb4b8 243 int err;
9c7f3ad0
LDM
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));
9f02561d 257 if (m == NULL)
9c7f3ad0 258 return -ENOMEM;
9c7f3ad0
LDM
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;
808eb4b8
TS
276 err = kmod_pool_add_module(ctx, m, m->hashkey);
277 if (err < 0) {
278 free(m);
279 return err;
280 }
9c7f3ad0
LDM
281 *mod = m;
282
283 return 0;
284}
285
115bcd52
EV
286KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx, const char *name,
287 struct kmod_module **mod)
8f788d58 288{
d753b8ca 289 size_t namelen;
6daceb2f 290 char name_norm[PATH_MAX];
8f788d58 291
818f8e8a 292 if (ctx == NULL || name == NULL || mod == NULL)
8f788d58
LDM
293 return -ENOENT;
294
9c7f3ad0 295 modname_normalize(name, name_norm, &namelen);
113c66a5 296
9c7f3ad0 297 return kmod_module_new(ctx, name_norm, name_norm, namelen, NULL, 0, mod);
8f788d58
LDM
298}
299
115bcd52
EV
300int kmod_module_new_from_alias(struct kmod_ctx *ctx, const char *alias, const char *name,
301 struct kmod_module **mod)
6ad5f263 302{
6daceb2f 303 char key[PATH_MAX];
113c66a5
LDM
304 size_t namelen = strlen(name);
305 size_t aliaslen = strlen(alias);
6ad5f263 306
6c5e7997 307 if (namelen + aliaslen + 2 > sizeof(key))
113c66a5 308 return -ENAMETOOLONG;
6ad5f263 309
113c66a5
LDM
310 memcpy(key, name, namelen);
311 memcpy(key + namelen + 1, alias, aliaslen + 1);
9c7f3ad0 312 key[namelen] = '\\';
6ad5f263 313
4891b4b0 314 return kmod_module_new(ctx, key, name, namelen, alias, aliaslen, mod);
6ad5f263
LDM
315}
316
115bcd52
EV
317KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx, const char *path,
318 struct kmod_module **mod)
8f788d58
LDM
319{
320 struct kmod_module *m;
321 int err;
322 struct stat st;
6daceb2f 323 char name[PATH_MAX];
71e975cd 324 char *abspath;
d753b8ca 325 size_t namelen;
8f788d58 326
818f8e8a 327 if (ctx == NULL || path == NULL || mod == NULL)
8f788d58
LDM
328 return -ENOENT;
329
71e975cd 330 abspath = path_make_absolute_cwd(path);
b55df2ee
GSB
331 if (abspath == NULL) {
332 DBG(ctx, "no absolute path for %s\n", path);
71e975cd 333 return -ENOMEM;
b55df2ee 334 }
71e975cd
LDM
335
336 err = stat(abspath, &st);
337 if (err < 0) {
b55df2ee 338 err = -errno;
fb0e59a1 339 DBG(ctx, "stat %s: %m\n", path);
71e975cd 340 free(abspath);
b55df2ee 341 return err;
71e975cd 342 }
8f788d58 343
973c80ba 344 if (path_to_modname(path, name, &namelen) == NULL) {
b55df2ee 345 DBG(ctx, "could not get modname from path %s\n", path);
973c80ba
GSB
346 free(abspath);
347 return -ENOENT;
348 }
d753b8ca 349
e19338da
TS
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)
4e391ac9 356 m->path = abspath;
e19338da
TS
357 else if (streq(m->path, abspath))
358 free(abspath);
359 else {
2043c657 360 kmod_module_unref(m);
e19338da
TS
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;
c1bc88c9 366 }
788ef0f7 367
4e391ac9 368 m->builtin = KMOD_MODULE_BUILTIN_NO;
8f788d58
LDM
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
4084c176 384 kmod_pool_del_module(mod->ctx, mod, mod->hashkey);
7636e72b 385 kmod_module_unref_list(mod->dep);
1eff942e
LDM
386
387 if (mod->file)
388 kmod_file_unref(mod->file);
389
8f788d58 390 kmod_unref(mod->ctx);
bd3f5535 391 free(mod->options);
f1fb6f85 392 free(mod->path);
8f788d58
LDM
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
115bcd52
EV
407typedef _nonnull_all_ int (*lookup_func)(struct kmod_ctx *ctx, const char *name,
408 struct kmod_list **list);
82972710
LDM
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}
b14dcfda 428
115bcd52
EV
429KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx, const char *given_alias,
430 struct kmod_list **list)
7f3eb0cc 431{
efc2e4b4 432 static const lookup_func lookup[] = {
82972710
LDM
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 };
6daceb2f 441 char alias[PATH_MAX];
82972710 442 int err;
7f3eb0cc 443
4308b176 444 if (ctx == NULL || given_alias == NULL)
7f3eb0cc
LDM
445 return -ENOENT;
446
7f3eb0cc
LDM
447 if (list == NULL || *list != NULL) {
448 ERR(ctx, "An empty list is needed to create lookup\n");
449 return -ENOSYS;
450 }
451
b55df2ee
GSB
452 if (alias_normalize(given_alias, alias, NULL) < 0) {
453 DBG(ctx, "invalid alias: %s\n", given_alias);
d470db10 454 return -EINVAL;
b55df2ee
GSB
455 }
456
457 DBG(ctx, "input alias=%s, normalized=%s\n", given_alias, alias);
d917f274 458
115bcd52 459 err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup), alias, list);
7afc98a1 460
82972710 461 DBG(ctx, "lookup=%s found=%d\n", alias, err >= 0 && *list);
89443220 462
82972710
LDM
463 if (err < 0) {
464 kmod_module_unref_list(*list);
465 *list = NULL;
466 }
b866b216 467
84f42204 468 return err;
7f3eb0cc 469}
b14dcfda 470
9becaaea
LDM
471KMOD_EXPORT int kmod_module_new_from_name_lookup(struct kmod_ctx *ctx,
472 const char *modname,
473 struct kmod_module **mod)
474{
efc2e4b4 475 static const lookup_func lookup[] = {
9becaaea
LDM
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
115bcd52
EV
491 err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup), name_norm,
492 &list);
9becaaea
LDM
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
7f3eb0cc
LDM
504KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list)
505{
63aec609 506 kmod_list_release(list, kmod_module_unref);
7f3eb0cc
LDM
507
508 return 0;
509}
510
0d46743c 511KMOD_EXPORT int kmod_module_get_filtered_blacklist(const struct kmod_ctx *ctx,
115bcd52
EV
512 const struct kmod_list *input,
513 struct kmod_list **output)
0d46743c 514{
d80b103c 515 return kmod_module_apply_filter(ctx, KMOD_FILTER_BLACKLIST, input, output);
0d46743c
LDM
516}
517
6ac1bccf 518static void module_get_dependencies_noref(struct kmod_module *mod)
b72f74b5
LDM
519{
520 if (!mod->init.dep) {
521 /* lazy init */
522 char *line = kmod_search_moddep(mod->ctx, mod->name);
523
be728dd3 524 if (line != NULL) {
6ac1bccf 525 kmod_module_parse_depline(mod, line);
be728dd3
TS
526 free(line);
527 }
b72f74b5 528 }
b72f74b5
LDM
529}
530
f1cd799f 531KMOD_EXPORT struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod)
0835fc3b 532{
f1cd799f
LDM
533 struct kmod_list *l, *l_new, *list_new = NULL;
534
535 if (mod == NULL)
536 return NULL;
537
6ac1bccf 538 module_get_dependencies_noref((struct kmod_module *)mod);
f1cd799f
LDM
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;
0835fc3b
LDM
556}
557
ad4d1ae5 558KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *entry)
6e869df7 559{
ad4d1ae5
GSB
560 if (entry == NULL)
561 return NULL;
28c175ed 562
ad4d1ae5 563 return kmod_module_ref(entry->data);
6e869df7
LDM
564}
565
1ce08a56 566KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
6e869df7 567{
818f8e8a
LDM
568 if (mod == NULL)
569 return NULL;
570
6e869df7
LDM
571 return mod->name;
572}
573
1ce08a56 574KMOD_EXPORT const char *kmod_module_get_path(const struct kmod_module *mod)
6e869df7 575{
818f8e8a
LDM
576 if (mod == NULL)
577 return NULL;
578
d01c67e3 579 DBG(mod->ctx, "name='%s' path='%s'\n", mod->name, mod->path);
c5e7b1f7 580
e005facd
LDM
581 if (mod->path != NULL)
582 return mod->path;
583 if (mod->init.dep)
584 return NULL;
c5e7b1f7 585
e005facd 586 /* lazy init */
6ac1bccf 587 module_get_dependencies_noref((struct kmod_module *)mod);
c5e7b1f7 588
6e869df7
LDM
589 return mod->path;
590}
591
8f788d58
LDM
592extern long delete_module(const char *name, unsigned int flags);
593
115bcd52 594KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod, unsigned int flags)
8f788d58 595{
3a92fc63
LDM
596 unsigned int libkmod_flags = flags & 0xff;
597
8f788d58 598 int err;
8f788d58
LDM
599
600 if (mod == NULL)
601 return -ENOENT;
602
7ab88044
LDM
603 /* Filter out other flags and force ONONBLOCK */
604 flags &= KMOD_REMOVE_FORCE;
605 flags |= KMOD_REMOVE_NOWAIT;
8f788d58 606
d753b8ca 607 err = delete_module(mod->name, flags);
8f788d58 608 if (err != 0) {
ba998b9c 609 err = -errno;
3a92fc63
LDM
610 if (!(libkmod_flags & KMOD_REMOVE_NOLOG))
611 ERR(mod->ctx, "could not remove '%s': %m\n", mod->name);
8f788d58
LDM
612 }
613
ba998b9c 614 return err;
8f788d58
LDM
615}
616
708624a4 617extern long init_module(const void *mem, unsigned long len, const char *args);
8f788d58 618
115bcd52 619static int do_finit_module(struct kmod_module *mod, unsigned int flags, const char *args)
e1f0e169 620{
09c9f8c5 621 enum kmod_file_compression_type compression, kernel_compression;
e1f0e169
LDM
622 unsigned int kernel_flags = 0;
623 int err;
624
625 /*
09c9f8c5
LDM
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
fcc367f9 628 * in userspace. Otherwise, reuse ENOSYS to trigger the same fallback
09c9f8c5 629 * as when finit_module() is not supported.
e1f0e169 630 */
09c9f8c5
LDM
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))
e1f0e169
LDM
635 return -ENOSYS;
636
09c9f8c5
LDM
637 if (compression != KMOD_FILE_COMPRESSION_NONE)
638 kernel_flags |= MODULE_INIT_COMPRESSED_FILE;
639
e1f0e169
LDM
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
115bcd52 652static int do_init_module(struct kmod_module *mod, unsigned int flags, const char *args)
e1f0e169 653{
1c8fae2f 654 _cleanup_free_ const void *stripped = NULL;
e1f0e169
LDM
655 struct kmod_elf *elf;
656 const void *mem;
657 off_t size;
658 int err;
659
e1f0e169 660 if (flags & (KMOD_INSERT_FORCE_VERMAGIC | KMOD_INSERT_FORCE_MODVERSION)) {
5cd2a2a4
EV
661 err = kmod_file_get_elf(mod->file, &elf);
662 if (err)
e1f0e169 663 return err;
e1f0e169 664
132eb4ca
EV
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;
e1f0e169 670 }
386acb3f 671 mem = stripped;
e1f0e169 672 } else {
8cc475f7
EV
673 err = kmod_file_load_contents(mod->file);
674 if (err)
675 return err;
676
e1f0e169
LDM
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
115bcd52
EV
688KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod, unsigned int flags,
689 const char *options)
8f788d58
LDM
690{
691 int err;
708624a4 692 const char *path;
3a721bbc 693 const char *args = options ? options : "";
8f788d58
LDM
694
695 if (mod == NULL)
696 return -ENOENT;
697
708624a4
GSB
698 path = kmod_module_get_path(mod);
699 if (path == NULL) {
b787b569 700 ERR(mod->ctx, "could not find module by name='%s'\n", mod->name);
114ec87c 701 return -ENOENT;
8f788d58
LDM
702 }
703
b1982674 704 if (!mod->file) {
5cd2a2a4
EV
705 err = kmod_file_open(mod->ctx, path, &mod->file);
706 if (err)
b1982674 707 return err;
8f788d58
LDM
708 }
709
e1f0e169
LDM
710 err = do_finit_module(mod, flags, args);
711 if (err == -ENOSYS)
712 err = do_init_module(mod, flags, args);
708624a4 713
e1f0e169 714 if (err < 0)
115bcd52 715 INFO(mod->ctx, "Failed to insert module '%s': %s\n", path, strerror(-err));
708624a4 716
8f788d58
LDM
717 return err;
718}
f12ae3c4 719
0bc8f2e7 720static bool module_is_blacklisted(const struct kmod_module *mod)
ddbda022 721{
0bc8f2e7 722 const struct kmod_ctx *ctx = mod->ctx;
e7fc2c86
LDM
723 const struct kmod_config *config = kmod_get_config(ctx);
724 const struct kmod_list *bl = config->blacklists;
ddbda022
LDM
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
d80b103c 737KMOD_EXPORT int kmod_module_apply_filter(const struct kmod_ctx *ctx,
115bcd52
EV
738 enum kmod_filter filter_type,
739 const struct kmod_list *input,
740 struct kmod_list **output)
d80b103c
DR
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
115bcd52 755 if ((filter_type & KMOD_FILTER_BLACKLIST) && module_is_blacklisted(mod))
d80b103c
DR
756 continue;
757
115bcd52 758 if ((filter_type & KMOD_FILTER_BUILTIN) && kmod_module_is_builtin(mod))
d80b103c
DR
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
115bcd52 777static int command_do(struct kmod_module *mod, const char *type, const char *cmd)
ddbda022
LDM
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
81dbf2be 788 if (err == -1) {
115bcd52
EV
789 ERR(mod->ctx, "Could not run %s command '%s' for module %s: %m\n", type,
790 cmd, modname);
81dbf2be 791 return -EINVAL;
ddbda022
LDM
792 }
793
81dbf2be
TM
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;
ddbda022
LDM
801}
802
b1a51256
LDM
803struct probe_insert_cb {
804 int (*run_install)(struct kmod_module *m, const char *cmd, void *data);
805 void *data;
806};
807
115bcd52
EV
808static int module_do_install_commands(struct kmod_module *mod, const char *options,
809 struct probe_insert_cb *cb)
ddbda022
LDM
810{
811 const char *command = kmod_module_get_install_commands(mod);
9f02561d
LDM
812 char *p;
813 _cleanup_free_ char *cmd;
ddbda022
LDM
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);
723bdadc 824 varlen = strlen("$CMDLINE_OPTS");
ddbda022
LDM
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;
28ba117f 835 _clang_suppress_alloc_ char *s = malloc(slen + 1);
9f02561d 836 if (!s)
ddbda022 837 return -ENOMEM;
9f02561d 838
ddbda022
LDM
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
ddbda022
LDM
854 return err;
855}
856
ddbda022
LDM
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
115bcd52
EV
883static int __kmod_module_get_probe_list(struct kmod_module *mod, bool required,
884 bool ignorecmd, struct kmod_list **list);
b1a51256
LDM
885
886/* re-entrant */
115bcd52 887static int __kmod_module_fill_softdep(struct kmod_module *mod, struct kmod_list **list)
ddbda022 888{
b1a51256 889 struct kmod_list *pre = NULL, *post = NULL, *l;
ddbda022 890 int err;
ddbda022 891
b1a51256
LDM
892 err = kmod_module_get_softdeps(mod, &pre, &post);
893 if (err < 0) {
115bcd52 894 ERR(mod->ctx, "could not get softdep: %s\n", strerror(-err));
b1a51256 895 goto fail;
ddbda022
LDM
896 }
897
b1a51256
LDM
898 kmod_list_foreach(l, pre) {
899 struct kmod_module *m = l->data;
450bd1b4 900 err = __kmod_module_get_probe_list(m, false, false, list);
b1a51256
LDM
901 if (err < 0)
902 goto fail;
903 }
ddbda022 904
b1a51256
LDM
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;
ddbda022 910 }
b1a51256 911 *list = l;
89e92487 912 mod->ignorecmd = (pre != NULL || post != NULL);
ddbda022 913
b1a51256
LDM
914 kmod_list_foreach(l, post) {
915 struct kmod_module *m = l->data;
450bd1b4 916 err = __kmod_module_get_probe_list(m, false, false, list);
b1a51256
LDM
917 if (err < 0)
918 goto fail;
919 }
ddbda022 920
b1a51256
LDM
921fail:
922 kmod_module_unref_list(pre);
923 kmod_module_unref_list(post);
ddbda022 924
b1a51256
LDM
925 return err;
926}
ddbda022 927
b1a51256 928/* re-entrant */
115bcd52
EV
929static int __kmod_module_get_probe_list(struct kmod_module *mod, bool required,
930 bool ignorecmd, struct kmod_list **list)
b1a51256
LDM
931{
932 struct kmod_list *dep, *l;
933 int err = 0;
ddbda022 934
b1a51256 935 if (mod->visited) {
115bcd52 936 DBG(mod->ctx, "Ignore module '%s': already visited\n", mod->name);
b1a51256
LDM
937 return 0;
938 }
8cd0f9e4 939 mod->visited = true;
ddbda022 940
b1a51256 941 dep = kmod_module_get_dependencies(mod);
450bd1b4
MM
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
b1a51256
LDM
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)
89e92487 959 goto finish;
b1a51256 960 }
ddbda022 961
89e92487
LDM
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
ddbda022 974finish:
b1a51256
LDM
975 kmod_module_unref_list(dep);
976 return err;
977}
978
115bcd52
EV
979static int kmod_module_get_probe_list(struct kmod_module *mod, bool ignorecmd,
980 struct kmod_list **list)
b1a51256
LDM
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);
450bd1b4 991 kmod_set_modules_required(mod->ctx, false);
b1a51256 992
450bd1b4 993 err = __kmod_module_get_probe_list(mod, true, ignorecmd, list);
b1a51256
LDM
994 if (err < 0) {
995 kmod_module_unref_list(*list);
996 *list = NULL;
997 }
ddbda022
LDM
998
999 return err;
1000}
1001
115bcd52
EV
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))
ddbda022 1007{
b1a51256 1008 struct kmod_list *list = NULL, *l;
ddbda022 1009 struct probe_insert_cb cb;
b1a51256
LDM
1010 int err;
1011
1012 if (mod == NULL)
1013 return -ENOENT;
1014
115bcd52 1015 if (!(flags & KMOD_PROBE_IGNORE_LOADED) && module_is_inkernel(mod)) {
814a57ba 1016 if (flags & KMOD_PROBE_FAIL_ON_LOADED)
af9572c6
DR
1017 return -EEXIST;
1018 else
1019 return 0;
1020 }
1021
6bfd74a9
EV
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;
b1a51256
LDM
1031 }
1032
115bcd52
EV
1033 err = kmod_module_get_probe_list(mod, !!(flags & KMOD_PROBE_IGNORE_COMMAND),
1034 &list);
b1a51256
LDM
1035 if (err < 0)
1036 return err;
1037
1038 if (flags & KMOD_PROBE_APPLY_BLACKLIST_ALL) {
1039 struct kmod_list *filtered = NULL;
1040
115bcd52
EV
1041 err = kmod_module_apply_filter(mod->ctx, KMOD_FILTER_BLACKLIST, list,
1042 &filtered);
b1a51256
LDM
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 }
ddbda022
LDM
1052
1053 cb.run_install = run_install;
115bcd52 1054 cb.data = (void *)data;
ddbda022 1055
b1a51256
LDM
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);
abd5557b
LDM
1060 char *options;
1061
115bcd52
EV
1062 if (!(flags & KMOD_PROBE_IGNORE_LOADED) && module_is_inkernel(m)) {
1063 DBG(mod->ctx, "Ignoring module '%s': already loaded\n", m->name);
abd5557b
LDM
1064 err = -EEXIST;
1065 goto finish_module;
1066 }
1067
115bcd52
EV
1068 options =
1069 module_options_concat(moptions, m == mod ? extra_options : NULL);
b1a51256 1070
89e92487 1071 if (cmd != NULL && !m->ignorecmd) {
6bd0713d
LDM
1072 if (print_action != NULL)
1073 print_action(m, true, options ?: "");
1074
4c1ffb75 1075 if (!(flags & KMOD_PROBE_DRY_RUN))
115bcd52 1076 err = module_do_install_commands(m, options, &cb);
b1a51256 1077 } else {
6bd0713d
LDM
1078 if (print_action != NULL)
1079 print_action(m, false, options ?: "");
1080
4c1ffb75 1081 if (!(flags & KMOD_PROBE_DRY_RUN))
115bcd52 1082 err = kmod_module_insert_module(m, flags, options);
b1a51256
LDM
1083 }
1084
1085 free(options);
1086
abd5557b 1087finish_module:
b1a51256 1088 /*
5f351473 1089 * Treat "already loaded" error. If we were told to stop on
3bc92e89
LDM
1090 * already loaded and the module being loaded is not a softdep
1091 * or dep, bail out. Otherwise, just ignore and continue.
5f351473
LDM
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.
b1a51256 1097 */
115bcd52 1098 if (err == -EEXIST && m == mod && (flags & KMOD_PROBE_FAIL_ON_LOADED))
5f351473 1099 break;
5f351473 1100
450bd1b4
MM
1101 /*
1102 * Ignore errors from softdeps
1103 */
1104 if (err == -EEXIST || !m->required)
3bc92e89 1105 err = 0;
450bd1b4 1106
3bc92e89 1107 else if (err < 0)
b1a51256
LDM
1108 break;
1109 }
ddbda022 1110
b1a51256
LDM
1111 kmod_module_unref_list(list);
1112 return err;
1113}
ddbda022 1114
49ce6d07
LDM
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;
e7fc2c86
LDM
1123 const struct kmod_list *l;
1124 const struct kmod_config *config;
49ce6d07
LDM
1125 char *opts = NULL;
1126 size_t optslen = 0;
1127
e7fc2c86 1128 config = kmod_get_config(mod->ctx);
49ce6d07 1129
e7fc2c86 1130 kmod_list_foreach(l, config->options) {
49ce6d07
LDM
1131 const char *modname = kmod_option_get_modname(l);
1132 const char *str;
1133 size_t len;
1134 void *tmp;
1135
115bcd52
EV
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))))
49ce6d07
LDM
1140 continue;
1141
115bcd52
EV
1142 DBG(mod->ctx, "passed = modname=%s mod->name=%s mod->alias=%s\n",
1143 modname, mod->name, mod->alias);
49ce6d07
LDM
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;
e7fc2c86
LDM
1186 const struct kmod_list *l;
1187 const struct kmod_config *config;
49ce6d07 1188
e7fc2c86 1189 config = kmod_get_config(mod->ctx);
49ce6d07 1190
e7fc2c86 1191 kmod_list_foreach(l, config->install_commands) {
49ce6d07 1192 const char *modname = kmod_command_get_modname(l);
49ce6d07 1193
a6bf2495 1194 if (fnmatch(modname, mod->name, 0) != 0)
49ce6d07
LDM
1195 continue;
1196
60f6760e 1197 m->install_commands = kmod_command_get_command(l);
49ce6d07 1198
60f6760e
LDM
1199 /*
1200 * find only the first command, as modprobe from
1201 * module-init-tools does
1202 */
1203 break;
49ce6d07
LDM
1204 }
1205
1206 m->init.install_commands = true;
49ce6d07
LDM
1207 }
1208
1209 return mod->install_commands;
49ce6d07
LDM
1210}
1211
f4fc5523
LDM
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
115bcd52
EV
1218static struct kmod_list *lookup_dep(struct kmod_ctx *ctx, const char *const *array,
1219 unsigned int count)
1c522600
GSB
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) {
115bcd52
EV
1231 ERR(ctx, "failed to lookup dependency '%s', continuing anyway.\n",
1232 depname);
1c522600
GSB
1233 continue;
1234 } else if (lst != NULL)
1235 ret = kmod_list_append_list(ret, lst);
1236 }
1237 return ret;
1238}
1239
2bd7cbf6 1240KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod,
115bcd52 1241 struct kmod_list **pre, struct kmod_list **post)
1c522600 1242{
e7fc2c86
LDM
1243 const struct kmod_list *l;
1244 const struct kmod_config *config;
1c522600
GSB
1245
1246 if (mod == NULL || pre == NULL || post == NULL)
1247 return -ENOENT;
1248
1249 assert(*pre == NULL);
1250 assert(*post == NULL);
1251
e7fc2c86 1252 config = kmod_get_config(mod->ctx);
1c522600 1253
e7fc2c86 1254 kmod_list_foreach(l, config->softdeps) {
2bd7cbf6 1255 const char *modname = kmod_softdep_get_name(l);
115bcd52 1256 const char *const *array;
2bd7cbf6 1257 unsigned count;
1c522600 1258
2bd7cbf6
LDM
1259 if (fnmatch(modname, mod->name, 0) != 0)
1260 continue;
1c522600 1261
2bd7cbf6 1262 array = kmod_softdep_get_pre(l, &count);
05828b4a 1263 *pre = lookup_dep(mod->ctx, array, count);
2bd7cbf6 1264 array = kmod_softdep_get_post(l, &count);
05828b4a
JITM
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
05828b4a 1277KMOD_EXPORT int kmod_module_get_weakdeps(const struct kmod_module *mod,
115bcd52 1278 struct kmod_list **weak)
05828b4a
JITM
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);
115bcd52 1292 const char *const *array;
05828b4a
JITM
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);
1c522600 1300
2bd7cbf6
LDM
1301 /*
1302 * find only the first command, as modprobe from
1303 * module-init-tools does
1304 */
1305 break;
1c522600
GSB
1306 }
1307
1308 return 0;
1c522600
GSB
1309}
1310
49ce6d07
LDM
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;
e7fc2c86
LDM
1319 const struct kmod_list *l;
1320 const struct kmod_config *config;
49ce6d07 1321
e7fc2c86 1322 config = kmod_get_config(mod->ctx);
49ce6d07 1323
e7fc2c86 1324 kmod_list_foreach(l, config->remove_commands) {
49ce6d07 1325 const char *modname = kmod_command_get_modname(l);
49ce6d07 1326
a6bf2495 1327 if (fnmatch(modname, mod->name, 0) != 0)
49ce6d07
LDM
1328 continue;
1329
60f6760e 1330 m->remove_commands = kmod_command_get_command(l);
49ce6d07 1331
60f6760e
LDM
1332 /*
1333 * find only the first command, as modprobe from
1334 * module-init-tools does
1335 */
1336 break;
49ce6d07
LDM
1337 }
1338
1339 m->init.remove_commands = true;
49ce6d07
LDM
1340 }
1341
1342 return mod->remove_commands;
49ce6d07
LDM
1343}
1344
f4fc5523
LDM
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
115bcd52 1351KMOD_EXPORT int kmod_module_new_from_loaded(struct kmod_ctx *ctx, struct kmod_list **list)
49ce6d07
LDM
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
79e5ea91 1360 fp = fopen("/proc/modules", "re");
49ce6d07
LDM
1361 if (fp == NULL) {
1362 int err = -errno;
fb0e59a1 1363 ERR(ctx, "could not open /proc/modules: %m\n");
49ce6d07
LDM
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;
2206d7f7 1371 size_t len = strlen(line);
49ce6d07
LDM
1372 char *saveptr, *name = strtok_r(line, " \t", &saveptr);
1373
1374 err = kmod_module_new_from_name(ctx, name, &m);
1375 if (err < 0) {
115bcd52
EV
1376 ERR(ctx, "could not get module from name '%s': %s\n", name,
1377 strerror(-err));
2206d7f7 1378 goto eat_line;
49ce6d07
LDM
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 }
2206d7f7 1388eat_line:
aad7c697 1389 while (len > 0 && line[len - 1] != '\n' && fgets(line, sizeof(line), fp))
2206d7f7 1390 len = strlen(line);
49ce6d07
LDM
1391 }
1392
1393 fclose(fp);
1394 *list = l;
1395
1396 return 0;
1397}
1398
f12ae3c4
GSB
1399KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate state)
1400{
7bede7b6
DR
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 }
f12ae3c4
GSB
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
818f8e8a
LDM
1420 if (mod == NULL)
1421 return -ENOENT;
1422
fd44a98a
HJ
1423 /* remove const: this can only change internal state */
1424 if (kmod_module_is_builtin((struct kmod_module *)mod))
3805274b
LDM
1425 return KMOD_MODULE_BUILTIN;
1426
115bcd52 1427 pathlen = snprintf(path, sizeof(path), "/sys/module/%s/initstate", mod->name);
badacf76
DA
1428 if (pathlen >= (int)sizeof(path)) {
1429 /* Too long path was truncated */
1430 return -ENAMETOOLONG;
1431 }
115bcd52 1432 fd = open(path, O_RDONLY | O_CLOEXEC);
f12ae3c4
GSB
1433 if (fd < 0) {
1434 err = -errno;
fb0e59a1 1435 DBG(mod->ctx, "could not open '%s': %m\n", path);
ddbda022 1436
723bdadc 1437 if (pathlen > (int)strlen("/initstate")) {
f12ae3c4 1438 struct stat st;
723bdadc 1439 path[pathlen - strlen("/initstate")] = '\0';
f12ae3c4 1440 if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
fd44a98a 1441 return KMOD_MODULE_COMING;
f12ae3c4 1442
428ed42c 1443 err = -errno;
fb0e59a1 1444 DBG(mod->ctx, "could not open '%s': %m\n", path);
428ed42c 1445 }
f12ae3c4
GSB
1446 return err;
1447 }
1448
1449 err = read_str_safe(fd, buf, sizeof(buf));
1450 close(fd);
1451 if (err < 0) {
115bcd52 1452 ERR(mod->ctx, "could not read from '%s': %s\n", path, strerror(-err));
f12ae3c4
GSB
1453 return err;
1454 }
1455
877e80cd 1456 if (streq(buf, "live\n"))
f12ae3c4 1457 return KMOD_MODULE_LIVE;
877e80cd 1458 else if (streq(buf, "coming\n"))
f12ae3c4 1459 return KMOD_MODULE_COMING;
877e80cd 1460 else if (streq(buf, "going\n"))
f12ae3c4
GSB
1461 return KMOD_MODULE_GOING;
1462
1463 ERR(mod->ctx, "unknown %s: '%s'\n", path, buf);
1464 return -EINVAL;
1465}
1466
2d7bab5c
LDM
1467KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
1468{
2d7bab5c
LDM
1469 FILE *fp;
1470 char line[4096];
1471 int lineno = 0;
1472 long size = -ENOENT;
486f9013 1473 int dfd, cfd;
2d7bab5c
LDM
1474
1475 if (mod == NULL)
1476 return -ENOENT;
1477
486f9013
DR
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);
115bcd52 1483 dfd = open(line, O_RDONLY | O_CLOEXEC);
486f9013
DR
1484 if (dfd < 0)
1485 return -errno;
1486
1487 /* available as of linux 3.3.x */
115bcd52 1488 cfd = openat(dfd, "coresize", O_RDONLY | O_CLOEXEC);
486f9013
DR
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 */
79e5ea91 1497 fp = fopen("/proc/modules", "re");
2d7bab5c
LDM
1498 if (fp == NULL) {
1499 int err = -errno;
fb0e59a1 1500 ERR(mod->ctx, "could not open /proc/modules: %m\n");
30bfd48a 1501 close(dfd);
2d7bab5c
LDM
1502 return err;
1503 }
1504
1505 while (fgets(line, sizeof(line), fp)) {
2206d7f7 1506 size_t len = strlen(line);
2d7bab5c
LDM
1507 char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
1508 long value;
1509
1510 lineno++;
1511 if (tok == NULL || !streq(tok, mod->name))
2206d7f7 1512 goto eat_line;
2d7bab5c
LDM
1513
1514 tok = strtok_r(NULL, " \t", &saveptr);
1515 if (tok == NULL) {
115bcd52 1516 ERR(mod->ctx, "invalid line format at /proc/modules:%d\n", lineno);
2d7bab5c
LDM
1517 break;
1518 }
1519
dcd652b5 1520 errno = 0;
2d7bab5c 1521 value = strtol(tok, &endptr, 10);
dcd652b5 1522 if (endptr == tok || *endptr != '\0' || errno == ERANGE || value < 0) {
115bcd52 1523 ERR(mod->ctx, "invalid line format at /proc/modules:%d\n", lineno);
2d7bab5c
LDM
1524 break;
1525 }
1526
1527 size = value;
1528 break;
2206d7f7 1529eat_line:
213508a6 1530 while (len > 0 && line[len - 1] != '\n' && fgets(line, sizeof(line), fp))
2206d7f7 1531 len = strlen(line);
2d7bab5c
LDM
1532 }
1533 fclose(fp);
486f9013
DR
1534
1535done:
1536 close(dfd);
2d7bab5c
LDM
1537 return size;
1538}
1539
f12ae3c4
GSB
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
818f8e8a
LDM
1546 if (mod == NULL)
1547 return -ENOENT;
1548
f12ae3c4 1549 snprintf(path, sizeof(path), "/sys/module/%s/refcnt", mod->name);
115bcd52 1550 fd = open(path, O_RDONLY | O_CLOEXEC);
f12ae3c4
GSB
1551 if (fd < 0) {
1552 err = -errno;
fb0e59a1 1553 DBG(mod->ctx, "could not open '%s': %m\n", path);
f12ae3c4
GSB
1554 return err;
1555 }
1556
1557 err = read_str_long(fd, &refcnt, 10);
1558 close(fd);
1559 if (err < 0) {
115bcd52
EV
1560 ERR(mod->ctx, "could not read integer from '%s': '%s'\n", path,
1561 strerror(-err));
f12ae3c4
GSB
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;
7e0385c4 1572 struct dirent *dent;
f12ae3c4 1573 DIR *d;
f12ae3c4 1574
b9a7da39 1575 if (mod == NULL || mod->ctx == NULL)
f12ae3c4 1576 return NULL;
818f8e8a 1577
f12ae3c4
GSB
1578 snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name);
1579
1580 d = opendir(dname);
1581 if (d == NULL) {
fb0e59a1 1582 ERR(mod->ctx, "could not open '%s': %m\n", dname);
f12ae3c4
GSB
1583 return NULL;
1584 }
1585
7e0385c4 1586 for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
f12ae3c4 1587 struct kmod_module *holder;
53886ddd 1588 struct kmod_list *l;
f12ae3c4
GSB
1589 int err;
1590
7e0385c4
LDM
1591 if (dent->d_name[0] == '.') {
1592 if (dent->d_name[1] == '\0' ||
1593 (dent->d_name[1] == '.' && dent->d_name[2] == '\0'))
f12ae3c4
GSB
1594 continue;
1595 }
1596
115bcd52 1597 err = kmod_module_new_from_name(mod->ctx, dent->d_name, &holder);
f12ae3c4
GSB
1598 if (err < 0) {
1599 ERR(mod->ctx, "could not create module for '%s': %s\n",
115bcd52 1600 dent->d_name, strerror(-err));
53886ddd 1601 goto fail;
f12ae3c4
GSB
1602 }
1603
53886ddd
LDM
1604 l = kmod_list_append(list, holder);
1605 if (l != NULL) {
1606 list = l;
1607 } else {
f12ae3c4
GSB
1608 ERR(mod->ctx, "out of memory\n");
1609 kmod_module_unref(holder);
53886ddd 1610 goto fail;
f12ae3c4
GSB
1611 }
1612 }
1613
1614 closedir(d);
1615 return list;
53886ddd
LDM
1616
1617fail:
1618 closedir(d);
1619 kmod_module_unref_list(list);
1620 return NULL;
f12ae3c4
GSB
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;
7e0385c4 1637 struct dirent *dent;
f12ae3c4
GSB
1638 DIR *d;
1639 int dfd;
f12ae3c4
GSB
1640
1641 if (mod == NULL)
1642 return NULL;
28c175ed 1643
f12ae3c4
GSB
1644 snprintf(dname, sizeof(dname), "/sys/module/%s/sections", mod->name);
1645
1646 d = opendir(dname);
1647 if (d == NULL) {
fb0e59a1 1648 ERR(mod->ctx, "could not open '%s': %m\n", dname);
f12ae3c4
GSB
1649 return NULL;
1650 }
1651
1652 dfd = dirfd(d);
40923bdb 1653
7e0385c4 1654 for (dent = readdir(d); dent; dent = readdir(d)) {
f12ae3c4 1655 struct kmod_module_section *section;
40923bdb 1656 struct kmod_list *l;
f12ae3c4
GSB
1657 unsigned long address;
1658 size_t namesz;
1659 int fd, err;
1660
7e0385c4
LDM
1661 if (dent->d_name[0] == '.') {
1662 if (dent->d_name[1] == '\0' ||
1663 (dent->d_name[1] == '.' && dent->d_name[2] == '\0'))
f12ae3c4
GSB
1664 continue;
1665 }
1666
115bcd52 1667 fd = openat(dfd, dent->d_name, O_RDONLY | O_CLOEXEC);
f12ae3c4 1668 if (fd < 0) {
115bcd52 1669 ERR(mod->ctx, "could not open '%s/%s': %m\n", dname, dent->d_name);
40923bdb 1670 goto fail;
f12ae3c4
GSB
1671 }
1672
1673 err = read_str_ulong(fd, &address, 16);
40923bdb 1674 close(fd);
f12ae3c4 1675 if (err < 0) {
a0bac391
EV
1676 ERR(mod->ctx, "could not read long from '%s/%s': %s\n", dname,
1677 dent->d_name, strerror(-err));
40923bdb
LDM
1678 goto fail;
1679 }
1680
7e0385c4 1681 namesz = strlen(dent->d_name) + 1;
40923bdb
LDM
1682 section = malloc(sizeof(*section) + namesz);
1683
1684 if (section == NULL) {
1685 ERR(mod->ctx, "out of memory\n");
1686 goto fail;
f12ae3c4
GSB
1687 }
1688
f12ae3c4 1689 section->address = address;
7e0385c4 1690 memcpy(section->name, dent->d_name, namesz);
f12ae3c4 1691
40923bdb
LDM
1692 l = kmod_list_append(list, section);
1693 if (l != NULL) {
1694 list = l;
1695 } else {
f12ae3c4
GSB
1696 ERR(mod->ctx, "out of memory\n");
1697 free(section);
40923bdb 1698 goto fail;
f12ae3c4 1699 }
f12ae3c4
GSB
1700 }
1701
1702 closedir(d);
1703 return list;
40923bdb
LDM
1704
1705fail:
1706 closedir(d);
1707 kmod_module_unref_list(list);
1708 return NULL;
f12ae3c4
GSB
1709}
1710
1711KMOD_EXPORT const char *kmod_module_section_get_name(const struct kmod_list *entry)
1712{
1713 struct kmod_module_section *section;
28c175ed 1714
f12ae3c4
GSB
1715 if (entry == NULL)
1716 return NULL;
28c175ed 1717
f12ae3c4
GSB
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;
28c175ed 1725
f12ae3c4
GSB
1726 if (entry == NULL)
1727 return (unsigned long)-1;
28c175ed 1728
f12ae3c4
GSB
1729 section = entry->data;
1730 return section->address;
1731}
1732
1733KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
1734{
63aec609 1735 kmod_list_release(list, kmod_module_section_free);
f12ae3c4 1736}
708624a4 1737
5cd2a2a4 1738static int kmod_module_get_elf(const struct kmod_module *mod, struct kmod_elf **elf)
1eff942e
LDM
1739{
1740 if (mod->file == NULL) {
1741 const char *path = kmod_module_get_path(mod);
5cd2a2a4 1742 int ret;
1eff942e 1743
5cd2a2a4
EV
1744 if (path == NULL)
1745 return -ENOENT;
1eff942e 1746
5cd2a2a4
EV
1747 ret = kmod_file_open(mod->ctx, path, &((struct kmod_module *)mod)->file);
1748 if (ret)
1749 return ret;
1eff942e
LDM
1750 }
1751
5cd2a2a4 1752 return kmod_file_get_elf(mod->file, elf);
1eff942e
LDM
1753}
1754
708624a4
GSB
1755struct kmod_module_info {
1756 char *key;
1757 char value[];
1758};
1759
115bcd52
EV
1760static struct kmod_module_info *kmod_module_info_new(const char *key, size_t keylen,
1761 const char *value, size_t valuelen)
708624a4
GSB
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
115bcd52 1769 info->key = (char *)info + sizeof(struct kmod_module_info) + valuelen + 1;
708624a4
GSB
1770 memcpy(info->key, key, keylen);
1771 info->key[keylen] = '\0';
8867f89c
LDM
1772 if (value)
1773 memcpy(info->value, value, valuelen);
708624a4
GSB
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
115bcd52
EV
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)
f64458ca
MM
1786{
1787 struct kmod_module_info *info;
1788 struct kmod_list *n;
1789
1790 info = kmod_module_info_new(key, keylen, value, valuelen);
6333934e 1791 if (info == NULL)
f64458ca 1792 return NULL;
f64458ca 1793 n = kmod_list_append(*list, info);
6333934e
MM
1794 if (n != NULL)
1795 *list = n;
1796 else
f64458ca 1797 kmod_module_info_free(info);
f64458ca
MM
1798 return n;
1799}
1800
0766b418 1801static bool kmod_module_strbuf_pushhex(struct strbuf *sbuf, const char *hex, size_t len)
96b88aea 1802{
b6b27d37 1803 static const char digits[] = "0123456789ABCDEF";
abcd0bf8 1804 const size_t line_limit = 20;
96b88aea 1805
b6b27d37 1806 for (size_t i = 0; i < len; i++) {
0766b418
TS
1807 if (!strbuf_pushchar(sbuf, digits[(hex[i] >> 4) & 0x0F]) ||
1808 !strbuf_pushchar(sbuf, digits[hex[i] & 0x0F]))
1809 return false;
25f2b2e0 1810
b6b27d37 1811 if (i < len - 1) {
0766b418
TS
1812 if (!strbuf_pushchar(sbuf, ':'))
1813 return false;
abcd0bf8 1814
0766b418
TS
1815 if ((i + 1) % line_limit == 0 && !strbuf_pushchars(sbuf, "\n\t\t"))
1816 return false;
abcd0bf8 1817 }
96b88aea 1818 }
25f2b2e0 1819
0766b418 1820 return true;
96b88aea
YK
1821}
1822
1823static struct kmod_list *kmod_module_info_append_hex(struct kmod_list **list,
115bcd52
EV
1824 const char *key, size_t keylen,
1825 const char *value, size_t valuelen)
96b88aea 1826{
96b88aea
YK
1827 struct kmod_list *n;
1828
1829 if (valuelen > 0) {
0766b418
TS
1830 DECLARE_STRBUF_WITH_STACK(sbuf, 512);
1831 const char *hex;
1832
96b88aea 1833 /* Display as 01:12:DE:AD:BE:EF:... */
0766b418
TS
1834 if (!kmod_module_strbuf_pushhex(&sbuf, value, valuelen))
1835 goto list_error;
1836 hex = strbuf_str(&sbuf);
0766b418 1837
96b88aea 1838 n = kmod_module_info_append(list, key, keylen, hex, strlen(hex));
96b88aea
YK
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
115bcd52
EV
1853KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod,
1854 struct kmod_list **list)
708624a4 1855{
708624a4 1856 struct kmod_elf *elf;
708624a4 1857 char **strings;
f64458ca 1858 int i, count, ret = -ENOMEM;
a1105720 1859 struct kmod_signature_info sig_info = {};
708624a4
GSB
1860
1861 if (mod == NULL || list == NULL)
1862 return -ENOENT;
1863
1864 assert(*list == NULL);
1865
e7e2cb61
AG
1866 /* remove const: this can only change internal state */
1867 if (kmod_module_is_builtin((struct kmod_module *)mod)) {
115bcd52
EV
1868 count = kmod_builtin_get_modinfo(mod->ctx, kmod_module_get_name(mod),
1869 &strings);
e7e2cb61
AG
1870 if (count < 0)
1871 return count;
1872 } else {
5cd2a2a4
EV
1873 ret = kmod_module_get_elf(mod, &elf);
1874 if (ret)
1875 return ret;
708624a4 1876
9099346c 1877 count = kmod_elf_get_modinfo_strings(elf, &strings);
e7e2cb61
AG
1878 if (count < 0)
1879 return count;
1880 }
708624a4
GSB
1881
1882 for (i = 0; i < count; i++) {
708624a4
GSB
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;
818af4f6 1892 value = key;
708624a4
GSB
1893 } else {
1894 keylen = value - key;
1895 value++;
1896 valuelen = strlen(value);
1897 }
1898
f64458ca
MM
1899 n = kmod_module_info_append(list, key, keylen, value, valuelen);
1900 if (n == NULL)
708624a4 1901 goto list_error;
708624a4 1902 }
8fe1681c 1903
e7e2cb61 1904 if (mod->file && kmod_module_signature_info(mod->file, &sig_info)) {
8fe1681c 1905 struct kmod_list *n;
8fe1681c 1906
30fb14f3 1907 n = kmod_module_info_append(list, "sig_id", strlen("sig_id"),
115bcd52 1908 sig_info.id_type, strlen(sig_info.id_type));
e78fe15f
LDM
1909 if (n == NULL)
1910 goto list_error;
1911 count++;
1912
8fe1681c 1913 n = kmod_module_info_append(list, "signer", strlen("signer"),
115bcd52 1914 sig_info.signer, sig_info.signer_len);
8fe1681c
MM
1915 if (n == NULL)
1916 goto list_error;
1917 count++;
1918
96b88aea 1919 n = kmod_module_info_append_hex(list, "sig_key", strlen("sig_key"),
115bcd52 1920 sig_info.key_id, sig_info.key_id_len);
96b88aea
YK
1921 if (n == NULL)
1922 goto list_error;
1923 count++;
8fe1681c 1924
115bcd52
EV
1925 n = kmod_module_info_append(list, "sig_hashalgo", strlen("sig_hashalgo"),
1926 sig_info.hash_algo,
1927 strlen(sig_info.hash_algo));
8fe1681c
MM
1928 if (n == NULL)
1929 goto list_error;
1930 count++;
1931
1932 /*
e78fe15f 1933 * Omit sig_info.algo for now, as these
8fe1681c
MM
1934 * are currently constant.
1935 */
115bcd52
EV
1936 n = kmod_module_info_append_hex(list, "signature", strlen("signature"),
1937 sig_info.sig, sig_info.sig_len);
e5b6a658
YK
1938
1939 if (n == NULL)
1940 goto list_error;
1941 count++;
8fe1681c 1942 }
708624a4
GSB
1943 ret = count;
1944
1945list_error:
391b4714
YK
1946 /* aux structures freed in normal case also */
1947 kmod_module_signature_info_free(&sig_info);
1948
6333934e
MM
1949 if (ret < 0) {
1950 kmod_module_info_free_list(*list);
1951 *list = NULL;
1952 }
708624a4 1953 free(strings);
708624a4
GSB
1954 return ret;
1955}
1956
708624a4
GSB
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
708624a4
GSB
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
708624a4
GSB
1979KMOD_EXPORT void kmod_module_info_free_list(struct kmod_list *list)
1980{
63aec609 1981 kmod_list_release(list, kmod_module_info_free);
708624a4
GSB
1982}
1983
1984struct kmod_module_version {
1985 uint64_t crc;
1986 char symbol[];
1987};
1988
115bcd52
EV
1989static struct kmod_module_version *kmod_module_versions_new(uint64_t crc,
1990 const char *symbol)
708624a4
GSB
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
115bcd52
EV
2009KMOD_EXPORT int kmod_module_get_versions(const struct kmod_module *mod,
2010 struct kmod_list **list)
708624a4 2011{
708624a4 2012 struct kmod_elf *elf;
708624a4 2013 struct kmod_modversion *versions;
708624a4
GSB
2014 int i, count, ret = 0;
2015
2016 if (mod == NULL || list == NULL)
2017 return -ENOENT;
2018
2019 assert(*list == NULL);
2020
5cd2a2a4
EV
2021 ret = kmod_module_get_elf(mod, &elf);
2022 if (ret)
2023 return ret;
708624a4 2024
708624a4 2025 count = kmod_elf_get_modversions(elf, &versions);
1eff942e
LDM
2026 if (count < 0)
2027 return count;
708624a4
GSB
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) {
708624a4
GSB
2035 kmod_module_versions_free_list(*list);
2036 *list = NULL;
70108351 2037 ret = -ENOMEM;
708624a4
GSB
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);
708624a4
GSB
2056 return ret;
2057}
2058
708624a4
GSB
2059KMOD_EXPORT const char *kmod_module_version_get_symbol(const struct kmod_list *entry)
2060{
2061 struct kmod_module_version *version;
2062
c8f0623a 2063 if (entry == NULL || entry->data == NULL)
708624a4
GSB
2064 return NULL;
2065
2066 version = entry->data;
2067 return version->symbol;
2068}
2069
708624a4
GSB
2070KMOD_EXPORT uint64_t kmod_module_version_get_crc(const struct kmod_list *entry)
2071{
2072 struct kmod_module_version *version;
2073
c8f0623a 2074 if (entry == NULL || entry->data == NULL)
708624a4
GSB
2075 return 0;
2076
2077 version = entry->data;
2078 return version->crc;
2079}
2080
708624a4
GSB
2081KMOD_EXPORT void kmod_module_versions_free_list(struct kmod_list *list)
2082{
63aec609 2083 kmod_list_release(list, kmod_module_version_free);
708624a4 2084}
45e6db9c
GSB
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
115bcd52
EV
2110KMOD_EXPORT int kmod_module_get_symbols(const struct kmod_module *mod,
2111 struct kmod_list **list)
45e6db9c 2112{
45e6db9c 2113 struct kmod_elf *elf;
45e6db9c 2114 struct kmod_modversion *symbols;
45e6db9c
GSB
2115 int i, count, ret = 0;
2116
2117 if (mod == NULL || list == NULL)
2118 return -ENOENT;
2119
2120 assert(*list == NULL);
2121
5cd2a2a4
EV
2122 ret = kmod_module_get_elf(mod, &elf);
2123 if (ret)
2124 return ret;
45e6db9c 2125
45e6db9c 2126 count = kmod_elf_get_symbols(elf, &symbols);
1eff942e
LDM
2127 if (count < 0)
2128 return count;
45e6db9c
GSB
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) {
45e6db9c
GSB
2136 kmod_module_symbols_free_list(*list);
2137 *list = NULL;
70108351 2138 ret = -ENOMEM;
45e6db9c
GSB
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);
45e6db9c
GSB
2157 return ret;
2158}
2159
45e6db9c
GSB
2160KMOD_EXPORT const char *kmod_module_symbol_get_symbol(const struct kmod_list *entry)
2161{
2162 struct kmod_module_symbol *symbol;
2163
c8f0623a 2164 if (entry == NULL || entry->data == NULL)
45e6db9c
GSB
2165 return NULL;
2166
2167 symbol = entry->data;
2168 return symbol->symbol;
2169}
2170
45e6db9c
GSB
2171KMOD_EXPORT uint64_t kmod_module_symbol_get_crc(const struct kmod_list *entry)
2172{
2173 struct kmod_module_symbol *symbol;
2174
c8f0623a 2175 if (entry == NULL || entry->data == NULL)
45e6db9c
GSB
2176 return 0;
2177
2178 symbol = entry->data;
2179 return symbol->crc;
2180}
2181
45e6db9c
GSB
2182KMOD_EXPORT void kmod_module_symbols_free_list(struct kmod_list *list)
2183{
63aec609 2184 kmod_list_release(list, kmod_module_symbol_free);
45e6db9c 2185}
674f8590
GSB
2186
2187struct kmod_module_dependency_symbol {
2188 uint64_t crc;
2189 uint8_t bind;
2190 char symbol[];
2191};
2192
8335c8c8 2193// clang-format off
674f8590 2194static struct kmod_module_dependency_symbol *kmod_module_dependency_symbols_new(uint64_t crc, uint8_t bind, const char *symbol)
8335c8c8 2195// clang-format on
674f8590
GSB
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
115bcd52
EV
2210static void kmod_module_dependency_symbol_free(
2211 struct kmod_module_dependency_symbol *dependency_symbol)
674f8590
GSB
2212{
2213 free(dependency_symbol);
2214}
2215
115bcd52
EV
2216KMOD_EXPORT int kmod_module_get_dependency_symbols(const struct kmod_module *mod,
2217 struct kmod_list **list)
674f8590 2218{
674f8590 2219 struct kmod_elf *elf;
674f8590 2220 struct kmod_modversion *symbols;
674f8590
GSB
2221 int i, count, ret = 0;
2222
2223 if (mod == NULL || list == NULL)
2224 return -ENOENT;
2225
2226 assert(*list == NULL);
2227
5cd2a2a4
EV
2228 ret = kmod_module_get_elf(mod, &elf);
2229 if (ret)
2230 return ret;
674f8590 2231
674f8590 2232 count = kmod_elf_get_dependency_symbols(elf, &symbols);
1eff942e
LDM
2233 if (count < 0)
2234 return count;
674f8590
GSB
2235
2236 for (i = 0; i < count; i++) {
2237 struct kmod_module_dependency_symbol *mv;
2238 struct kmod_list *n;
2239
115bcd52 2240 mv = kmod_module_dependency_symbols_new(symbols[i].crc, symbols[i].bind,
674f8590
GSB
2241 symbols[i].symbol);
2242 if (mv == NULL) {
674f8590
GSB
2243 kmod_module_dependency_symbols_free_list(*list);
2244 *list = NULL;
70108351 2245 ret = -ENOMEM;
674f8590
GSB
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);
674f8590
GSB
2264 return ret;
2265}
2266
8335c8c8 2267// clang-format off
674f8590 2268KMOD_EXPORT const char *kmod_module_dependency_symbol_get_symbol(const struct kmod_list *entry)
8335c8c8 2269// clang-format on
674f8590
GSB
2270{
2271 struct kmod_module_dependency_symbol *dependency_symbol;
2272
c8f0623a 2273 if (entry == NULL || entry->data == NULL)
674f8590
GSB
2274 return NULL;
2275
2276 dependency_symbol = entry->data;
2277 return dependency_symbol->symbol;
2278}
2279
674f8590
GSB
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
c8f0623a 2284 if (entry == NULL || entry->data == NULL)
674f8590
GSB
2285 return 0;
2286
2287 dependency_symbol = entry->data;
2288 return dependency_symbol->crc;
2289}
2290
674f8590
GSB
2291KMOD_EXPORT int kmod_module_dependency_symbol_get_bind(const struct kmod_list *entry)
2292{
2293 struct kmod_module_dependency_symbol *dependency_symbol;
2294
c8f0623a 2295 if (entry == NULL || entry->data == NULL)
674f8590
GSB
2296 return 0;
2297
2298 dependency_symbol = entry->data;
2299 return dependency_symbol->bind;
2300}
2301
674f8590
GSB
2302KMOD_EXPORT void kmod_module_dependency_symbols_free_list(struct kmod_list *list)
2303{
63aec609 2304 kmod_list_release(list, kmod_module_dependency_symbol_free);
674f8590 2305}