]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/modules-load/modules-load.c
modules-load: fix kernel cmdline parsing
[thirdparty/systemd.git] / src / modules-load / modules-load.c
CommitLineData
b2423f1f
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
b2423f1f
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
b2423f1f 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
b2423f1f
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <unistd.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <string.h>
26#include <sys/stat.h>
27#include <limits.h>
28#include <dirent.h>
83684a35 29#include <libkmod.h>
b2423f1f
LP
30
31#include "log.h"
32#include "util.h"
33#include "strv.h"
2c21044f 34#include "conf-files.h"
03658d4f
LP
35#include "virt.h"
36
37static char **arg_proc_cmdline_modules = NULL;
b2423f1f 38
cdb454f2
LP
39#pragma GCC diagnostic push
40#pragma GCC diagnostic ignored "-Wformat-nonliteral"
83684a35
TG
41static void systemd_kmod_log(void *data, int priority, const char *file, int line,
42 const char *fn, const char *format, va_list args)
43{
e62abb62 44 log_metav(priority, file, line, fn, format, args);
83684a35 45}
cdb454f2 46#pragma GCC diagnostic pop
83684a35 47
03658d4f
LP
48static int add_modules(const char *p) {
49 char **t, **k;
50
51 k = strv_split(p, ",");
52 if (!k) {
53 log_error("Out of memory");
54 return -ENOMEM;
55 }
56
57 t = strv_merge(arg_proc_cmdline_modules, k);
58 strv_free(k);
59 if (!t) {
60 log_error("Out of memory");
61 return -ENOMEM;
62 }
63
64 strv_free(arg_proc_cmdline_modules);
65 arg_proc_cmdline_modules = t;
66
67 return 0;
68}
69
70static int parse_proc_cmdline(void) {
71 char *line, *w, *state;
72 int r;
73 size_t l;
74
75 if (detect_container(NULL) > 0)
76 return 0;
77
78 r = read_one_line_file("/proc/cmdline", &line);
79 if (r < 0) {
80 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
81 return 0;
82 }
83
84 FOREACH_WORD_QUOTED(w, l, line, state) {
85 char *word;
86
87 word = strndup(w, l);
88 if (!word) {
89 r = -ENOMEM;
90 goto finish;
91 }
92
91ac7425 93 if (startswith(word, "modules-load=")) {
03658d4f 94
b2fc39a6 95 r = add_modules(word + 13);
03658d4f
LP
96 if (r < 0)
97 goto finish;
98
91ac7425 99 } else if (startswith(word, "rd.modules-load=")) {
03658d4f
LP
100
101 if (in_initrd()) {
b2fc39a6 102 r = add_modules(word + 16);
03658d4f
LP
103 if (r < 0)
104 goto finish;
105 }
106
107 }
108
109 free(word);
110 }
111
112 r = 0;
113
114finish:
115 free(line);
116 return r;
117}
118
119static int load_module(struct kmod_ctx *ctx, const char *m) {
27fda47f 120 const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
03658d4f
LP
121 struct kmod_list *itr, *modlist = NULL;
122 int r = 0;
123
124 log_debug("load: %s\n", m);
125
126 r = kmod_module_new_from_lookup(ctx, m, &modlist);
127 if (r < 0) {
128 log_error("Failed to lookup alias '%s': %s", m, strerror(-r));
129 return r;
130 }
131
27fda47f
MS
132 if (!modlist) {
133 log_error("Failed to find module '%s'", m);
8f9c0b4c 134 return -ENOENT;
27fda47f
MS
135 }
136
03658d4f
LP
137 kmod_list_foreach(itr, modlist) {
138 struct kmod_module *mod;
27fda47f 139 int state, err;
03658d4f
LP
140
141 mod = kmod_module_get_module(itr);
27fda47f
MS
142 state = kmod_module_get_initstate(mod);
143
144 switch (state) {
145 case KMOD_MODULE_BUILTIN:
146 log_info("Module '%s' is builtin", kmod_module_get_name(mod));
147 break;
148
149 case KMOD_MODULE_LIVE:
150 log_info("Module '%s' is already loaded", kmod_module_get_name(mod));
151 break;
152
153 default:
154 err = kmod_module_probe_insert_module(mod, probe_flags,
155 NULL, NULL, NULL, NULL);
156
157 if (err == 0)
158 log_info("Inserted module '%s'", kmod_module_get_name(mod));
159 else if (err == KMOD_PROBE_APPLY_BLACKLIST)
160 log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
161 else {
162 log_error("Failed to insert '%s': %s", kmod_module_get_name(mod),
163 strerror(-err));
164 r = err;
165 }
03658d4f
LP
166 }
167
168 kmod_module_unref(mod);
169 }
170
171 kmod_module_unref_list(modlist);
172
173 return r;
174}
175
b2423f1f 176int main(int argc, char *argv[]) {
03658d4f
LP
177 int r = EXIT_FAILURE, k;
178 char **files, **fn, **i;
83684a35 179 struct kmod_ctx *ctx;
b2423f1f
LP
180
181 if (argc > 1) {
182 log_error("This program takes no argument.");
22f4096c 183 return EXIT_FAILURE;
b2423f1f
LP
184 }
185
4cfa2c99 186 log_set_target(LOG_TARGET_AUTO);
b2423f1f
LP
187 log_parse_environment();
188 log_open();
189
4c12626c
LP
190 umask(0022);
191
03658d4f
LP
192 if (parse_proc_cmdline() < 0)
193 return EXIT_FAILURE;
194
4e2075ce
LP
195 ctx = kmod_new(NULL, NULL);
196 if (!ctx) {
83684a35 197 log_error("Failed to allocate memory for kmod.");
b2423f1f
LP
198 goto finish;
199 }
200
83684a35 201 kmod_load_resources(ctx);
83684a35 202 kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
b2423f1f 203
03658d4f
LP
204 r = EXIT_SUCCESS;
205
206 STRV_FOREACH(i, arg_proc_cmdline_modules) {
207 k = load_module(ctx, *i);
208 if (k < 0)
209 r = EXIT_FAILURE;
210 }
211
212 k = conf_files_list(&files, ".conf",
44143309 213 "/etc/modules-load.d",
fc1a2e06 214 "/run/modules-load.d",
223a3558 215 "/usr/local/lib/modules-load.d",
44143309 216 "/usr/lib/modules-load.d",
4e2075ce 217#ifdef HAVE_SPLIT_USR
223a3558 218 "/lib/modules-load.d",
4e2075ce 219#endif
03658d4f
LP
220 NULL);
221 if (k < 0) {
222 log_error("Failed to enumerate modules-load.d files: %s", strerror(-k));
223 r = EXIT_FAILURE;
b2423f1f
LP
224 goto finish;
225 }
226
db1413d7 227 STRV_FOREACH(fn, files) {
b2423f1f
LP
228 FILE *f;
229
db1413d7 230 f = fopen(*fn, "re");
b2423f1f 231 if (!f) {
db1413d7 232 if (errno == ENOENT)
70ca520f
LP
233 continue;
234
db1413d7 235 log_error("Failed to open %s: %m", *fn);
22f4096c 236 r = EXIT_FAILURE;
b2423f1f
LP
237 continue;
238 }
239
db1413d7 240 log_debug("apply: %s\n", *fn);
b2423f1f 241 for (;;) {
83684a35 242 char line[LINE_MAX], *l;
b2423f1f 243
4e2075ce 244 if (!fgets(line, sizeof(line), f))
b2423f1f
LP
245 break;
246
247 l = strstrip(line);
248 if (*l == '#' || *l == 0)
249 continue;
250
03658d4f
LP
251 k = load_module(ctx, l);
252 if (k < 0)
83684a35 253 r = EXIT_FAILURE;
b2423f1f
LP
254 }
255
256 if (ferror(f)) {
b2423f1f 257 log_error("Failed to read from file: %m");
83684a35 258 r = EXIT_FAILURE;
b2423f1f
LP
259 }
260
261 fclose(f);
262 }
263
b2423f1f 264finish:
83684a35
TG
265 strv_free(files);
266 kmod_unref(ctx);
03658d4f 267 strv_free(arg_proc_cmdline_modules);
b2423f1f
LP
268
269 return r;
270}