2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2010-05-22 00:29:53 +02:00
|
|
|
|
2017-08-31 15:33:33 +02:00
|
|
|
#include <ftw.h>
|
2010-05-22 00:29:53 +02:00
|
|
|
#include <string.h>
|
2015-11-16 22:09:36 +01:00
|
|
|
#include <unistd.h>
|
2014-11-14 17:58:32 +01:00
|
|
|
|
2017-08-31 15:33:33 +02:00
|
|
|
#include "alloc-util.h"
|
2015-05-06 18:18:43 +02:00
|
|
|
#include "bus-util.h"
|
2015-11-16 22:09:36 +01:00
|
|
|
#include "capability-util.h"
|
2017-08-31 15:33:33 +02:00
|
|
|
#include "fileio.h"
|
2010-05-22 00:29:53 +02:00
|
|
|
#include "kmod-setup.h"
|
2015-11-16 22:09:36 +01:00
|
|
|
#include "macro.h"
|
2017-08-31 15:33:33 +02:00
|
|
|
#include "string-util.h"
|
2010-05-22 00:29:53 +02:00
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_KMOD
|
2017-11-24 13:53:36 +01:00
|
|
|
#include <libkmod.h>
|
|
|
|
#include "module-util.h"
|
|
|
|
|
2013-05-07 17:48:25 +02:00
|
|
|
static void systemd_kmod_log(
|
|
|
|
void *data,
|
|
|
|
int priority,
|
|
|
|
const char *file, int line,
|
|
|
|
const char *fn,
|
|
|
|
const char *format,
|
|
|
|
va_list args) {
|
|
|
|
|
2012-11-04 16:54:19 +01:00
|
|
|
/* library logging is enabled at debug only */
|
2014-02-20 18:18:32 +01:00
|
|
|
DISABLE_WARNING_FORMAT_NONLITERAL;
|
2014-11-27 20:20:23 +01:00
|
|
|
log_internalv(LOG_DEBUG, 0, file, line, fn, format, args);
|
2014-02-20 18:18:32 +01:00
|
|
|
REENABLE_WARNING;
|
2012-02-08 21:52:18 +01:00
|
|
|
}
|
2013-05-07 17:48:25 +02:00
|
|
|
|
2017-08-31 15:33:33 +02:00
|
|
|
static int has_virtio_rng_nftw_cb(
|
|
|
|
const char *fpath,
|
|
|
|
const struct stat *sb,
|
|
|
|
int tflag,
|
|
|
|
struct FTW *ftwbuf) {
|
|
|
|
|
|
|
|
_cleanup_free_ char *alias = NULL;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if ((FTW_D == tflag) && (ftwbuf->level > 2))
|
|
|
|
return FTW_SKIP_SUBTREE;
|
|
|
|
|
|
|
|
if (FTW_F != tflag)
|
|
|
|
return FTW_CONTINUE;
|
|
|
|
|
|
|
|
if (!endswith(fpath, "/modalias"))
|
|
|
|
return FTW_CONTINUE;
|
|
|
|
|
|
|
|
r = read_one_line_file(fpath, &alias);
|
|
|
|
if (r < 0)
|
|
|
|
return FTW_SKIP_SIBLINGS;
|
|
|
|
|
|
|
|
if (startswith(alias, "pci:v00001AF4d00001005"))
|
|
|
|
return FTW_STOP;
|
|
|
|
|
|
|
|
if (startswith(alias, "pci:v00001AF4d00001044"))
|
|
|
|
return FTW_STOP;
|
|
|
|
|
|
|
|
return FTW_SKIP_SIBLINGS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool has_virtio_rng(void) {
|
|
|
|
return (nftw("/sys/devices/pci0000:00", has_virtio_rng_nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL) == FTW_STOP);
|
|
|
|
}
|
2017-09-08 23:51:04 +02:00
|
|
|
#endif
|
2017-08-31 15:33:33 +02:00
|
|
|
|
2013-12-18 23:56:35 +01:00
|
|
|
int kmod_setup(void) {
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_KMOD
|
2014-06-17 03:23:23 +02:00
|
|
|
|
2013-12-18 23:56:35 +01:00
|
|
|
static const struct {
|
|
|
|
const char *module;
|
|
|
|
const char *path;
|
2015-06-08 18:52:25 +02:00
|
|
|
bool warn_if_unavailable:1;
|
|
|
|
bool warn_if_module:1;
|
2013-12-18 23:56:35 +01:00
|
|
|
bool (*condition_fn)(void);
|
|
|
|
} kmod_table[] = {
|
2018-07-06 11:51:04 +02:00
|
|
|
/* This one we need to load explicitly, since auto-loading on use doesn't work
|
|
|
|
* before udev created the ghost device nodes, and we need it earlier than that. */
|
2015-06-08 18:52:25 +02:00
|
|
|
{ "autofs4", "/sys/class/misc/autofs", true, false, NULL },
|
2013-12-18 23:56:35 +01:00
|
|
|
|
2018-07-06 11:51:04 +02:00
|
|
|
/* This one we need to load explicitly, since auto-loading of IPv6 is not done when
|
|
|
|
* we try to configure ::1 on the loopback device. */
|
2015-06-08 18:52:25 +02:00
|
|
|
{ "ipv6", "/sys/module/ipv6", false, true, NULL },
|
2013-12-18 23:56:35 +01:00
|
|
|
|
2018-07-06 11:51:04 +02:00
|
|
|
/* This should never be a module */
|
2015-06-08 18:52:25 +02:00
|
|
|
{ "unix", "/proc/net/unix", true, true, NULL },
|
2013-12-18 23:56:35 +01:00
|
|
|
|
2017-10-03 10:41:51 +02:00
|
|
|
#if HAVE_LIBIPTC
|
2015-04-22 13:50:56 +02:00
|
|
|
/* netfilter is needed by networkd, nspawn among others, and cannot be autoloaded */
|
2015-06-08 18:52:25 +02:00
|
|
|
{ "ip_tables", "/proc/net/ip_tables_names", false, false, NULL },
|
2015-05-18 17:27:37 +02:00
|
|
|
#endif
|
2017-08-31 15:33:33 +02:00
|
|
|
/* virtio_rng would be loaded by udev later, but real entropy might be needed very early */
|
|
|
|
{ "virtio_rng", NULL, false, false, has_virtio_rng },
|
2013-12-18 23:56:35 +01:00
|
|
|
};
|
2017-10-08 15:55:24 +02:00
|
|
|
_cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL;
|
2018-10-19 20:00:46 +02:00
|
|
|
unsigned i;
|
2010-05-22 00:29:53 +02:00
|
|
|
|
2014-06-17 03:23:23 +02:00
|
|
|
if (have_effective_cap(CAP_SYS_MODULE) == 0)
|
|
|
|
return 0;
|
|
|
|
|
2013-12-18 23:56:35 +01:00
|
|
|
for (i = 0; i < ELEMENTSOF(kmod_table); i++) {
|
2013-12-19 01:32:55 +01:00
|
|
|
if (kmod_table[i].path && access(kmod_table[i].path, F_OK) >= 0)
|
2013-12-18 23:56:35 +01:00
|
|
|
continue;
|
|
|
|
|
2013-12-19 01:32:55 +01:00
|
|
|
if (kmod_table[i].condition_fn && !kmod_table[i].condition_fn())
|
2010-05-22 00:29:53 +02:00
|
|
|
continue;
|
|
|
|
|
2015-06-08 18:52:25 +02:00
|
|
|
if (kmod_table[i].warn_if_module)
|
2013-12-18 23:56:35 +01:00
|
|
|
log_debug("Your kernel apparently lacks built-in %s support. Might be "
|
|
|
|
"a good idea to compile it in. We'll now try to work around "
|
|
|
|
"this by loading the module...", kmod_table[i].module);
|
2010-05-22 00:29:53 +02:00
|
|
|
|
2012-02-08 21:52:18 +01:00
|
|
|
if (!ctx) {
|
|
|
|
ctx = kmod_new(NULL, NULL);
|
2013-05-07 17:48:25 +02:00
|
|
|
if (!ctx)
|
|
|
|
return log_oom();
|
2010-05-22 00:29:53 +02:00
|
|
|
|
2012-02-08 21:52:18 +01:00
|
|
|
kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
|
|
|
|
kmod_load_resources(ctx);
|
|
|
|
}
|
2010-05-22 00:29:53 +02:00
|
|
|
|
2018-07-06 12:41:50 +02:00
|
|
|
(void) module_load_and_warn(ctx, kmod_table[i].module, kmod_table[i].warn_if_unavailable);
|
2010-05-22 00:29:53 +02:00
|
|
|
}
|
|
|
|
|
2014-11-14 17:58:32 +01:00
|
|
|
#endif
|
2012-02-08 21:52:18 +01:00
|
|
|
return 0;
|
2010-05-22 00:29:53 +02:00
|
|
|
}
|