Skip to content

libkmod: tools: Introduce 'module fallback' directory #202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ AM_CPPFLAGS = \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DDISTCONFDIR=\""$(distconfdir)"\" \
-DMODULE_DIRECTORY=\""$(module_directory)"\" \
-DMODULE_FALLBACK_DIRECTORY=\""$(module_fallback_directory)"\" \
${zlib_CFLAGS}

AM_CFLAGS = $(OUR_CFLAGS)
Expand Down Expand Up @@ -196,7 +197,7 @@ MODULE_PLAYGROUND = testsuite/module-playground
BUILD_MODULES = $(AM_V_GEN) $(top_srcdir)/scripts/setup-modules.sh $(top_srcdir) $(top_builddir) $(MODULE_PLAYGROUND)
ROOTFS = testsuite/rootfs
ROOTFS_PRISTINE = $(top_srcdir)/testsuite/rootfs-pristine
CREATE_ROOTFS = $(AM_V_GEN) $(top_srcdir)/scripts/setup-rootfs.sh $(ROOTFS_PRISTINE) $(ROOTFS) $(MODULE_PLAYGROUND) $(top_builddir)/config.h $(sysconfdir) $(module_directory)
CREATE_ROOTFS = $(AM_V_GEN) $(top_srcdir)/scripts/setup-rootfs.sh $(ROOTFS_PRISTINE) $(ROOTFS) $(MODULE_PLAYGROUND) $(top_builddir)/config.h $(sysconfdir) $(module_directory) $(module_fallback_directory)

build-module-playground:
$(BUILD_MODULES)
Expand Down
7 changes: 6 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,13 @@ AC_ARG_WITH([module_directory],
[], [with_module_directory=/lib/modules])
AC_SUBST([module_directory], [$with_module_directory])

AC_ARG_WITH([module_fallback_directory],
AS_HELP_STRING([--with-module-fallback_directory=DIR], [alternative directory in which to look for kernel modules @<:@default=/run/modules@:>@]),
[], [with_module_fallback_directory=/run/modules])
AC_SUBST([module_fallback_directory], [$with_module_fallback_directory])

# Check all directory arguments for consistency.
for ac_var in distconfdir module_directory
for ac_var in distconfdir module_directory module_fallback_directory
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
Expand Down
8 changes: 8 additions & 0 deletions libkmod/libkmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ static int log_priority(const char *priority)
}

static const char *dirname_default_prefix = MODULE_DIRECTORY;
static const char *dirname_fallback_prefix = MODULE_FALLBACK_DIRECTORY;

static char *get_kernel_release(const char *dirname)
{
Expand All @@ -179,6 +180,13 @@ static char *get_kernel_release(const char *dirname)
if (asprintf(&p, "%s/%s", dirname_default_prefix, u.release) < 0)
return NULL;

/* If main path doesn't exist, try fallback */
if (is_dir(p) <= 0) {
free(p);
if (asprintf(&p, "%s/%s", dirname_fallback_prefix, u.release) < 0)
return NULL;
}

return p;
}

Expand Down
1 change: 1 addition & 0 deletions man/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ define generate_manpage
sed -e 's|@SYSCONFDIR@|$(sysconfdir)|g' | \
sed -e 's|@DISTCONFDIR@|$(distconfdir)|g' | \
sed -e 's|@MODULE_DIRECTORY@|$(module_directory)|g' | \
sed -e 's|@MODULE_FALLBACK_DIRECTORY@|$(module_fallback_directory)|g' | \
$(SCDOC) > $@
endef

Expand Down
6 changes: 6 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ if moduledir == ''
endif
cdata.set_quoted('MODULE_DIRECTORY', moduledir)

moduledir = get_option('modulefallbackdir')
if moduledir == ''
moduledir = '/run/modules'
endif
cdata.set_quoted('MODULE_FALLBACK_DIRECTORY', moduledir)

