]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/modules-load/modules-load.c
resolved: avoid possible dereference of null pointer
[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>
fabe5c0e 29#include <getopt.h>
83684a35 30#include <libkmod.h>
b2423f1f
LP
31
32#include "log.h"
33#include "util.h"
34#include "strv.h"
2c21044f 35#include "conf-files.h"
a5c32cff 36#include "fileio.h"
eb9da376 37#include "build.h"
03658d4f
LP
38
39static char **arg_proc_cmdline_modules = NULL;
b2423f1f 40
fabe5c0e
LP
41static const char conf_file_dirs[] =
42 "/etc/modules-load.d\0"
43 "/run/modules-load.d\0"
44 "/usr/local/lib/modules-load.d\0"
45 "/usr/lib/modules-load.d\0"
46#ifdef HAVE_SPLIT_USR
47 "/lib/modules-load.d\0"
48#endif
49 ;
50
83684a35 51static void systemd_kmod_log(void *data, int priority, const char *file, int line,
f168c273 52 const char *fn, const char *format, va_list args) {
bcfce235
LP
53
54 DISABLE_WARNING_FORMAT_NONLITERAL;
e62abb62 55 log_metav(priority, file, line, fn, format, args);
bcfce235 56 REENABLE_WARNING;
83684a35
TG
57}
58
03658d4f 59static int add_modules(const char *p) {
fabe5c0e 60 _cleanup_strv_free_ char **k = NULL;
03658d4f
LP
61
62 k = strv_split(p, ",");
0d0f0c50
SL
63 if (!k)
64 return log_oom();
03658d4f 65
e3e45d4f 66 if (strv_extend_strv(&arg_proc_cmdline_modules, k) < 0)
0d0f0c50 67 return log_oom();
03658d4f 68
03658d4f
LP
69 return 0;
70}
71
059cb385 72static int parse_proc_cmdline_item(const char *key, const char *value) {
74df0fca 73 int r;
03658d4f 74
059cb385
LP
75 if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) {
76 r = add_modules(value);
141a79f4
ZJS
77 if (r < 0)
78 return r;
03658d4f
LP
79 }
80
c007bb1b 81 return 0;
03658d4f
LP
82}
83
84static int load_module(struct kmod_ctx *ctx, const char *m) {
27fda47f 85 const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
03658d4f
LP
86 struct kmod_list *itr, *modlist = NULL;
87 int r = 0;
88
9f6445e3 89 log_debug("load: %s", m);
03658d4f
LP
90
91 r = kmod_module_new_from_lookup(ctx, m, &modlist);
92 if (r < 0) {
93 log_error("Failed to lookup alias '%s': %s", m, strerror(-r));
94 return r;
95 }
96
27fda47f
MS
97 if (!modlist) {
98 log_error("Failed to find module '%s'", m);
8f9c0b4c 99 return -ENOENT;
27fda47f
MS
100 }
101
03658d4f
LP
102 kmod_list_foreach(itr, modlist) {
103 struct kmod_module *mod;
27fda47f 104 int state, err;
03658d4f
LP
105
106 mod = kmod_module_get_module(itr);
27fda47f
MS
107 state = kmod_module_get_initstate(mod);
108
109 switch (state) {
110 case KMOD_MODULE_BUILTIN:
111 log_info("Module '%s' is builtin", kmod_module_get_name(mod));
112 break;
113
114 case KMOD_MODULE_LIVE:
b56c267f 115 log_debug("Module '%s' is already loaded", kmod_module_get_name(mod));
27fda47f
MS
116 break;
117
118 default:
119 err = kmod_module_probe_insert_module(mod, probe_flags,
120 NULL, NULL, NULL, NULL);
121
122 if (err == 0)
123 log_info("Inserted module '%s'", kmod_module_get_name(mod));
124 else if (err == KMOD_PROBE_APPLY_BLACKLIST)
125 log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
126 else {
127 log_error("Failed to insert '%s': %s", kmod_module_get_name(mod),
128 strerror(-err));
129 r = err;
130 }
03658d4f
LP
131 }
132
133 kmod_module_unref(mod);
134 }
135
136 kmod_module_unref_list(modlist);
137
138 return r;
139}
140
fabe5c0e
LP
141static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) {
142 _cleanup_fclose_ FILE *f = NULL;
143 int r;
144
145 assert(ctx);
146 assert(path);
147
4cf7ea55 148 r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
fabe5c0e
LP
149 if (r < 0) {
150 if (ignore_enoent && r == -ENOENT)
151 return 0;
152
153 log_error("Failed to open %s, ignoring: %s", path, strerror(-r));
154 return r;
155 }
156
9f6445e3 157 log_debug("apply: %s", path);
fabe5c0e
LP
158 for (;;) {
159 char line[LINE_MAX], *l;
160 int k;
161
162 if (!fgets(line, sizeof(line), f)) {
163 if (feof(f))
164 break;
165
166 log_error("Failed to read file '%s', ignoring: %m", path);
167 return -errno;
168 }
169
170 l = strstrip(line);
171 if (!*l)
172 continue;
d3b6d0c2 173 if (strchr(COMMENTS "\n", *l))
fabe5c0e
LP
174 continue;
175
176 k = load_module(ctx, l);
177 if (k < 0 && r == 0)
178 r = k;
179 }
180
181 return r;
182}
183
184static int help(void) {
185
186 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
187 "Loads statically configured kernel modules.\n\n"
eb9da376
LP
188 " -h --help Show this help\n"
189 " --version Show package version\n",
fabe5c0e
LP
190 program_invocation_short_name);
191
192 return 0;
193}
194
195static int parse_argv(int argc, char *argv[]) {
196
eb9da376
LP
197 enum {
198 ARG_VERSION = 0x100,
199 };
200
fabe5c0e
LP
201 static const struct option options[] = {
202 { "help", no_argument, NULL, 'h' },
eb9da376
LP
203 { "version", no_argument, NULL, ARG_VERSION },
204 {}
fabe5c0e
LP
205 };
206
207 int c;
208
209 assert(argc >= 0);
210 assert(argv);
211
212 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
213
214 switch (c) {
215
216 case 'h':
eb9da376
LP
217 return help();
218
219 case ARG_VERSION:
220 puts(PACKAGE_STRING);
221 puts(SYSTEMD_FEATURES);
fabe5c0e
LP
222 return 0;
223
224 case '?':
225 return -EINVAL;
226
227 default:
eb9da376 228 assert_not_reached("Unhandled option");
fabe5c0e
LP
229 }
230 }
231
232 return 1;
233}
234
b2423f1f 235int main(int argc, char *argv[]) {
fabe5c0e 236 int r, k;
83684a35 237 struct kmod_ctx *ctx;
b2423f1f 238
fabe5c0e
LP
239 r = parse_argv(argc, argv);
240 if (r <= 0)
241 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b2423f1f 242
4cfa2c99 243 log_set_target(LOG_TARGET_AUTO);
b2423f1f
LP
244 log_parse_environment();
245 log_open();
246
4c12626c
LP
247 umask(0022);
248
059cb385 249 if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
03658d4f
LP
250 return EXIT_FAILURE;
251
4e2075ce
LP
252 ctx = kmod_new(NULL, NULL);
253 if (!ctx) {
83684a35 254 log_error("Failed to allocate memory for kmod.");
b2423f1f
LP
255 goto finish;
256 }
257
83684a35 258 kmod_load_resources(ctx);
83684a35 259 kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
b2423f1f 260
fabe5c0e 261 r = 0;
03658d4f 262
fabe5c0e
LP
263 if (argc > optind) {
264 int i;
b2423f1f 265
fabe5c0e
LP
266 for (i = optind; i < argc; i++) {
267 k = apply_file(ctx, argv[i], false);
268 if (k < 0 && r == 0)
269 r = k;
b2423f1f
LP
270 }
271
fabe5c0e
LP
272 } else {
273 _cleanup_free_ char **files = NULL;
274 char **fn, **i;
b2423f1f 275
fabe5c0e
LP
276 STRV_FOREACH(i, arg_proc_cmdline_modules) {
277 k = load_module(ctx, *i);
b857193b
LP
278 if (k < 0 && r == 0)
279 r = k;
b2423f1f
LP
280 }
281
4b462d1a
LP
282 k = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
283 if (k < 0) {
284 log_error("Failed to enumerate modules-load.d files: %s", strerror(-k));
285 if (r == 0)
286 r = k;
fabe5c0e 287 goto finish;
b2423f1f
LP
288 }
289
fabe5c0e
LP
290 STRV_FOREACH(fn, files) {
291 k = apply_file(ctx, *fn, true);
292 if (k < 0 && r == 0)
293 r = k;
294 }
b2423f1f
LP
295 }
296
b2423f1f 297finish:
83684a35 298 kmod_unref(ctx);
03658d4f 299 strv_free(arg_proc_cmdline_modules);
b2423f1f 300
fabe5c0e 301 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b2423f1f 302}