1 // SPDX-License-Identifier: LGPL-2.1-or-later
3 * Copyright (C) 2011-2013 ProFUSION embedded systems
18 #include <sys/utsname.h>
20 #include <shared/hash.h>
21 #include <shared/util.h>
24 #include "libkmod-internal.h"
25 #include "libkmod-index.h"
27 #define KMOD_HASH_SIZE (256)
28 #define KMOD_LRU_MAX (128)
29 #define _KMOD_INDEX_MODULES_SIZE KMOD_INDEX_MODULES_BUILTIN + 1
36 [KMOD_INDEX_MODULES_DEP
] = { .fn
= "modules.dep" },
37 [KMOD_INDEX_MODULES_ALIAS
] = { .fn
= "modules.alias", .alias_prefix
= true },
38 [KMOD_INDEX_MODULES_SYMBOL
] = { .fn
= "modules.symbols", .alias_prefix
= true },
39 [KMOD_INDEX_MODULES_BUILTIN_ALIAS
] = { .fn
= "modules.builtin.alias" },
40 [KMOD_INDEX_MODULES_BUILTIN
] = { .fn
= "modules.builtin" },
44 static const char *const default_config_paths
[] = {
46 SYSCONFDIR
"/modprobe.d",
48 "/usr/local/lib/modprobe.d",
49 DISTCONFDIR
"/modprobe.d",
58 void (*log_fn
)(void *data
, int priority
, const char *file
, int line
,
59 const char *fn
, const char *format
, va_list args
);
63 enum kmod_file_compression_type kernel_compression
;
64 struct kmod_config
*config
;
65 struct hash
*modules_by_name
;
66 struct index_mm
*indexes
[_KMOD_INDEX_MODULES_SIZE
];
67 unsigned long long indexes_stamp
[_KMOD_INDEX_MODULES_SIZE
];
70 void kmod_log(const struct kmod_ctx
*ctx
, int priority
, const char *file
, int line
,
71 const char *fn
, const char *format
, ...)
75 if (ctx
->log_fn
== NULL
)
78 va_start(args
, format
);
79 ctx
->log_fn(ctx
->log_data
, priority
, file
, line
, fn
, format
, args
);
83 _printf_format_(6, 0) static void log_filep(void *data
, int priority
, const char *file
,
84 int line
, const char *fn
, const char *format
,
92 priname
= "EMERGENCY";
116 snprintf(buf
, sizeof(buf
), "L:%d", priority
);
119 if (ENABLE_DEBUG
== 1)
120 fprintf(fp
, "libkmod: %s %s:%d %s: ", priname
, file
, line
, fn
);
122 fprintf(fp
, "libkmod: %s: %s: ", priname
, fn
);
123 vfprintf(fp
, format
, args
);
126 KMOD_EXPORT
const char *kmod_get_dirname(const struct kmod_ctx
*ctx
)
134 KMOD_EXPORT
void *kmod_get_userdata(const struct kmod_ctx
*ctx
)
138 return (void *)ctx
->userdata
;
141 KMOD_EXPORT
void kmod_set_userdata(struct kmod_ctx
*ctx
, const void *userdata
)
145 ctx
->userdata
= userdata
;
148 static int log_priority(const char *priority
)
154 prio
= strtol(priority
, &endptr
, 10);
155 if (errno
== ERANGE
|| prio
< INT_MIN
|| prio
> INT_MAX
)
157 if (endptr
[0] == '\0' || isspace(endptr
[0]))
159 if (strstartswith(priority
, "err"))
161 if (strstartswith(priority
, "info"))
163 if (strstartswith(priority
, "debug"))
168 static const char *dirname_default_prefix
= MODULE_DIRECTORY
;
170 static char *get_kernel_release(const char *dirname
)
176 return path_make_absolute_cwd(dirname
);
181 if (asprintf(&p
, "%s/%s", dirname_default_prefix
, u
.release
) < 0)
187 static enum kmod_file_compression_type
get_kernel_compression(struct kmod_ctx
*ctx
)
189 const char *path
= "/sys/module/compression";
194 fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
196 /* Not having the file is not an error: kernel may be too old */
197 DBG(ctx
, "could not open '%s' for reading: %m\n", path
);
198 return KMOD_FILE_COMPRESSION_NONE
;
201 err
= read_str_safe(fd
, buf
, sizeof(buf
));
204 ERR(ctx
, "could not read from '%s': %s\n", path
, strerror(-err
));
205 return KMOD_FILE_COMPRESSION_NONE
;
208 if (streq(buf
, "zstd\n"))
209 return KMOD_FILE_COMPRESSION_ZSTD
;
210 else if (streq(buf
, "xz\n"))
211 return KMOD_FILE_COMPRESSION_XZ
;
212 else if (streq(buf
, "gzip\n"))
213 return KMOD_FILE_COMPRESSION_ZLIB
;
215 ERR(ctx
, "unknown kernel compression %s", buf
);
217 return KMOD_FILE_COMPRESSION_NONE
;
220 KMOD_EXPORT
struct kmod_ctx
*kmod_new(const char *dirname
, const char *const *config_paths
)
223 struct kmod_ctx
*ctx
;
226 ctx
= calloc(1, sizeof(struct kmod_ctx
));
231 ctx
->log_fn
= log_filep
;
232 ctx
->log_data
= stderr
;
233 ctx
->log_priority
= LOG_ERR
;
235 ctx
->dirname
= get_kernel_release(dirname
);
236 if (ctx
->dirname
== NULL
) {
237 ERR(ctx
, "could not retrieve directory\n");
241 /* environment overwrites config */
242 env
= secure_getenv("KMOD_LOG");
244 kmod_set_log_priority(ctx
, log_priority(env
));
246 ctx
->kernel_compression
= get_kernel_compression(ctx
);
248 if (config_paths
== NULL
)
249 config_paths
= default_config_paths
;
250 err
= kmod_config_new(ctx
, &ctx
->config
, config_paths
);
252 ERR(ctx
, "could not create config\n");
256 ctx
->modules_by_name
= hash_new(KMOD_HASH_SIZE
, NULL
);
257 if (ctx
->modules_by_name
== NULL
) {
258 ERR(ctx
, "could not create by-name hash\n");
262 INFO(ctx
, "ctx %p created\n", ctx
);
263 DBG(ctx
, "log_priority=%d\n", ctx
->log_priority
);
268 free(ctx
->modules_by_name
);
274 KMOD_EXPORT
struct kmod_ctx
*kmod_ref(struct kmod_ctx
*ctx
)
282 KMOD_EXPORT
struct kmod_ctx
*kmod_unref(struct kmod_ctx
*ctx
)
287 if (--ctx
->refcount
> 0)
290 INFO(ctx
, "context %p released\n", ctx
);
292 kmod_unload_resources(ctx
);
293 hash_free(ctx
->modules_by_name
);
296 kmod_config_free(ctx
->config
);
302 KMOD_EXPORT
void kmod_set_log_fn(struct kmod_ctx
*ctx
,
303 void (*log_fn
)(void *data
, int priority
,
304 const char *file
, int line
, const char *fn
,
305 const char *format
, va_list args
),
310 ctx
->log_fn
= log_fn
;
311 ctx
->log_data
= (void *)data
;
312 INFO(ctx
, "custom logging function %p registered\n", log_fn
);
315 KMOD_EXPORT
int kmod_get_log_priority(const struct kmod_ctx
*ctx
)
319 return ctx
->log_priority
;
322 KMOD_EXPORT
void kmod_set_log_priority(struct kmod_ctx
*ctx
, int priority
)
326 ctx
->log_priority
= priority
;
329 struct kmod_module
*kmod_pool_get_module(struct kmod_ctx
*ctx
, const char *key
)
331 struct kmod_module
*mod
;
333 mod
= hash_find(ctx
->modules_by_name
, key
);
335 DBG(ctx
, "get module name='%s' found=%p\n", key
, mod
);
340 int kmod_pool_add_module(struct kmod_ctx
*ctx
, struct kmod_module
*mod
, const char *key
)
342 DBG(ctx
, "add %p key='%s'\n", mod
, key
);
344 return hash_add(ctx
->modules_by_name
, key
, mod
);
347 void kmod_pool_del_module(struct kmod_ctx
*ctx
, struct kmod_module
*mod
, const char *key
)
349 DBG(ctx
, "del %p key='%s'\n", mod
, key
);
351 hash_del(ctx
->modules_by_name
, key
);
354 static int kmod_lookup_alias_from_alias_bin(struct kmod_ctx
*ctx
,
355 enum kmod_index index_number
,
356 const char *name
, struct kmod_list
**list
)
359 struct index_file
*idx
;
360 struct index_value
*realnames
, *realname
;
362 assert(*list
== NULL
);
364 if (ctx
->indexes
[index_number
] != NULL
) {
365 DBG(ctx
, "use mmapped index '%s' for name=%s\n",
366 index_files
[index_number
].fn
, name
);
367 realnames
= index_mm_searchwild(ctx
->indexes
[index_number
], name
);
371 snprintf(fn
, sizeof(fn
), "%s/%s.bin", ctx
->dirname
,
372 index_files
[index_number
].fn
);
374 DBG(ctx
, "file=%s name=%s\n", fn
, name
);
376 idx
= index_file_open(fn
);
380 realnames
= index_searchwild(idx
, name
);
381 index_file_close(idx
);
384 for (realname
= realnames
; realname
; realname
= realname
->next
) {
385 struct kmod_module
*mod
;
386 struct kmod_list
*node
;
388 err
= kmod_module_new_from_alias(ctx
, name
, realname
->value
, &mod
);
390 ERR(ctx
, "Could not create module for alias=%s realname=%s: %s\n",
391 name
, realname
->value
, strerror(-err
));
395 node
= kmod_list_append(*list
, mod
);
397 ERR(ctx
, "out of memory\n");
398 kmod_module_unref(mod
);
406 index_values_free(realnames
);
410 kmod_list_release(*list
, kmod_module_unref
);
411 index_values_free(realnames
);
415 int kmod_lookup_alias_from_symbols_file(struct kmod_ctx
*ctx
, const char *name
,
416 struct kmod_list
**list
)
418 if (!strstartswith(name
, "symbol:"))
421 return kmod_lookup_alias_from_alias_bin(ctx
, KMOD_INDEX_MODULES_SYMBOL
, name
,
425 int kmod_lookup_alias_from_aliases_file(struct kmod_ctx
*ctx
, const char *name
,
426 struct kmod_list
**list
)
428 return kmod_lookup_alias_from_alias_bin(ctx
, KMOD_INDEX_MODULES_ALIAS
, name
, list
);
431 static char *lookup_file(struct kmod_ctx
*ctx
, enum kmod_index index_number
,
436 if (ctx
->indexes
[index_number
]) {
437 DBG(ctx
, "use mmapped index '%s' modname=%s\n",
438 index_files
[index_number
].fn
, name
);
439 line
= index_mm_search(ctx
->indexes
[index_number
], name
);
441 struct index_file
*idx
;
444 snprintf(fn
, sizeof(fn
), "%s/%s.bin", ctx
->dirname
,
445 index_files
[index_number
].fn
);
446 DBG(ctx
, "file=%s modname=%s\n", fn
, name
);
448 idx
= index_file_open(fn
);
450 DBG(ctx
, "could not open builtin file '%s'\n", fn
);
454 line
= index_search(idx
, name
);
455 index_file_close(idx
);
461 static bool lookup_builtin_file(struct kmod_ctx
*ctx
, const char *name
)
463 _cleanup_free_
char *line
= lookup_file(ctx
, KMOD_INDEX_MODULES_BUILTIN
, name
);
468 int kmod_lookup_alias_from_kernel_builtin_file(struct kmod_ctx
*ctx
, const char *name
,
469 struct kmod_list
**list
)
474 ret
= kmod_lookup_alias_from_alias_bin(ctx
, KMOD_INDEX_MODULES_BUILTIN_ALIAS
,
477 kmod_list_foreach(l
, *list
) {
478 struct kmod_module
*mod
= l
->data
;
479 kmod_module_set_builtin(mod
, true);
485 int kmod_lookup_alias_from_builtin_file(struct kmod_ctx
*ctx
, const char *name
,
486 struct kmod_list
**list
)
488 assert(*list
== NULL
);
490 if (lookup_builtin_file(ctx
, name
)) {
491 struct kmod_module
*mod
;
492 struct kmod_list
*node
;
495 err
= kmod_module_new_from_name(ctx
, name
, &mod
);
497 ERR(ctx
, "Could not create module from name %s: %s\n", name
,
502 /* already mark it as builtin since it's being created from
504 kmod_module_set_builtin(mod
, true);
505 node
= kmod_list_append(*list
, mod
);
507 ERR(ctx
, "out of memory\n");
508 kmod_module_unref(mod
);
517 bool kmod_lookup_alias_is_builtin(struct kmod_ctx
*ctx
, const char *name
)
519 return lookup_builtin_file(ctx
, name
);
522 char *kmod_search_moddep(struct kmod_ctx
*ctx
, const char *name
)
524 return lookup_file(ctx
, KMOD_INDEX_MODULES_DEP
, name
);
527 int kmod_lookup_alias_from_moddep_file(struct kmod_ctx
*ctx
, const char *name
,
528 struct kmod_list
**list
)
533 assert(*list
== NULL
);
536 * Module names do not contain ':'. Return early if we know it will
539 if (strchr(name
, ':'))
542 line
= kmod_search_moddep(ctx
, name
);
544 struct kmod_module
*mod
;
545 struct kmod_list
*node
;
547 n
= kmod_module_new_from_name(ctx
, name
, &mod
);
549 ERR(ctx
, "Could not create module from name %s: %s\n", name
,
554 node
= kmod_list_append(*list
, mod
);
556 ERR(ctx
, "out of memory\n");
557 kmod_module_unref(mod
);
562 kmod_module_parse_depline(mod
, line
);
571 int kmod_lookup_alias_from_config(struct kmod_ctx
*ctx
, const char *name
,
572 struct kmod_list
**list
)
574 struct kmod_config
*config
= ctx
->config
;
578 assert(*list
== NULL
);
580 kmod_list_foreach(l
, config
->aliases
) {
581 const char *aliasname
= kmod_alias_get_name(l
);
582 const char *modname
= kmod_alias_get_modname(l
);
584 if (fnmatch(aliasname
, name
, 0) == 0) {
585 struct kmod_module
*mod
;
586 struct kmod_list
*node
;
588 err
= kmod_module_new_from_alias(ctx
, aliasname
, modname
, &mod
);
591 "Could not create module for alias=%s modname=%s: %s\n",
592 name
, modname
, strerror(-err
));
596 node
= kmod_list_append(*list
, mod
);
598 ERR(ctx
, "out of memory\n");
599 kmod_module_unref(mod
);
611 kmod_list_release(*list
, kmod_module_unref
);
615 int kmod_lookup_alias_from_commands(struct kmod_ctx
*ctx
, const char *name
,
616 struct kmod_list
**list
)
618 struct kmod_config
*config
= ctx
->config
;
619 struct kmod_list
*l
, *node
;
622 assert(*list
== NULL
);
624 kmod_list_foreach(l
, config
->install_commands
) {
625 const char *modname
= kmod_command_get_modname(l
);
627 if (streq(modname
, name
)) {
628 const char *cmd
= kmod_command_get_command(l
);
629 struct kmod_module
*mod
;
631 err
= kmod_module_new_from_name(ctx
, modname
, &mod
);
633 ERR(ctx
, "Could not create module from name %s: %s\n",
634 modname
, strerror(-err
));
638 node
= kmod_list_append(*list
, mod
);
640 ERR(ctx
, "out of memory\n");
641 kmod_module_unref(mod
);
648 kmod_module_set_install_commands(mod
, cmd
);
651 * match only the first one, like modprobe from
652 * module-init-tools does
661 kmod_list_foreach(l
, config
->remove_commands
) {
662 const char *modname
= kmod_command_get_modname(l
);
664 if (streq(modname
, name
)) {
665 const char *cmd
= kmod_command_get_command(l
);
666 struct kmod_module
*mod
;
668 err
= kmod_module_new_from_name(ctx
, modname
, &mod
);
670 ERR(ctx
, "Could not create module from name %s: %s\n",
671 modname
, strerror(-err
));
675 node
= kmod_list_append(*list
, mod
);
677 ERR(ctx
, "out of memory\n");
678 kmod_module_unref(mod
);
685 kmod_module_set_remove_commands(mod
, cmd
);
688 * match only the first one, like modprobe from
689 * module-init-tools does
698 void kmod_set_modules_visited(struct kmod_ctx
*ctx
, bool visited
)
700 struct hash_iter iter
;
703 hash_iter_init(ctx
->modules_by_name
, &iter
);
704 while (hash_iter_next(&iter
, NULL
, &v
))
705 kmod_module_set_visited((struct kmod_module
*)v
, visited
);
708 void kmod_set_modules_required(struct kmod_ctx
*ctx
, bool required
)
710 struct hash_iter iter
;
713 hash_iter_init(ctx
->modules_by_name
, &iter
);
714 while (hash_iter_next(&iter
, NULL
, &v
))
715 kmod_module_set_required((struct kmod_module
*)v
, required
);
718 static bool is_cache_invalid(const char *path
, unsigned long long stamp
)
722 if (stat(path
, &st
) < 0)
725 if (stamp
!= stat_mstamp(&st
))
731 KMOD_EXPORT
int kmod_validate_resources(struct kmod_ctx
*ctx
)
736 if (ctx
== NULL
|| ctx
->config
== NULL
)
737 return KMOD_RESOURCES_MUST_RECREATE
;
739 kmod_list_foreach(l
, ctx
->config
->paths
) {
740 struct kmod_config_path
*cf
= l
->data
;
742 if (is_cache_invalid(cf
->path
, cf
->stamp
))
743 return KMOD_RESOURCES_MUST_RECREATE
;
746 for (i
= 0; i
< _KMOD_INDEX_MODULES_SIZE
; i
++) {
749 if (ctx
->indexes
[i
] == NULL
)
752 snprintf(path
, sizeof(path
), "%s/%s.bin", ctx
->dirname
, index_files
[i
].fn
);
754 if (is_cache_invalid(path
, ctx
->indexes_stamp
[i
]))
755 return KMOD_RESOURCES_MUST_RELOAD
;
758 return KMOD_RESOURCES_OK
;
761 KMOD_EXPORT
int kmod_load_resources(struct kmod_ctx
*ctx
)
769 for (i
= 0; i
< _KMOD_INDEX_MODULES_SIZE
; i
++) {
772 if (ctx
->indexes
[i
] != NULL
) {
773 INFO(ctx
, "Index %s already loaded\n", index_files
[i
].fn
);
777 snprintf(path
, sizeof(path
), "%s/%s.bin", ctx
->dirname
, index_files
[i
].fn
);
778 ret
= index_mm_open(ctx
, path
, &ctx
->indexes_stamp
[i
], &ctx
->indexes
[i
]);
781 * modules.builtin.alias are considered optional since it's
782 * recently added and older installations may not have it;
783 * we allow failing for any reason
786 if (i
!= KMOD_INDEX_MODULES_BUILTIN_ALIAS
)
793 kmod_unload_resources(ctx
);
798 KMOD_EXPORT
void kmod_unload_resources(struct kmod_ctx
*ctx
)
805 for (i
= 0; i
< _KMOD_INDEX_MODULES_SIZE
; i
++) {
806 if (ctx
->indexes
[i
] != NULL
) {
807 index_mm_close(ctx
->indexes
[i
]);
808 ctx
->indexes
[i
] = NULL
;
809 ctx
->indexes_stamp
[i
] = 0;
814 KMOD_EXPORT
int kmod_dump_index(struct kmod_ctx
*ctx
, enum kmod_index type
, int fd
)
819 #if defined(__clang__)
820 #pragma clang diagnostic push
821 #pragma clang diagnostic ignored "-Wtautological-unsigned-enum-zero-compare"
823 if (type
< 0 || type
>= _KMOD_INDEX_MODULES_SIZE
)
825 #if defined(__clang__)
826 #pragma clang diagnostic pop
829 if (ctx
->indexes
[type
] != NULL
) {
830 DBG(ctx
, "use mmapped index '%s'\n", index_files
[type
].fn
);
831 index_mm_dump(ctx
->indexes
[type
], fd
, index_files
[type
].alias_prefix
);
834 struct index_file
*idx
;
836 snprintf(fn
, sizeof(fn
), "%s/%s.bin", ctx
->dirname
, index_files
[type
].fn
);
838 DBG(ctx
, "file=%s\n", fn
);
840 idx
= index_file_open(fn
);
844 index_dump(idx
, fd
, index_files
[type
].alias_prefix
);
845 index_file_close(idx
);
851 const struct kmod_config
*kmod_get_config(const struct kmod_ctx
*ctx
)
856 enum kmod_file_compression_type
kmod_get_kernel_compression(const struct kmod_ctx
*ctx
)
858 return ctx
->kernel_compression
;