_completiondirs = [
['bashcompletiondir', 'bash-completion', 'bash-completion/completions', 'shell-completion/bash/@0@'],
['fishcompletiondir', 'fish', 'fish/vendor_functions.d', 'shell-completion/fish/@0@.fish'],
Expand Down
6 changes: 6 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ option(
description : 'Directory to look for kernel modules. Default: /lib/modules',
)

option(
'modulefallbackdir',
type : 'string',
description : 'Alternative directory to look for kernel modules. Default: /run/modules',
)

option(
'bashcompletiondir',
type : 'string',
Expand Down
5 changes: 5 additions & 0 deletions scripts/setup-rootfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ MODULE_PLAYGROUND=$3
CONFIG_H=$4
SYSCONFDIR=$5
MODULE_DIRECTORY=$6
MODULE_FALLBACK_DIRECTORY=$7
ANOTHER_MODULE_DIRECTORY=/foobar

# create rootfs from rootfs-pristine
Expand Down Expand Up @@ -98,6 +99,8 @@ map=(
["test-modprobe/external/lib/modules/external/"]="mod-simple.ko"
["test-modprobe/module-from-abspath/home/foo/"]="mod-simple.ko"
["test-modprobe/module-from-relpath/home/foo/"]="mod-simple.ko"
["test-modprobe/fallback$MODULE_FALLBACK_DIRECTORY/4.4.4/kernel/"]="mod-simple.ko"
["test-modprobe/fallback-custom$MODULE_FALLBACK_DIRECTORY/3.3.3/kernel/"]="mod-simple.ko"
["test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/block/cciss.ko"]="mod-fake-cciss.ko"
["test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/scsi/hpsa.ko"]="mod-fake-hpsa.ko"
["test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/scsi/scsi_mod.ko"]="mod-fake-scsi-mod.ko"
Expand All @@ -111,6 +114,8 @@ map=(
["test-modinfo/mod-simple-sha256.ko"]="mod-simple.ko"
["test-modinfo/mod-simple-pkcs7.ko"]="mod-simple.ko"
["test-modinfo/external/lib/modules/external/mod-simple.ko"]="mod-simple.ko"
["test-modinfo/fallback$MODULE_FALLBACK_DIRECTORY/4.4.4/kernel/"]="mod-simple.ko"
["test-modinfo/fallback-custom$MODULE_FALLBACK_DIRECTORY/3.3.3/kernel/"]="mod-simple.ko"
["test-weakdep$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-a.ko"]="mod-loop-a.ko"
["test-weakdep$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-b.ko"]="mod-loop-b.ko"
["test-weakdep$MODULE_DIRECTORY/4.4.4/kernel/mod-simple.ko"]="mod-simple.ko"
Expand Down
2 changes: 1 addition & 1 deletion shared/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ char *path_make_absolute_cwd(const char *p)
return r;
}

static inline int is_dir(const char *path)
int is_dir(const char *path)
{
struct stat st;

Expand Down
1 change: 1 addition & 0 deletions shared/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ _nonnull_(1) char *freadline_wrapped(FILE *fp, unsigned int *linenum);
/* path handling functions */
/* ************************************************************************ */
_must_check_ _nonnull_all_ char *path_make_absolute_cwd(const char *p);
int is_dir(const char *path);
int mkdir_p(const char *path, int len, mode_t mode);
int mkdir_parents(const char *path, mode_t mode);
unsigned long long stat_mstamp(const struct stat *st);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/run/modules/3.3.3/kernel/mod-simple.ko
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/run/modules/4.4.4/kernel/mod-simple.ko
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aliases extracted from modules themselves.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kernel/mod-simple.ko:
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Device nodes to trigger on-demand module loading.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Soft dependencies extracted from modules themselves.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aliases for symbols, used by symbol_request().
Binary file not shown.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aliases extracted from modules themselves.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kernel/mod-simple.ko:
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Device nodes to trigger on-demand module loading.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Soft dependencies extracted from modules themselves.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aliases for symbols, used by symbol_request().
Binary file not shown.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aliases extracted from modules themselves.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kernel/mod-simple.ko:
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Device nodes to trigger on-demand module loading.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Soft dependencies extracted from modules themselves.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aliases for symbols, used by symbol_request().
Binary file not shown.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aliases extracted from modules themselves.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kernel/mod-simple.ko:
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Device nodes to trigger on-demand module loading.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Soft dependencies extracted from modules themselves.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aliases for symbols, used by symbol_request().
Binary file not shown.
49 changes: 49 additions & 0 deletions testsuite/test-modinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,53 @@ DEFINE_TEST(test_modinfo_builtin,
.out = TESTSUITE_ROOTFS "test-modinfo/correct-builtin.txt",
})

static noreturn int test_modinfo_fallback(const struct test *t)
{
const char *const args[] = {
// clang-format off
progname,
"-F", "filename",
"mod-simple",
NULL,
// clang-format on
};
test_spawn_prog(progname, args);
exit(EXIT_FAILURE);
}
DEFINE_TEST(test_modinfo_fallback,
.description = "check if modinfo finds external module",
.config = {
[TC_ROOTFS] = TESTSUITE_ROOTFS "test-modinfo/fallback",
[TC_UNAME_R] = "4.4.4",
},
.output = {
.out = TESTSUITE_ROOTFS "test-modinfo/correct-fallback.txt",
})

static noreturn int test_modinfo_fallback_custom(const struct test *t)
{
const char *const args[] = {
// clang-format off
progname,
"-F", "filename",
"--set-version",
"3.3.3",
"mod-simple",
NULL,
// clang-format on
};
test_spawn_prog(progname, args);
exit(EXIT_FAILURE);
}
DEFINE_TEST(test_modinfo_fallback_custom,
.description = "check if modinfo finds external module",
.config = {
[TC_ROOTFS] = TESTSUITE_ROOTFS "test-modinfo/fallback-custom",
[TC_UNAME_R] = "4.4.4",
},
.output = {
.out = TESTSUITE_ROOTFS "test-modinfo/correct-fallback-custom.txt",
})


TESTSUITE_MAIN();
47 changes: 47 additions & 0 deletions testsuite/test-modprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,4 +484,51 @@ DEFINE_TEST(modprobe_module_from_relpath,
.modules_loaded = "mod-simple",
);

static noreturn int modprobe_fallback(const struct test *t)
{
const char *progname = TOOLS_DIR "/modprobe";
const char *const args[] = {
progname,
"mod-simple",
NULL,
};

test_spawn_prog(progname, args);
exit(EXIT_FAILURE);
}
DEFINE_TEST(modprobe_fallback,
.description = "check modprobe able to load module from fallback path",
.config = {
[TC_UNAME_R] = "4.4.4",
[TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/fallback",
[TC_INIT_MODULE_RETCODES] = "",
},
.need_spawn = true,
.modules_loaded = "mod-simple",
);

static noreturn int modprobe_fallback_custom(const struct test *t)
{
const char *progname = TOOLS_DIR "/modprobe";
const char *const args[] = {
progname,
"--set-version",
"3.3.3",
"mod-simple",
NULL,
};

test_spawn_prog(progname, args);
exit(EXIT_FAILURE);
}
DEFINE_TEST(modprobe_fallback_custom,
.description = "check modprobe able to load module from fallback path with --set-version",
.config = {
[TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/fallback-custom",
[TC_INIT_MODULE_RETCODES] = "",
},
.need_spawn = true,
.modules_loaded = "mod-simple",
);

TESTSUITE_MAIN();
11 changes: 11 additions & 0 deletions tools/modinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,17 @@ static int do_modinfo(int argc, char *argv[])
root, kversion);
return EXIT_FAILURE;
}

if (is_dir(dirname_buf) <= 0) {
n = snprintf(dirname_buf, sizeof(dirname_buf),
"%s" MODULE_FALLBACK_DIRECTORY "/%s", root, kversion);
if (n >= (int)sizeof(dirname_buf)) {
ERR("bad directory %s" MODULE_FALLBACK_DIRECTORY "/%s: path too long\n",
root, kversion);
return EXIT_FAILURE;
}
}

dirname = dirname_buf;
}

Expand Down
12 changes: 12 additions & 0 deletions tools/modprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,18 @@ static int do_modprobe(int argc, char **orig_argv)
err = -1;
goto done;
}

if (is_dir(dirname_buf) <= 0) {
n = snprintf(dirname_buf, sizeof(dirname_buf),
"%s" MODULE_FALLBACK_DIRECTORY "/%s", root, kversion);
if (n >= (int)sizeof(dirname_buf)) {
ERR("bad directory %s" MODULE_FALLBACK_DIRECTORY "/%s: path too long\n",
root, kversion);
err = -1;
goto done;
}
}

dirname = dirname_buf;
}

Expand Down