Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <ftw.h>
4 : : #include <string.h>
5 : : #include <unistd.h>
6 : :
7 : : #include "alloc-util.h"
8 : : #include "bus-util.h"
9 : : #include "capability-util.h"
10 : : #include "fileio.h"
11 : : #include "kmod-setup.h"
12 : : #include "macro.h"
13 : : #include "string-util.h"
14 : :
15 : : #if HAVE_KMOD
16 : : #include <libkmod.h>
17 : : #include "module-util.h"
18 : :
19 : 0 : static void systemd_kmod_log(
20 : : void *data,
21 : : int priority,
22 : : const char *file, int line,
23 : : const char *fn,
24 : : const char *format,
25 : : va_list args) {
26 : :
27 : : /* library logging is enabled at debug only */
28 : : DISABLE_WARNING_FORMAT_NONLITERAL;
29 : 0 : log_internalv(LOG_DEBUG, 0, file, line, fn, format, args);
30 : : REENABLE_WARNING;
31 : 0 : }
32 : :
33 : 0 : static int has_virtio_rng_nftw_cb(
34 : : const char *fpath,
35 : : const struct stat *sb,
36 : : int tflag,
37 : : struct FTW *ftwbuf) {
38 : :
39 : 0 : _cleanup_free_ char *alias = NULL;
40 : : int r;
41 : :
42 [ # # # # ]: 0 : if ((FTW_D == tflag) && (ftwbuf->level > 2))
43 : 0 : return FTW_SKIP_SUBTREE;
44 : :
45 [ # # ]: 0 : if (FTW_F != tflag)
46 : 0 : return FTW_CONTINUE;
47 : :
48 [ # # ]: 0 : if (!endswith(fpath, "/modalias"))
49 : 0 : return FTW_CONTINUE;
50 : :
51 : 0 : r = read_one_line_file(fpath, &alias);
52 [ # # ]: 0 : if (r < 0)
53 : 0 : return FTW_SKIP_SIBLINGS;
54 : :
55 [ # # ]: 0 : if (startswith(alias, "pci:v00001AF4d00001005"))
56 : 0 : return FTW_STOP;
57 : :
58 [ # # ]: 0 : if (startswith(alias, "pci:v00001AF4d00001044"))
59 : 0 : return FTW_STOP;
60 : :
61 : 0 : return FTW_SKIP_SIBLINGS;
62 : : }
63 : :
64 : 0 : static bool has_virtio_rng(void) {
65 : 0 : return (nftw("/sys/devices/pci0000:00", has_virtio_rng_nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL) == FTW_STOP);
66 : : }
67 : : #endif
68 : :
69 : 0 : int kmod_setup(void) {
70 : : #if HAVE_KMOD
71 : :
72 : : static const struct {
73 : : const char *module;
74 : : const char *path;
75 : : bool warn_if_unavailable:1;
76 : : bool warn_if_module:1;
77 : : bool (*condition_fn)(void);
78 : : } kmod_table[] = {
79 : : /* This one we need to load explicitly, since auto-loading on use doesn't work
80 : : * before udev created the ghost device nodes, and we need it earlier than that. */
81 : : { "autofs4", "/sys/class/misc/autofs", true, false, NULL },
82 : :
83 : : /* This one we need to load explicitly, since auto-loading of IPv6 is not done when
84 : : * we try to configure ::1 on the loopback device. */
85 : : { "ipv6", "/sys/module/ipv6", false, true, NULL },
86 : :
87 : : /* This should never be a module */
88 : : { "unix", "/proc/net/unix", true, true, NULL },
89 : :
90 : : #if HAVE_LIBIPTC
91 : : /* netfilter is needed by networkd, nspawn among others, and cannot be autoloaded */
92 : : { "ip_tables", "/proc/net/ip_tables_names", false, false, NULL },
93 : : #endif
94 : : /* virtio_rng would be loaded by udev later, but real entropy might be needed very early */
95 : : { "virtio_rng", NULL, false, false, has_virtio_rng },
96 : : };
97 : 0 : _cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL;
98 : : unsigned i;
99 : :
100 [ # # ]: 0 : if (have_effective_cap(CAP_SYS_MODULE) == 0)
101 : 0 : return 0;
102 : :
103 [ # # ]: 0 : for (i = 0; i < ELEMENTSOF(kmod_table); i++) {
104 [ # # # # ]: 0 : if (kmod_table[i].path && access(kmod_table[i].path, F_OK) >= 0)
105 : 0 : continue;
106 : :
107 [ # # # # ]: 0 : if (kmod_table[i].condition_fn && !kmod_table[i].condition_fn())
108 : 0 : continue;
109 : :
110 [ # # ]: 0 : if (kmod_table[i].warn_if_module)
111 [ # # ]: 0 : log_debug("Your kernel apparently lacks built-in %s support. Might be "
112 : : "a good idea to compile it in. We'll now try to work around "
113 : : "this by loading the module...", kmod_table[i].module);
114 : :
115 [ # # ]: 0 : if (!ctx) {
116 : 0 : ctx = kmod_new(NULL, NULL);
117 [ # # ]: 0 : if (!ctx)
118 : 0 : return log_oom();
119 : :
120 : 0 : kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
121 : 0 : kmod_load_resources(ctx);
122 : : }
123 : :
124 : 0 : (void) module_load_and_warn(ctx, kmod_table[i].module, kmod_table[i].warn_if_unavailable);
125 : : }
126 : :
127 : : #endif
128 : 0 : return 0;
129 : : }
|