From b5683f45d9f4a640c120b579f05b2ee024790f56 Mon Sep 17 00:00:00 2001 From: Marius Bakke Date: Sat, 1 Aug 2020 18:02:21 +0200 Subject: testsuite: Add facility to skip tests. The Makefile helpfully warns that some tests will fail when --sysconfdir != /etc, but there are no provisions to easily disable those. This commit provides an escape hatch. [ Lucas: add comment detailing the purpose of the field ] --- testsuite/testsuite.c | 9 +++++++++ testsuite/testsuite.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index e46f3d8..05df553 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -37,6 +37,7 @@ #include "testsuite.h" static const char *ANSI_HIGHLIGHT_GREEN_ON = "\x1B[1;32m"; +static const char *ANSI_HIGHLIGHT_YELLOW_ON = "\x1B[1;33m"; static const char *ANSI_HIGHLIGHT_RED_ON = "\x1B[1;31m"; static const char *ANSI_HIGHLIGHT_OFF = "\x1B[0m"; @@ -948,6 +949,14 @@ static inline int test_run_parent(const struct test *t, int fdout[2], int err; bool matchout, match_modules; + if (t->skip) { + LOG("%sSKIPPED%s: %s\n", + ANSI_HIGHLIGHT_YELLOW_ON, ANSI_HIGHLIGHT_OFF, + t->name); + err = EXIT_SUCCESS; + goto exit; + } + /* Close write-fds */ if (t->output.out != NULL) close(fdout[1]); diff --git a/testsuite/testsuite.h b/testsuite/testsuite.h index f190249..c74b648 100644 --- a/testsuite/testsuite.h +++ b/testsuite/testsuite.h @@ -109,6 +109,8 @@ struct test { const struct keyval *env_vars; bool need_spawn; bool expected_fail; + /* allow to skip tests that don't meet compile-time dependencies */ + bool skip; bool print_outputs; } __attribute__((aligned(8))); -- cgit v1.2.3 From 847247a4a8b50f0fc2f6021d734c15f0824b85c2 Mon Sep 17 00:00:00 2001 From: Marius Bakke Date: Sat, 1 Aug 2020 18:02:22 +0200 Subject: testsuite: Automatically skip tests that fail when sysconfdir != /etc. --- Makefile.am | 12 +++++------- configure.ac | 2 ++ testsuite/test-blacklist.c | 3 +++ testsuite/test-depmod.c | 12 ++++++++++++ testsuite/test-modprobe.c | 6 ++++++ 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Makefile.am b/Makefile.am index acde92b..b29e943 100644 --- a/Makefile.am +++ b/Makefile.am @@ -280,13 +280,7 @@ TESTSUITE_OVERRIDE_LIBS = \ TESTSUITE_OVERRIDE_LIBS_LDFLAGS = \ avoid-version -module -shared -export-dynamic -rpath /nowhere -ldl -check-sysconfdir: - $(AM_V_at)if test "$(sysconfdir)" != "/etc" -a "$(sysconfdir)" != "/etc/"; then \ - echo "warning: Some tests will fail without --sysconfdir=/etc" >&2; \ - fi -.PHONY: check-sysconfdir - -check-am: rootfs check-sysconfdir +check-am: rootfs EXTRA_DIST += \ @@ -341,6 +335,10 @@ TESTSUITE_LDADD = \ testsuite/libtestsuite.la libkmod/libkmod-internal.la \ shared/libshared.la +if KMOD_SYSCONFDIR_NOT_ETC +TESTSUITE_CPPFLAGS += -DKMOD_SYSCONFDIR_NOT_ETC +endif + check_LTLIBRARIES += testsuite/libtestsuite.la testsuite_libtestsuite_la_SOURCES = \ testsuite/testsuite.c testsuite/testsuite.h diff --git a/configure.ac b/configure.ac index 0cf2eda..222de3e 100644 --- a/configure.ac +++ b/configure.ac @@ -224,6 +224,8 @@ GTK_DOC_CHECK([1.14],[--flavour no-tmpl-flat]) ], [ AM_CONDITIONAL([ENABLE_GTK_DOC], false)]) +# Some tests are skipped when sysconfdir != /etc. +AM_CONDITIONAL([KMOD_SYSCONFDIR_NOT_ETC], [test "x$sysconfdir" != "x/etc"]) ##################################################################### # Default CFLAGS and LDFLAGS diff --git a/testsuite/test-blacklist.c b/testsuite/test-blacklist.c index 969567d..d03eedb 100644 --- a/testsuite/test-blacklist.c +++ b/testsuite/test-blacklist.c @@ -95,6 +95,9 @@ fail_lookup: } DEFINE_TEST(blacklist_1, +#if defined(KMOD_SYSCONFDIR_NOT_ETC) + .skip = true, +#endif .description = "check if modules are correctly blacklisted", .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-blacklist/", diff --git a/testsuite/test-depmod.c b/testsuite/test-depmod.c index 47dafb4..261559c 100644 --- a/testsuite/test-depmod.c +++ b/testsuite/test-depmod.c @@ -42,6 +42,9 @@ static noreturn int depmod_modules_order_for_compressed(const struct test *t) } DEFINE_TEST(depmod_modules_order_for_compressed, +#if defined(KMOD_SYSCONFDIR_NOT_ETC) + .skip = true, +#endif .description = "check if depmod let aliases in right order when using compressed modules", .config = { [TC_UNAME_R] = MODULES_ORDER_UNAME, @@ -121,6 +124,9 @@ static noreturn int depmod_detect_loop(const struct test *t) exit(EXIT_FAILURE); } DEFINE_TEST(depmod_detect_loop, +#if defined(KMOD_SYSCONFDIR_NOT_ETC) + .skip = true, +#endif .description = "check if depmod detects module loops correctly", .config = { [TC_UNAME_R] = "4.4.4", @@ -144,6 +150,9 @@ static noreturn int depmod_search_order_external_first(const struct test *t) exit(EXIT_FAILURE); } DEFINE_TEST(depmod_search_order_external_first, +#if defined(KMOD_SYSCONFDIR_NOT_ETC) + .skip = true, +#endif .description = "check if depmod honor external keyword with higher priority", .config = { [TC_UNAME_R] = "4.4.4", @@ -196,6 +205,9 @@ static noreturn int depmod_search_order_override(const struct test *t) exit(EXIT_FAILURE); } DEFINE_TEST(depmod_search_order_override, +#if defined(KMOD_SYSCONFDIR_NOT_ETC) + .skip = true, +#endif .description = "check if depmod honor override keyword", .config = { [TC_UNAME_R] = "4.4.4", diff --git a/testsuite/test-modprobe.c b/testsuite/test-modprobe.c index f908d56..f6bed8b 100644 --- a/testsuite/test-modprobe.c +++ b/testsuite/test-modprobe.c @@ -83,6 +83,9 @@ static noreturn int modprobe_show_alias_to_none(const struct test *t) exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_show_alias_to_none, +#if defined(KMOD_SYSCONFDIR_NOT_ETC) + .skip = true, +#endif .description = "check if modprobe --show-depends doesn't explode with an alias to nothing", .config = { [TC_UNAME_R] = "4.4.4", @@ -172,6 +175,9 @@ static noreturn int modprobe_softdep_loop(const struct test *t) exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_softdep_loop, +#if defined(KMOD_SYSCONFDIR_NOT_ETC) + .skip = true, +#endif .description = "check if modprobe breaks softdep loop", .config = { [TC_UNAME_R] = "4.4.4", -- cgit v1.2.3 From c3771eddcb6385e94055d00050db4340b6e86530 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 7 Jan 2021 19:51:40 -0800 Subject: README: remove leftover from semaphoreci We are not currently using semaphoreci, so remove leftover status from README. --- README | 3 --- 1 file changed, 3 deletions(-) diff --git a/README b/README index a0226e3..b541db9 100644 --- a/README +++ b/README @@ -3,9 +3,6 @@ kmod - Linux kernel module handling Information =========== -Build Status: - https://lucasdemarchi.semaphoreci.com/projects/kmod - Mailing list: linux-modules@vger.kernel.org (no subscription needed) https://lore.kernel.org/linux-modules/ -- cgit v1.2.3 From fa67110f896cdef67f42cbc2206ae2a8524acee6 Mon Sep 17 00:00:00 2001 From: Marco d'Itri Date: Thu, 7 Jan 2021 20:17:48 -0800 Subject: Fix "modinfo -F always shows name for built-ins" Bug reported by Ben Hutchings : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=970871 Now that the kernel provides module information for potentially modular code that's actually built-in, it's possible to query these built-ins with "modinfo -F". However, this doesn't work quite right: $ modinfo -Flicense e1000e GPL v2 $ modinfo -Flicense bitrev name: bitrev GPL --- tools/modinfo.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/modinfo.c b/tools/modinfo.c index 0231bb0..f6a971f 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -178,7 +178,11 @@ static int modinfo_do(struct kmod_module *mod) is_builtin = (filename == NULL); if (is_builtin) { - printf("%-16s%s%c", "name:", kmod_module_get_name(mod), separator); + if (field == NULL) + printf("%-16s%s%c", "name:", + kmod_module_get_name(mod), separator); + else if (field != NULL && streq(field, "name")) + printf("%s%c", kmod_module_get_name(mod), separator); filename = "(builtin)"; } -- cgit v1.2.3 From 67e43bbe042a44b0f224b96d9d065b94c5bf0405 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 18 Jan 2021 18:05:09 -0800 Subject: libkmod: Fix documentation on config precedence order /etc is has higher priority than /run. --- libkmod/libkmod.c | 2 +- man/depmod.d.xml | 2 +- man/modprobe.d.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libkmod/libkmod.c b/libkmod/libkmod.c index 43423d6..25655b9 100644 --- a/libkmod/libkmod.c +++ b/libkmod/libkmod.c @@ -235,7 +235,7 @@ static char *get_kernel_release(const char *dirname) * @config_paths: ordered array of paths (directories or files) where * to load from user-defined configuration parameters such as * alias, blacklists, commands (install, remove). If - * NULL defaults to /run/modprobe.d, /etc/modprobe.d and + * NULL defaults to /etc/modprobe.d, /run/modprobe.d and * /lib/modprobe.d. Give an empty vector if configuration should * not be read. This array must be null terminated. * diff --git a/man/depmod.d.xml b/man/depmod.d.xml index 4341a56..6472bda 100644 --- a/man/depmod.d.xml +++ b/man/depmod.d.xml @@ -40,8 +40,8 @@ /usr/lib/depmod.d/*.conf - /etc/depmod.d/*.conf /run/depmod.d/*.conf + /etc/depmod.d/*.conf DESCRIPTION diff --git a/man/modprobe.d.xml b/man/modprobe.d.xml index 211af84..a674d69 100644 --- a/man/modprobe.d.xml +++ b/man/modprobe.d.xml @@ -41,8 +41,8 @@ /lib/modprobe.d/*.conf - /etc/modprobe.d/*.conf /run/modprobe.d/*.conf + /etc/modprobe.d/*.conf DESCRIPTION -- cgit v1.2.3 From 1c10f3248378af987243049e0220964e3bdbbac0 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 18 Jan 2021 18:13:25 -0800 Subject: depmod: fix precedence order Configuration in /etc should have higher prio than /run. Given how rarely configuration in /run is used with depmod, this is likely not to cause any problems, even if it's a change in behavior. --- tools/depmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/depmod.c b/tools/depmod.c index 3f31cdf..8e1d9ec 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -51,8 +51,8 @@ static int verbose = DEFAULT_VERBOSE; static const char CFG_BUILTIN_KEY[] = "built-in"; static const char CFG_EXTERNAL_KEY[] = "external"; static const char *default_cfg_paths[] = { - "/run/depmod.d", SYSCONFDIR "/depmod.d", + "/run/depmod.d", "/lib/depmod.d", NULL }; -- cgit v1.2.3 From 9319b0f4cba5be851ae6ceced394f445b30bf07d Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 18 Jan 2021 18:22:31 -0800 Subject: Support /usr/local for configuration files Add /usr/local to the search path for configuration files. These are intended for local installs, provided /usr/local is given as prefix. --- libkmod/libkmod.c | 10 ++++++---- man/depmod.d.xml | 1 + man/modprobe.d.xml | 1 + tools/depmod.c | 1 + 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libkmod/libkmod.c b/libkmod/libkmod.c index 25655b9..7c2b889 100644 --- a/libkmod/libkmod.c +++ b/libkmod/libkmod.c @@ -64,6 +64,7 @@ static struct _index_files { static const char *default_config_paths[] = { SYSCONFDIR "/modprobe.d", "/run/modprobe.d", + "/usr/local/lib/modprobe.d", "/lib/modprobe.d", NULL }; @@ -234,10 +235,11 @@ static char *get_kernel_release(const char *dirname) * Otherwise, give an absolute dirname. * @config_paths: ordered array of paths (directories or files) where * to load from user-defined configuration parameters such as - * alias, blacklists, commands (install, remove). If - * NULL defaults to /etc/modprobe.d, /run/modprobe.d and - * /lib/modprobe.d. Give an empty vector if configuration should - * not be read. This array must be null terminated. + * alias, blacklists, commands (install, remove). If NULL + * defaults to /etc/modprobe.d, /run/modprobe.d, + * /usr/local/lib/modprobe.d and /lib/modprobe.d. Give an empty + * vector if configuration should not be read. This array must + * be null terminated. * * Create kmod library context. This reads the kmod configuration * and fills in the default values. diff --git a/man/depmod.d.xml b/man/depmod.d.xml index 6472bda..b315e93 100644 --- a/man/depmod.d.xml +++ b/man/depmod.d.xml @@ -40,6 +40,7 @@ /usr/lib/depmod.d/*.conf + /usr/local/lib/depmod.d/*.conf /run/depmod.d/*.conf /etc/depmod.d/*.conf diff --git a/man/modprobe.d.xml b/man/modprobe.d.xml index a674d69..0ab3e91 100644 --- a/man/modprobe.d.xml +++ b/man/modprobe.d.xml @@ -41,6 +41,7 @@ /lib/modprobe.d/*.conf + /usr/local/lib/modprobe.d/*.conf /run/modprobe.d/*.conf /etc/modprobe.d/*.conf diff --git a/tools/depmod.c b/tools/depmod.c index 8e1d9ec..170a1d8 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -53,6 +53,7 @@ static const char CFG_EXTERNAL_KEY[] = "external"; static const char *default_cfg_paths[] = { SYSCONFDIR "/depmod.d", "/run/depmod.d", + "/usr/local/lib/depmod.d", "/lib/depmod.d", NULL }; -- cgit v1.2.3 From 63fd63077de273d24574acb26ecf863587bf2ecc Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 20 Jan 2021 18:50:33 -0800 Subject: README: make github mirror official For some time I've been maintaining a read-only mirror on github. I think it's time to allow patches flowing from there besides the mailing list: I created a new org to host the project: https://github.com/kmod-project/kmod --- README | 4 +- README.md | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 4 deletions(-) diff --git a/README b/README index b541db9..59eb301 100644 --- a/README +++ b/README @@ -7,9 +7,6 @@ Mailing list: linux-modules@vger.kernel.org (no subscription needed) https://lore.kernel.org/linux-modules/ -Patchwork: - https://patchwork.kernel.org/project/linux-modules/ - Signed packages: http://www.kernel.org/pub/linux/utils/kernel/kmod/ @@ -20,6 +17,7 @@ Git: Gitweb: http://git.kernel.org/?p=utils/kernel/kmod/kmod.git + https://github.com/kmod-project/kmod Irc: #kmod on irc.freenode.org diff --git a/README.md b/README.md index d3b84bd..a83b4ac 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,128 @@ [![Coverity Scan Status](https://scan.coverity.com/projects/2096/badge.svg)](https://scan.coverity.com/projects/2096) -This is a ***mirror only***. Please see [README](../master/README) file for more information. + +Information +=========== + +Mailing list: + linux-modules@vger.kernel.org (no subscription needed) + https://lore.kernel.org/linux-modules/ + +Signed packages: + http://www.kernel.org/pub/linux/utils/kernel/kmod/ + +Git: + git://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git + http://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git + https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git + +Gitweb: + http://git.kernel.org/?p=utils/kernel/kmod/kmod.git + https://github.com/kmod-project/kmod + +Irc: + #kmod on irc.freenode.org + +License: + LGPLv2.1+ for libkmod, testsuite and helper libraries + GPLv2+ for tools/* + + +OVERVIEW +======== + +kmod is a set of tools to handle common tasks with Linux kernel modules like +insert, remove, list, check properties, resolve dependencies and aliases. + +These tools are designed on top of libkmod, a library that is shipped with +kmod. See libkmod/README for more details on this library and how to use it. +The aim is to be compatible with tools, configurations and indexes from +module-init-tools project. + +Compilation and installation +============================ + +In order to compiler the source code you need following software packages: + - GCC compiler + - GNU C library + +Optional dependencies: + - ZLIB library + - LZMA library + +Typical configuration: + ./configure CFLAGS="-g -O2" --prefix=/usr \ + --sysconfdir=/etc --libdir=/usr/lib + +Configure automatically searches for all required components and packages. + +To compile and install run: + make && make install + +Hacking +======= + +Run 'autogen.sh' script before configure. If you want to accept the recommended +flags, you just need to run 'autogen.sh c'. Note that the recommended +flags require cython be installed to compile successfully. + +Make sure to read the CODING-STYLE file and the other READMEs: libkmod/README +and testsuite/README. + +Compatibility with module-init-tools +==================================== + +kmod replaces module-init-tools, which is end-of-life. Most of its tools are +rewritten on top of libkmod so it can be used as a drop in replacements. +Somethings however were changed. Reasons vary from "the feature was already +long deprecated on module-init-tools" to "it would be too much trouble to +support it". + +There are several features that are being added in kmod, but we don't +keep track of them here. + +modprobe +-------- + +* 'modprobe -l' was marked as deprecated and does not exist anymore + +* 'modprobe -t' is gone, together with 'modprobe -l' + +* modprobe doesn't parse configuration files with names not ending in + '.alias' or '.conf'. modprobe used to warn about these files. + +* modprobe doesn't parse 'config' and 'include' commands in configuration + files. + +* modprobe from m-i-t does not honour softdeps for install commands. E.g.: + config: + + install bli "echo bli" + install bla "echo bla" + softdep bla pre: bli + + With m-i-t, the output of 'modprobe --show-depends bla' will be: + install "echo bla" + + While with kmod: + install "echo bli" + install "echo bla" + +* kmod doesn't dump the configuration as is in the config files. Instead it + dumps the configuration as it was parsed. Therefore, comments and file names + are not dumped, but on the good side we know what the exact configuration + kmod is using. We did this because if we only want to know the entire content + of configuration files, it's enough to use find(1) in modprobe.d directories + +depmod +------ + +* there's no 'depmod -m' option: legacy modules.*map files are gone + +lsmod +----- + +* module-init-tools used /proc/modules to parse module info. kmod uses + /sys/module/*, but there's a fallback to /proc/modules if the latter isn't + available -- cgit v1.2.3 From 3cee67ddd75114f9557ab7e13ef1751c277d9bd3 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Wed, 25 Mar 2020 11:03:58 -0400 Subject: populate-modules: Use more bash, more quotes We're already using associatives arrays, so there's no reason we should be using 'test'. --- testsuite/populate-modules.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/testsuite/populate-modules.sh b/testsuite/populate-modules.sh index 358e740..b0cc932 100755 --- a/testsuite/populate-modules.sh +++ b/testsuite/populate-modules.sh @@ -85,15 +85,15 @@ attach_pkcs7_array=( "test-modinfo/mod-simple-pkcs7.ko" ) -for k in ${!map[@]}; do +for k in "${!map[@]}"; do dst=${ROOTFS}/$k src=${MODULE_PLAYGROUND}/${map[$k]} - if test "${dst: -1}" = "/"; then - install -d $dst - install -t $dst $src + if [[ $dst = */ ]]; then + install -d "$dst" + install -t "$dst" "$src" else - install -D $src $dst + install -D "$src" "$dst" fi done @@ -101,7 +101,7 @@ done # gzip these modules for m in "${gzip_array[@]}"; do - gzip $ROOTFS/$m + gzip "$ROOTFS/$m" done # zstd-compress these modules @@ -110,13 +110,13 @@ for m in "${zstd_array[@]}"; do done for m in "${attach_sha1_array[@]}"; do - cat ${MODULE_PLAYGROUND}/dummy.sha1 >> ${ROOTFS}/$m + cat "${MODULE_PLAYGROUND}/dummy.sha1" >>"${ROOTFS}/$m" done for m in "${attach_sha256_array[@]}"; do - cat ${MODULE_PLAYGROUND}/dummy.sha256 >> ${ROOTFS}/$m + cat "${MODULE_PLAYGROUND}/dummy.sha256" >>"${ROOTFS}/$m" done for m in "${attach_pkcs7_array[@]}"; do - cat ${MODULE_PLAYGROUND}/dummy.pkcs7 >> ${ROOTFS}/$m + cat "${MODULE_PLAYGROUND}/dummy.pkcs7" >>"${ROOTFS}/$m" done -- cgit v1.2.3 From 1921c370c25cb4735105397c285ffa38a04b286b Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 29 Jan 2021 18:28:38 -0800 Subject: testsuite: compress modules if feature is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the output needs to be the same, regardless if the module is compressed, change populate-modules.sh to conditionally compress the module if that feature is enabled. This way we can execute the tests with any build-time configuration and it should still pass. Suggested-by: Michal Suchánek Reviewed-by: Michal Suchánek Tested-by: Michal Suchánek Reviewed-by: Petr Vorel --- Makefile.am | 2 +- testsuite/populate-modules.sh | 27 ++++++++++++++++++--------- testsuite/test-depmod.c | 2 -- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Makefile.am b/Makefile.am index b29e943..24a586e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -249,7 +249,7 @@ CREATE_ROOTFS = $(AM_V_GEN) ( $(RM) -rf $(ROOTFS) && mkdir -p $(dir $(ROOTFS)) & find $(ROOTFS) -type d -exec chmod +w {} \; && \ find $(ROOTFS) -type f -name .gitignore -exec rm -f {} \; && \ $(top_srcdir)/testsuite/populate-modules.sh \ - $(MODULE_PLAYGROUND) $(ROOTFS) ) && \ + $(MODULE_PLAYGROUND) $(ROOTFS) $(top_builddir)/config.h ) && \ touch testsuite/stamp-rootfs build-module-playground: diff --git a/testsuite/populate-modules.sh b/testsuite/populate-modules.sh index b0cc932..ae43884 100755 --- a/testsuite/populate-modules.sh +++ b/testsuite/populate-modules.sh @@ -4,6 +4,12 @@ set -e MODULE_PLAYGROUND=$1 ROOTFS=$2 +CONFIG_H=$3 + +feature_enabled() { + local feature=$1 + grep KMOD_FEATURES $CONFIG_H | head -n 1 | grep -q \+$feature +} declare -A map map=( @@ -99,15 +105,18 @@ done # start poking the final rootfs... -# gzip these modules -for m in "${gzip_array[@]}"; do - gzip "$ROOTFS/$m" -done - -# zstd-compress these modules -for m in "${zstd_array[@]}"; do - zstd --rm $ROOTFS/$m -done +# compress modules with each format if feature is enabled +if feature_enabled ZLIB; then + for m in "${gzip_array[@]}"; do + gzip "$ROOTFS/$m" + done +fi + +if feature_enabled ZSTD; then + for m in "${zstd_array[@]}"; do + zstd --rm $ROOTFS/$m + done +fi for m in "${attach_sha1_array[@]}"; do cat "${MODULE_PLAYGROUND}/dummy.sha1" >>"${ROOTFS}/$m" diff --git a/testsuite/test-depmod.c b/testsuite/test-depmod.c index 261559c..d7802d7 100644 --- a/testsuite/test-depmod.c +++ b/testsuite/test-depmod.c @@ -25,7 +25,6 @@ #include "testsuite.h" -#ifdef ENABLE_ZLIB #define MODULES_ORDER_UNAME "4.4.4" #define MODULES_ORDER_ROOTFS TESTSUITE_ROOTFS "test-depmod/modules-order-compressed" #define MODULES_ORDER_LIB_MODULES MODULES_ORDER_ROOTFS "/lib/modules/" MODULES_ORDER_UNAME @@ -57,7 +56,6 @@ DEFINE_TEST(depmod_modules_order_for_compressed, { } }, }); -#endif #define SEARCH_ORDER_SIMPLE_ROOTFS TESTSUITE_ROOTFS "test-depmod/search-order-simple" static noreturn int depmod_search_order_simple(const struct test *t) -- cgit v1.2.3 From fd71604da9d9bab91f270deacceecc0d5c0fcffd Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 29 Jan 2021 18:34:30 -0800 Subject: testsuite: also test xz compression Reviewed-by: Petr Vorel --- testsuite/populate-modules.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/testsuite/populate-modules.sh b/testsuite/populate-modules.sh index ae43884..099f026 100755 --- a/testsuite/populate-modules.sh +++ b/testsuite/populate-modules.sh @@ -72,6 +72,9 @@ map=( gzip_array=( "test-depmod/modules-order-compressed/lib/modules/4.4.4/kernel/drivers/block/cciss.ko" + ) + +xz_array=( "test-depmod/modules-order-compressed/lib/modules/4.4.4/kernel/drivers/scsi/scsi_mod.ko" ) @@ -112,6 +115,12 @@ if feature_enabled ZLIB; then done fi +if feature_enabled XZ; then + for m in "${xz_array[@]}"; do + xz "$ROOTFS/$m" + done +fi + if feature_enabled ZSTD; then for m in "${zstd_array[@]}"; do zstd --rm $ROOTFS/$m -- cgit v1.2.3 From 01ed9af61e239b40514edf527ac87c79377266ac Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 12 Feb 2021 01:45:21 -0800 Subject: libkmod-config: revamp kcmdline parsing into a state machine The handling of spaces and quotes is becoming hard to maintain. Convert the parser into a state machine so we can check all the states. This should make it easier to fix a corner case we have right now: The kernel also accepts a quote before the module name instead of the value. But this additional is left for later. This is purely an algorithm change with no behavior change. Tested-by: Jessica Yu --- libkmod/libkmod-config.c | 86 +++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c index 971f20b..d3cd10d 100644 --- a/libkmod/libkmod-config.c +++ b/libkmod/libkmod-config.c @@ -499,7 +499,14 @@ static int kmod_config_parse_kcmdline(struct kmod_config *config) char buf[KCMD_LINE_SIZE]; int fd, err; char *p, *modname, *param = NULL, *value = NULL; - bool is_quoted = false, is_module = true; + bool is_quoted = false, iter = true; + enum state { + STATE_IGNORE, + STATE_MODNAME, + STATE_PARAM, + STATE_VALUE, + STATE_COMPLETE, + } state; fd = open("/proc/cmdline", O_RDONLY|O_CLOEXEC); if (fd < 0) { @@ -516,54 +523,65 @@ static int kmod_config_parse_kcmdline(struct kmod_config *config) return err; } - for (p = buf, modname = buf; *p != '\0' && *p != '\n'; p++) { - if (*p == '"') { + state = STATE_MODNAME; + for (p = buf, modname = buf; iter; p++) { + switch (*p) { + case '"': is_quoted = !is_quoted; - - if (is_quoted) { - /* don't consider a module until closing quotes */ - is_module = false; - } else if (param != NULL && value != NULL) { + break; + case '\0': + case '\n': + /* Stop iterating on new chars */ + iter = false; + /* fall-through */ + case ' ': + if (is_quoted && state == STATE_VALUE) { + /* no state change*/; + } else if (is_quoted) { + /* spaces are only allowed in the value part */ + state = STATE_IGNORE; + } else if (state == STATE_VALUE || state == STATE_PARAM) { + *p = '\0'; + state = STATE_COMPLETE; + } else { /* - * If we are indeed expecting a value and - * closing quotes, then this can be considered - * a valid option for a module + * go to next option, ignoring any possible + * partial match we have */ - is_module = true; + modname = p + 1; + state = STATE_MODNAME; } - - continue; - } - if (is_quoted) - continue; - - switch (*p) { - case ' ': - *p = '\0'; - if (is_module) - kcmdline_parse_result(config, modname, param, value); - param = value = NULL; - modname = p + 1; - is_module = true; break; case '.': - if (param == NULL) { + if (state == STATE_MODNAME) { *p = '\0'; param = p + 1; + state = STATE_PARAM; + } else if (state == STATE_PARAM) { + state = STATE_IGNORE; } break; case '=': - if (param != NULL) + if (state == STATE_PARAM) { + /* + * Don't set *p to '\0': the value var shadows + * param + */ value = p + 1; - else - is_module = false; + state = STATE_VALUE; + } else if (state == STATE_MODNAME) { + state = STATE_IGNORE; + } break; } - } - *p = '\0'; - if (is_module) - kcmdline_parse_result(config, modname, param, value); + if (state == STATE_COMPLETE) { + kcmdline_parse_result(config, modname, param, value); + /* start over on next iteration */ + modname = p + 1; + state = STATE_MODNAME; + } + } return 0; } -- cgit v1.2.3 From d3a1fe67b64cad103ff4f93dfd9f2cf19cab09ba Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 12 Feb 2021 01:45:22 -0800 Subject: libkmod-config: re-quote option from kernel cmdline It was reported that grub mangles the kernel cmdline. It turns acpi_cpufreq.dyndbg="file drivers/cpufreq/acpi-cpufreq.c +mpf" into "acpi_cpufreq.dyndbg=file drivers/cpufreq/acpi-cpufreq.c +mpf" However, even though we could blame grub for doing that, the kernel happily accepts and re-quotes it when the module is built-in. So, it's better if kmod also understands it this way and does the same. Here we basically add additional code to un-mangle it, moving the quote in way that is acceptable to pass through init_module(). Note that the interface [f]init_module() gives us mandates the quote to be part of the value: the module name is not passed and the options are separated by space. Reported-by: Jiri Slaby Tested-by: Jessica Yu Link: https://bugzilla.suse.com/show_bug.cgi?id=1181111#c10 --- libkmod/libkmod-config.c | 36 +++++++++++++++- .../module-param-kcmdline7/correct.txt | 5 +++ .../module-param-kcmdline7/correct.txt | 5 +++ .../module-param-kcmdline7/proc/cmdline | 1 + .../module-param-kcmdline7/proc/cmdline | 1 + .../module-param-kcmdline8/correct.txt | 5 +++ .../module-param-kcmdline7/correct.txt | 5 +++ .../module-param-kcmdline7/proc/cmdline | 1 + .../module-param-kcmdline8/proc/cmdline | 1 + testsuite/test-modprobe.c | 50 ++++++++++++++++++++++ 10 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/correct.txt create mode 100644 testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/correct.txt create mode 100644 testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/proc/cmdline create mode 100644 testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/proc/cmdline create mode 100644 testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/correct.txt create mode 100644 testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/correct.txt create mode 100644 testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/proc/cmdline create mode 100644 testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/proc/cmdline diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c index d3cd10d..2873f06 100644 --- a/libkmod/libkmod-config.c +++ b/libkmod/libkmod-config.c @@ -498,7 +498,7 @@ static int kmod_config_parse_kcmdline(struct kmod_config *config) { char buf[KCMD_LINE_SIZE]; int fd, err; - char *p, *modname, *param = NULL, *value = NULL; + char *p, *p_quote_start, *modname, *param = NULL, *value = NULL; bool is_quoted = false, iter = true; enum state { STATE_IGNORE, @@ -524,10 +524,23 @@ static int kmod_config_parse_kcmdline(struct kmod_config *config) } state = STATE_MODNAME; + p_quote_start = NULL; for (p = buf, modname = buf; iter; p++) { switch (*p) { case '"': is_quoted = !is_quoted; + + /* + * only allow starting quote as first char when looking + * for a modname: anything else is considered ill-formed + */ + if (is_quoted && state == STATE_MODNAME && p == modname) { + p_quote_start = p; + modname = p + 1; + } else if (state != STATE_VALUE) { + state = STATE_IGNORE; + } + break; case '\0': case '\n': @@ -550,6 +563,7 @@ static int kmod_config_parse_kcmdline(struct kmod_config *config) */ modname = p + 1; state = STATE_MODNAME; + p_quote_start = NULL; } break; case '.': @@ -576,10 +590,30 @@ static int kmod_config_parse_kcmdline(struct kmod_config *config) } if (state == STATE_COMPLETE) { + /* + * We may need to re-quote to unmangle what the + * bootloader passed. Example: grub passes the option as + * "parport.dyndbg=file drivers/parport/ieee1284_ops.c +mpf" + * instead of + * parport.dyndbg="file drivers/parport/ieee1284_ops.c +mpf" + */ + if (p_quote_start && p_quote_start < modname) { + /* + * p_quote_start + * | + * |modname param value + * || | | + * vv v v + * "parport\0dyndbg=file drivers/parport/ieee1284_ops.c +mpf" */ + memmove(p_quote_start, modname, value - modname); + value--; modname--; param--; + *value = '"'; + } kcmdline_parse_result(config, modname, param, value); /* start over on next iteration */ modname = p + 1; state = STATE_MODNAME; + p_quote_start = NULL; } } diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/correct.txt new file mode 100644 index 0000000..d80da6d --- /dev/null +++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/correct.txt @@ -0,0 +1,5 @@ +options psmouse foo +options parport dyndbg="file drivers/parport/ieee1284_ops.c +mpf" + +# End of configuration files. Dumping indexes now: + diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/correct.txt new file mode 100644 index 0000000..d80da6d --- /dev/null +++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/correct.txt @@ -0,0 +1,5 @@ +options psmouse foo +options parport dyndbg="file drivers/parport/ieee1284_ops.c +mpf" + +# End of configuration files. Dumping indexes now: + diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/proc/cmdline new file mode 100644 index 0000000..86f9052 --- /dev/null +++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/proc/cmdline @@ -0,0 +1 @@ +psmouse.foo parport.dyndbg="file drivers/parport/ieee1284_ops.c +mpf" quiet rw diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/proc/cmdline new file mode 100644 index 0000000..86f9052 --- /dev/null +++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/proc/cmdline @@ -0,0 +1 @@ +psmouse.foo parport.dyndbg="file drivers/parport/ieee1284_ops.c +mpf" quiet rw diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/correct.txt new file mode 100644 index 0000000..d80da6d --- /dev/null +++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/correct.txt @@ -0,0 +1,5 @@ +options psmouse foo +options parport dyndbg="file drivers/parport/ieee1284_ops.c +mpf" + +# End of configuration files. Dumping indexes now: + diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/correct.txt new file mode 100644 index 0000000..d80da6d --- /dev/null +++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/correct.txt @@ -0,0 +1,5 @@ +options psmouse foo +options parport dyndbg="file drivers/parport/ieee1284_ops.c +mpf" + +# End of configuration files. Dumping indexes now: + diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/proc/cmdline new file mode 100644 index 0000000..86f9052 --- /dev/null +++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/proc/cmdline @@ -0,0 +1 @@ +psmouse.foo parport.dyndbg="file drivers/parport/ieee1284_ops.c +mpf" quiet rw diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/proc/cmdline new file mode 100644 index 0000000..eab04ad --- /dev/null +++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/proc/cmdline @@ -0,0 +1 @@ +psmouse.foo "parport.dyndbg=file drivers/parport/ieee1284_ops.c +mpf" quiet rw diff --git a/testsuite/test-modprobe.c b/testsuite/test-modprobe.c index f6bed8b..dbc54f3 100644 --- a/testsuite/test-modprobe.c +++ b/testsuite/test-modprobe.c @@ -359,6 +359,56 @@ DEFINE_TEST(modprobe_param_kcmdline6, ); +static noreturn int modprobe_param_kcmdline7(const struct test *t) +{ + const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; + const char *const args[] = { + progname, + "-c", + NULL, + }; + + test_spawn_prog(progname, args); + exit(EXIT_FAILURE); +} +DEFINE_TEST(modprobe_param_kcmdline7, + .description = "check if dots on other parts of kcmdline don't confuse our parser", + .config = { + [TC_UNAME_R] = "4.4.4", + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline7", + }, + .output = { + .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline7/correct.txt", + }, + .modules_loaded = "", + ); + + +static noreturn int modprobe_param_kcmdline8(const struct test *t) +{ + const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; + const char *const args[] = { + progname, + "-c", + NULL, + }; + + test_spawn_prog(progname, args); + exit(EXIT_FAILURE); +} +DEFINE_TEST(modprobe_param_kcmdline8, + .description = "check if dots on other parts of kcmdline don't confuse our parser", + .config = { + [TC_UNAME_R] = "4.4.4", + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline8", + }, + .output = { + .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline8/correct.txt", + }, + .modules_loaded = "", + ); + + static noreturn int modprobe_force(const struct test *t) { const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; -- cgit v1.2.3 From b77251f08d3c1acc28f1f453da5e3971d50e0bc2 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 12 Feb 2021 01:45:23 -0800 Subject: testsuite: allow to re-use single function for tests Add a new DEFINE_TEST_WITH_FUNC() that accepts the function alongside the test name. This will allow us to share a single function for different tests. --- testsuite/testsuite.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/testsuite/testsuite.h b/testsuite/testsuite.h index c74b648..44d1730 100644 --- a/testsuite/testsuite.h +++ b/testsuite/testsuite.h @@ -140,14 +140,16 @@ int test_run(const struct test *t); /* Test definitions */ -#define DEFINE_TEST(_name, ...) \ +#define DEFINE_TEST_WITH_FUNC(_name, _func, ...) \ static const struct test UNIQ(s##_name) \ __attribute__((used, section("kmod_tests"), aligned(8))) = { \ .name = #_name, \ - .func = _name, \ + .func = _func, \ ## __VA_ARGS__ \ }; +#define DEFINE_TEST(_name, ...) DEFINE_TEST_WITH_FUNC(_name, _name, __VA_ARGS__) + #define TESTSUITE_MAIN() \ extern struct test __start_kmod_tests[] __attribute__((weak, visibility("hidden"))); \ extern struct test __stop_kmod_tests[] __attribute__((weak, visibility("hidden"))); \ -- cgit v1.2.3 From d8b31c34a6b487123ee935762bbd3c7046607249 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 12 Feb 2021 01:45:24 -0800 Subject: test-modprobe: share single function for kcmdline tests --- testsuite/test-modprobe.c | 95 +++++------------------------------------------ 1 file changed, 10 insertions(+), 85 deletions(-) diff --git a/testsuite/test-modprobe.c b/testsuite/test-modprobe.c index dbc54f3..0255f1a 100644 --- a/testsuite/test-modprobe.c +++ b/testsuite/test-modprobe.c @@ -213,7 +213,7 @@ DEFINE_TEST(modprobe_install_cmd_loop, .modules_loaded = "mod-loop-b,mod-loop-a", ); -static noreturn int modprobe_param_kcmdline(const struct test *t) +static noreturn int modprobe_param_kcmdline_show_deps(const struct test *t) { const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; const char *const args[] = { @@ -225,7 +225,7 @@ static noreturn int modprobe_param_kcmdline(const struct test *t) test_spawn_prog(progname, args); exit(EXIT_FAILURE); } -DEFINE_TEST(modprobe_param_kcmdline, +DEFINE_TEST(modprobe_param_kcmdline_show_deps, .description = "check if params from kcmdline are passed to (f)init_module call", .config = { [TC_UNAME_R] = "4.4.4", @@ -237,7 +237,7 @@ DEFINE_TEST(modprobe_param_kcmdline, .modules_loaded = "", ); -static noreturn int modprobe_param_kcmdline2(const struct test *t) +static noreturn int modprobe_param_kcmdline(const struct test *t) { const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; const char *const args[] = { @@ -249,7 +249,7 @@ static noreturn int modprobe_param_kcmdline2(const struct test *t) test_spawn_prog(progname, args); exit(EXIT_FAILURE); } -DEFINE_TEST(modprobe_param_kcmdline2, +DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline2, modprobe_param_kcmdline, .description = "check if params with no value are parsed correctly from kcmdline", .config = { [TC_UNAME_R] = "4.4.4", @@ -261,19 +261,7 @@ DEFINE_TEST(modprobe_param_kcmdline2, .modules_loaded = "", ); -static noreturn int modprobe_param_kcmdline3(const struct test *t) -{ - const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; - const char *const args[] = { - progname, - "-c", - NULL, - }; - - test_spawn_prog(progname, args); - exit(EXIT_FAILURE); -} -DEFINE_TEST(modprobe_param_kcmdline3, +DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline3, modprobe_param_kcmdline, .description = "check if unrelated strings in kcmdline are correctly ignored", .config = { [TC_UNAME_R] = "4.4.4", @@ -285,19 +273,7 @@ DEFINE_TEST(modprobe_param_kcmdline3, .modules_loaded = "", ); -static noreturn int modprobe_param_kcmdline4(const struct test *t) -{ - const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; - const char *const args[] = { - progname, - "-c", - NULL, - }; - - test_spawn_prog(progname, args); - exit(EXIT_FAILURE); -} -DEFINE_TEST(modprobe_param_kcmdline4, +DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline4, modprobe_param_kcmdline, .description = "check if unrelated strings in kcmdline are correctly ignored", .config = { [TC_UNAME_R] = "4.4.4", @@ -309,19 +285,7 @@ DEFINE_TEST(modprobe_param_kcmdline4, .modules_loaded = "", ); -static noreturn int modprobe_param_kcmdline5(const struct test *t) -{ - const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; - const char *const args[] = { - progname, - "-c", - NULL, - }; - - test_spawn_prog(progname, args); - exit(EXIT_FAILURE); -} -DEFINE_TEST(modprobe_param_kcmdline5, +DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline5, modprobe_param_kcmdline, .description = "check if params with spaces are parsed correctly from kcmdline", .config = { [TC_UNAME_R] = "4.4.4", @@ -333,20 +297,7 @@ DEFINE_TEST(modprobe_param_kcmdline5, .modules_loaded = "", ); - -static noreturn int modprobe_param_kcmdline6(const struct test *t) -{ - const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; - const char *const args[] = { - progname, - "-c", - NULL, - }; - - test_spawn_prog(progname, args); - exit(EXIT_FAILURE); -} -DEFINE_TEST(modprobe_param_kcmdline6, +DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline6, modprobe_param_kcmdline, .description = "check if dots on other parts of kcmdline don't confuse our parser", .config = { [TC_UNAME_R] = "4.4.4", @@ -358,20 +309,7 @@ DEFINE_TEST(modprobe_param_kcmdline6, .modules_loaded = "", ); - -static noreturn int modprobe_param_kcmdline7(const struct test *t) -{ - const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; - const char *const args[] = { - progname, - "-c", - NULL, - }; - - test_spawn_prog(progname, args); - exit(EXIT_FAILURE); -} -DEFINE_TEST(modprobe_param_kcmdline7, +DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline7, modprobe_param_kcmdline, .description = "check if dots on other parts of kcmdline don't confuse our parser", .config = { [TC_UNAME_R] = "4.4.4", @@ -383,20 +321,7 @@ DEFINE_TEST(modprobe_param_kcmdline7, .modules_loaded = "", ); - -static noreturn int modprobe_param_kcmdline8(const struct test *t) -{ - const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe"; - const char *const args[] = { - progname, - "-c", - NULL, - }; - - test_spawn_prog(progname, args); - exit(EXIT_FAILURE); -} -DEFINE_TEST(modprobe_param_kcmdline8, +DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline8, modprobe_param_kcmdline, .description = "check if dots on other parts of kcmdline don't confuse our parser", .config = { [TC_UNAME_R] = "4.4.4", -- cgit v1.2.3 From 8742be0aa5ed14d28980eb706b08e8bdf650f21c Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 10 Mar 2021 08:33:01 -0800 Subject: libkmod-config: more chars allowed as space Recently in a discussion I noticed that kernel allows more chars to be considered as space in the kernel command line. Switch to the equivalent of isspace() instead of considering only ' '. --- libkmod/libkmod-config.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c index 2873f06..4fdd40f 100644 --- a/libkmod/libkmod-config.c +++ b/libkmod/libkmod-config.c @@ -543,11 +543,14 @@ static int kmod_config_parse_kcmdline(struct kmod_config *config) break; case '\0': - case '\n': - /* Stop iterating on new chars */ iter = false; /* fall-through */ case ' ': + case '\n': + case '\t': + case '\v': + case '\f': + case '\r': if (is_quoted && state == STATE_VALUE) { /* no state change*/; } else if (is_quoted) { -- cgit v1.2.3 From 39dd171623744ac390dadf487c5a3ebf0b69f2ca Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 9 Apr 2021 18:44:23 +0900 Subject: libkmod-config: fix a memory leak when kmod_list_append() fails From kmod_config_new(), when kmod_list_append() fails, fix not list-appended kmod_config_path leak. Signed-off-by: Seung-Woo Kim --- libkmod/libkmod-config.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c index 4fdd40f..e83621b 100644 --- a/libkmod/libkmod-config.c +++ b/libkmod/libkmod-config.c @@ -909,8 +909,10 @@ int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config, memcpy(cf->path, path, pathlen); tmp = kmod_list_append(path_list, cf); - if (tmp == NULL) + if (tmp == NULL) { + free(cf); goto oom; + } path_list = tmp; } -- cgit v1.2.3 From ed892ff4edfe99e4ca0aca160e7b875ddefb1ec8 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Sat, 17 Apr 2021 13:39:12 -0700 Subject: gitignore: ignore .mbx and .cover for b4 integration Lately I'm using b4 to work with the patches in the mailing list. Better to start ignoring .cover and .mbx files since they get created by b4. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 2347858..f823511 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ *.gcno /*.tar.xz /*.md5sum +/*.mbx +/*.cover .deps/ .libs/ /Makefile -- cgit v1.2.3 From 1cab02ecf6ee2a0aa34f3615dfd99c59f7e04e90 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Tue, 13 Apr 2021 20:23:14 +0900 Subject: libkmod: fix an overflow with wrong modules.builtin.modinfo Fix a possbile overflow with exact PATH_MAX length modname in wrong modules.builtin.modinfo. Signed-off-by: Seung-Woo Kim --- libkmod/libkmod-builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libkmod/libkmod-builtin.c b/libkmod/libkmod-builtin.c index fc9a376..a75a542 100644 --- a/libkmod/libkmod-builtin.c +++ b/libkmod/libkmod-builtin.c @@ -246,7 +246,7 @@ bool kmod_builtin_iter_get_modname(struct kmod_builtin_iter *iter, len = dot - line; - if (len > PATH_MAX) { + if (len >= PATH_MAX) { sv_errno = ENAMETOOLONG; goto fail; } -- cgit v1.2.3 From 675410c3b3b1cf4523f02ab6e3128c39bd5d5101 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Tue, 13 Apr 2021 20:23:15 +0900 Subject: libkmod: fix possible double free with wrong modules.builtin.modinfo Fix double free for *modinfo with non '\0' terminated wrong modules.builtin.modinfo, which is because EOF is minus value. Signed-off-by: Seung-Woo Kim --- libkmod/libkmod-builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libkmod/libkmod-builtin.c b/libkmod/libkmod-builtin.c index a75a542..a002cb5 100644 --- a/libkmod/libkmod-builtin.c +++ b/libkmod/libkmod-builtin.c @@ -313,7 +313,7 @@ ssize_t kmod_builtin_get_modinfo(struct kmod_ctx *ctx, const char *modname, while (offset < iter->next) { offset = get_string(iter, pos, &line, &linesz); if (offset <= 0) { - count = (offset) ? -errno : -EOF; + count = (offset) ? -errno : -EINVAL; free(*modinfo); goto fail; } -- cgit v1.2.3 From 729f0f685336e7aa91d1a0236a8f09804d261b90 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 11 May 2021 09:47:09 -0700 Subject: Fix return value doc for kmod_module_get_info() We don't return 0 on success, we return the number of elements we added to the list. --- libkmod/libkmod-module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 76a6dc3..b6320cc 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -2277,7 +2277,7 @@ list_error: * * After use, free the @list by calling kmod_module_info_free_list(). * - * Returns: 0 on success or < 0 otherwise. + * Returns: number of entries in @list on success or < 0 otherwise. */ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_list **list) { -- cgit v1.2.3 From f0a136076189b50e252773ff79d800e56e840b14 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 11 May 2021 09:48:04 -0700 Subject: depmod: fix modules.builtin.alias.bin output Due to wrong documentation on kmod_module_get_info() we ended up checking for 0 as return. Check for > 0 to decided if we want to write the index to the file, otherwise we would output a 0-sized index on success. --- tools/depmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/depmod.c b/tools/depmod.c index 170a1d8..eb810b8 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -2457,7 +2457,7 @@ static int output_builtin_alias_bin(struct depmod *depmod, FILE *out) out: /* do not bother writing the index if we are going to discard it */ - if (!ret) + if (ret > 0) index_write(idx, out); if (builtin) -- cgit v1.2.3 From b07bfb4a10c8cceb2e13da8a7d0208f70af3a675 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 11 May 2021 09:57:10 -0700 Subject: testsuite: update gitignore --- testsuite/module-playground/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/module-playground/.gitignore b/testsuite/module-playground/.gitignore index fca12f3..6d9c7b1 100644 --- a/testsuite/module-playground/.gitignore +++ b/testsuite/module-playground/.gitignore @@ -1,4 +1,3 @@ -*o.cmd *.ko !mod-simple-*.ko !cache/*.ko @@ -8,6 +7,7 @@ *.mod *.a *.cmd +*.o.d modules.order Module.symvers -- cgit v1.2.3 From b6ecfc916a17eab8f93be5b09f4e4f845aabd3d1 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 20 May 2021 16:02:57 -0700 Subject: kmod 29 --- Makefile.am | 2 +- NEWS | 46 ++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 24a586e..d859c24 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,7 +58,7 @@ SED_PROCESS = \ # 6. If any interfaces have been removed or changed since the last public # release, then set age to 0. LIBKMOD_CURRENT=5 -LIBKMOD_REVISION=6 +LIBKMOD_REVISION=7 LIBKMOD_AGE=3 noinst_LTLIBRARIES = shared/libshared.la diff --git a/NEWS b/NEWS index ae56657..a8c9194 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,49 @@ +kmod 29 +======= + +- Improvements + - Add support to use /usr/local as a place for configuration files. This makes it easier + to install locally without overriding distro files. + +- Bug fixes + - Fix `modinfo -F` when module is builtin: when we asked by a specific field from modinfo, + it was not working correctly if the module was builtin + + - Documentation fixes on precedence order of /etc and /run: the correct order is + /etc/modprobe.d, /run/modprobe.d, /lib/modprobe.d + + - Fix the priority order that we use for searching configuration files. The + correct one is /etc, /run, /usr/local/lib, /lib, for both modprobe.d + and depmo.d + + - Fix kernel command line parsing when there are quotes present. Grub + mangles the command line and changes it from 'module.option="val with + spaces"' to '"module.option=val with spaces"'. Although this is weird + behavior and grub could have been fixed, the kernel understands it + correctly for builtin modules. So change libkmod to also parse it + correctly. This also brings another hidden behavior from the kernel: + newline in the kernel command line is also allowed and can be used to + separate options. + + - Fix a memory leak, overflow and double free on error path + + - Fix documentation for return value from kmod_module_get_info(): we + return the number of entries we added to the list + + - Fix output of modules.builtin.alias.bin index: we were writing an empty file due to + the misuse of kmod_module_get_info() + +- Infra/internal + - Retire integration with semaphoreci + + - Declare the github mirror also as an official upstream source: now besides accepting + patches via mailing list, PRs on github are also acceptable + + - Misc improvements to testsuite, so we can use it reliably regardless + of the configuration used: now tests will skip if we don't have the + build dependencies) + + kmod 28 ======= diff --git a/configure.ac b/configure.ac index 222de3e..136d5b7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.64) AC_INIT([kmod], - [28], + [29], [linux-modules@vger.kernel.org], [kmod], [http://git.kernel.org/?p=utils/kernel/kmod/kmod.git]) -- cgit v1.2.3 From 64541d6aad210879e104e4796beeef49d4311f6d Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Tue, 8 Jun 2021 09:29:22 +0300 Subject: libkmod-module: check "new_from_name" return value in get_builtin kmod_module_new_from_name() may fail and return error value. It is handled properly across the code, but in this particular place the check is missing. Signed-off-by: Yauheni Kaliuta --- libkmod/libkmod-module.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index b6320cc..6e0ff1a 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -2912,7 +2912,10 @@ int kmod_module_get_builtin(struct kmod_ctx *ctx, struct kmod_list **list) goto fail; } - kmod_module_new_from_name(ctx, modname, &mod); + err = kmod_module_new_from_name(ctx, modname, &mod); + if (err < 0) + goto fail; + kmod_module_set_builtin(mod, true); *list = kmod_list_append(*list, mod); -- cgit v1.2.3 From 43bdf97ce1298c8727effb470291ed884e1161e6 Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Mon, 9 Aug 2021 22:16:00 -0700 Subject: libkmod: add a library notice log level print When you use pass the -v argument to modprobe we bump the log level from the default modprobe log level of LOG_WARNING (4) to LOG_NOTICE (5), however the library only has avaiable to print: #define DBG(ctx, arg...) kmod_log_cond(ctx, LOG_DEBUG, ## arg) #define INFO(ctx, arg...) kmod_log_cond(ctx, LOG_INFO, ## arg) #define ERR(ctx, arg...) kmod_log_cond(ctx, LOG_ERR, ## arg) LOG_INFO (6) however is too high of a level for it to be effective at printing anything when modprobe -v is passed. And so the only way in which modprobe -v can trigger the library to print a verbose message is to use ERR() but that always prints something and we don't want that in some situations. We need to add a new log level macro which uses LOG_NOTICE (5) for a "normal but significant condition" which users and developers can use to look underneath the hood to confirm if a situation is happening. Signed-off-by: Luis Chamberlain Signed-off-by: Lucas De Marchi --- libkmod/libkmod-internal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libkmod/libkmod-internal.h b/libkmod/libkmod-internal.h index 398af9c..c22644a 100644 --- a/libkmod/libkmod-internal.h +++ b/libkmod/libkmod-internal.h @@ -25,10 +25,12 @@ static _always_inline_ _printf_format_(2, 3) void # else # define DBG(ctx, arg...) kmod_log_null(ctx, ## arg) # endif +# define NOTICE(ctx, arg...) kmod_log_cond(ctx, LOG_NOTICE, ## arg) # define INFO(ctx, arg...) kmod_log_cond(ctx, LOG_INFO, ## arg) # define ERR(ctx, arg...) kmod_log_cond(ctx, LOG_ERR, ## arg) #else # define DBG(ctx, arg...) kmod_log_null(ctx, ## arg) +# define NOTICE(ctx, arg...) kmod_log_null(ctx, ## arg) # define INFO(ctx, arg...) kmod_log_null(ctx, ## arg) # define ERR(ctx, arg...) kmod_log_null(ctx, ## arg) #endif -- cgit v1.2.3 From 4e391ac92d1b9a2c8c0e9d8735d2913ee86c0ad8 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Wed, 18 Aug 2021 22:52:00 +0200 Subject: libkmod: Set builtin to no when module is created from path. A recent bug report showed that modinfo doesn't give the signature information for certain modules, and it turned out to happen only on the modules that are built-in on the running kernel; then modinfo skips the signature check, as if the target module file never exists. The behavior is, however, inconsistent when modinfo is performed for external modules (no matter which kernel version is) and the module file path is explicitly given by a command-line argument, which guarantees the presence of the module file itself. Fixes: e7e2cb61fa9f ("modinfo: Show information about built-in modules") Link: https://lore.kernel.org/linux-modules/CAKi4VAJVvY3=JdSZm-GD1hJqyCPYaYz-jBJ_REeY5BakVb6_ww@mail.gmail.com/ BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1189537 Suggested-by: Lucas De Marchi Signed-off-by: Michal Suchanek Reviewed-by: Petr Vorel --- libkmod/libkmod-module.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 6e0ff1a..6f7747c 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -431,17 +431,18 @@ KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx, return -EEXIST; } - *mod = kmod_module_ref(m); - return 0; - } + kmod_module_ref(m); + } else { + err = kmod_module_new(ctx, name, name, namelen, NULL, 0, &m); + if (err < 0) { + free(abspath); + return err; + } - err = kmod_module_new(ctx, name, name, namelen, NULL, 0, &m); - if (err < 0) { - free(abspath); - return err; + m->path = abspath; } - m->path = abspath; + m->builtin = KMOD_MODULE_BUILTIN_NO; *mod = m; return 0; -- cgit v1.2.3 From a965641625dab1688b202e1f8b8b52497d75eeb1 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 9 Feb 2022 18:21:03 -0800 Subject: libkmod: Prefer builtin index over builtin.alias The modules.builtin.alias.bin is way larger than the modules.builtin.bin. On a normal "distro kernel": 21k modules.builtin.alias.bin 11k modules.builtin.bin From the kernel we get both modules.builtin and modules.builtin.modinfo. depmod generates modules.builtin.bin and modules.builtin.alias.bin from them respectively. modules.bultin is not going away: it's not deprecated by the new index added. So, let's just stop duplicating the information inside modules.builtin.alias.bin and just use the other index. --- libkmod/libkmod-module.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 6f7747c..6423339 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -576,13 +576,15 @@ KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx, err = kmod_lookup_alias_from_aliases_file(ctx, alias, list); CHECK_ERR_AND_FINISH(err, fail, list, finish); + DBG(ctx, "lookup modules.builtin %s\n", alias); + err = kmod_lookup_alias_from_builtin_file(ctx, alias, list); + CHECK_ERR_AND_FINISH(err, fail, list, finish); + DBG(ctx, "lookup modules.builtin.modinfo %s\n", alias); err = kmod_lookup_alias_from_kernel_builtin_file(ctx, alias, list); - if (err == -ENOSYS) { - /* Optional index missing, try the old one */ - DBG(ctx, "lookup modules.builtin %s\n", alias); - err = kmod_lookup_alias_from_builtin_file(ctx, alias, list); - } + /* Optional index missing, ignore */ + if (err == -ENOSYS) + err = 0; CHECK_ERR_AND_FINISH(err, fail, list, finish); -- cgit v1.2.3 From 7a0f593de3bef04b8f8d35e51f76995d0493d007 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 9 Feb 2022 18:46:34 -0800 Subject: depmod: Do not duplicate builtin index Now that libkmod uses modules.builtin.bin again, we don't need to add the module names in modules.builtin.alias.bin and just add the aliases. After this change, here are the new sizes for the indexes: Before After index 21k 6.4K modules.builtin.alias.bin 11k 11K modules.builtin.bin --- tools/depmod.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/depmod.c b/tools/depmod.c index eb810b8..ac6ead8 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -2405,7 +2405,7 @@ static int output_devname(struct depmod *depmod, FILE *out) static int output_builtin_alias_bin(struct depmod *depmod, FILE *out) { - int ret = 0, count = 0; + int ret = 0; struct index_node *idx; struct kmod_list *l, *builtin = NULL; @@ -2450,9 +2450,6 @@ static int output_builtin_alias_bin(struct depmod *depmod, FILE *out) } kmod_module_info_free_list(info_list); - - index_insert(idx, modname, modname, 0); - count++; } out: -- cgit v1.2.3 From 0246e06340df292b5dda4bc00e24cc9ae894e881 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 9 Feb 2022 18:07:03 -0800 Subject: depmod: Stop opening modules.modinfo once per module Since the addition of modules.aliases.bin, depmod has to open that index multiple times and parse it over and over again: $ sudo strace -e openat ./tools/depmod 2>&1 | grep modules.builtin.modinfo | wc -l 299 $ time sudo ./tools/depmod real 0m7.814s user 0m7.571s sys 0m0.237s Rework the logic in depmod so it does everything: open, read and parse. The format is very straightforward and we don't need to keep it in a data structure since we only want to add the result to a index. New output: $ sudo strace -e openat ./tools/depmod 2>&1 | grep modules.builtin.modinfo | wc -l 1 $ time sudo ./tools/depmod real 0m7.663s user 0m7.516s sys 0m0.139s Indexes still match: $ cmp /tmp/modules.builtin.alias.bin.new /tmp/modules.builtin.alias.bin.old; echo $? 0 Fix: https://github.com/kmod-project/kmod/issues/11 --- tools/depmod.c | 158 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 96 insertions(+), 62 deletions(-) diff --git a/tools/depmod.c b/tools/depmod.c index ac6ead8..07a35ba 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -2346,6 +2346,102 @@ static int output_builtin_bin(struct depmod *depmod, FILE *out) return 0; } +static int flush_stream(FILE *in, int endchar) +{ + size_t i = 0; + int c; + + for (c = fgetc(in); + c != EOF && c != endchar && c != '\0'; + c = fgetc(in)) + ; + + return c == endchar ? i : 0; +} + +static int flush_stream_to(FILE *in, int endchar, char *dst, size_t dst_sz) +{ + size_t i = 0; + int c; + + for (c = fgetc(in); + c != EOF && c != endchar && c != '\0' && i < dst_sz; + c = fgetc(in)) + dst[i++] = c; + + if (i == dst_sz) { + WRN("Could not flush stream: %d. Partial content: %.*s\n", + ENOSPC, (int) dst_sz, dst); + } + + return c == endchar ? i : 0; +} + +static int output_builtin_alias_bin(struct depmod *depmod, FILE *out) +{ + FILE *in; + struct index_node *idx; + int ret; + + if (out == stdout) + return 0; + + in = dfdopen(depmod->cfg->dirname, "modules.builtin.modinfo", O_RDONLY, "r"); + if (in == NULL) + return 0; + + idx = index_create(); + if (idx == NULL) { + fclose(in); + return -ENOMEM; + } + + /* format: modname.key=value\0 */ + while (!feof(in) && !ferror(in)) { + char alias[PATH_MAX]; + char modname[PATH_MAX]; + char value[PATH_MAX]; + size_t len; + + len = flush_stream_to(in, '.', modname, sizeof(modname)); + modname[len] = '\0'; + if (!len) + continue; + + len = flush_stream_to(in, '=', value, sizeof(value)); + value[len] = '\0'; + if (!streq(value, "alias")) { + flush_stream(in, '\0'); + continue; + } + + len = flush_stream_to(in, '\0', value, sizeof(value)); + value[len] = '\0'; + if (!len) + continue; + + alias[0] = '\0'; + if (alias_normalize(value, alias, NULL) < 0) { + WRN("Unmatched bracket in %s\n", value); + continue; + } + + index_insert(idx, alias, modname, 0); + } + + if (ferror(in)) { + ret = -EINVAL; + } else { + index_write(idx, out); + ret = 0; + } + + index_destroy(idx); + fclose(in); + + return ret; +} + static int output_devname(struct depmod *depmod, FILE *out) { size_t i; @@ -2403,68 +2499,6 @@ static int output_devname(struct depmod *depmod, FILE *out) return 0; } -static int output_builtin_alias_bin(struct depmod *depmod, FILE *out) -{ - int ret = 0; - struct index_node *idx; - struct kmod_list *l, *builtin = NULL; - - if (out == stdout) - return 0; - - idx = index_create(); - if (idx == NULL) - return -ENOMEM; - - ret = kmod_module_get_builtin(depmod->ctx, &builtin); - if (ret < 0) { - if (ret == -ENOENT) - ret = 0; - goto out; - } - - kmod_list_foreach(l, builtin) { - struct kmod_list *ll, *info_list = NULL; - struct kmod_module *mod = l->data; - const char *modname = kmod_module_get_name(mod); - - ret = kmod_module_get_info(mod, &info_list); - if (ret < 0) - goto out; - - kmod_list_foreach(ll, info_list) { - char alias[PATH_MAX]; - const char *key = kmod_module_info_get_key(ll); - const char *value = kmod_module_info_get_value(ll); - - if (!streq(key, "alias")) - continue; - - alias[0] = '\0'; - if (alias_normalize(value, alias, NULL) < 0) { - WRN("Unmatched bracket in %s\n", value); - continue; - } - - index_insert(idx, alias, modname, 0); - } - - kmod_module_info_free_list(info_list); - } - -out: - /* do not bother writing the index if we are going to discard it */ - if (ret > 0) - index_write(idx, out); - - if (builtin) - kmod_module_unref_list(builtin); - - index_destroy(idx); - - return ret; -} - static int depmod_output(struct depmod *depmod, FILE *out) { static const struct depfile { -- cgit v1.2.3 From 9dc4e5ccd4d7ff9ed4e96db8446501a3dc862dbf Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 15 Feb 2022 14:05:13 -0800 Subject: test-initstate: Check for negative value on error Documentation says kmod_module_new_from_lookup() returns < 0 on error and 0 otherwise. There are bugs in libkmod however making it return a positive value in some situations, that need to be fixed. However it's best to check for the error explicitly like is done in the rest of the library to avoid this kind of issues. Reviewed-by: Luis Chamberlain --- testsuite/test-initstate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/test-initstate.c b/testsuite/test-initstate.c index da2303a..9332e8f 100644 --- a/testsuite/test-initstate.c +++ b/testsuite/test-initstate.c @@ -45,7 +45,7 @@ static noreturn int test_initstate_from_lookup(const struct test *t) exit(EXIT_FAILURE); err = kmod_module_new_from_lookup(ctx, "fake-builtin", &list); - if (err != 0) { + if (err < 0) { ERR("could not create module from lookup: %s\n", strerror(-err)); exit(EXIT_FAILURE); } -- cgit v1.2.3 From ec8818bcfb903c8f6a614a5aa4d1aa231d79308c Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 15 Feb 2022 14:09:14 -0800 Subject: libkmod-module: Fix return code for kmod_module_new_from_lookup() When kmod_module_new_from_lookup() resolves to an alias, `err` will be set to a positive value from the lookup function. Do not return a positive value to follow the behavior when it matches a module name and the documentation. Reviewed-by: Luis Chamberlain --- libkmod/libkmod-module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 6423339..1b59c3c 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -589,8 +589,8 @@ KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx, finish: - DBG(ctx, "lookup %s=%d, list=%p\n", alias, err, *list); - return err; + DBG(ctx, "lookup %s matches=%d, list=%p\n", alias, err, *list); + return err > 0 ? 0 : err; fail: DBG(ctx, "Failed to lookup %s\n", alias); kmod_module_unref_list(*list); -- cgit v1.2.3 From 61a93a043aa52ad62a11ba940d4ba93cb3254e78 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 15 Feb 2022 17:28:53 -0800 Subject: gitignore: ignore gtk-doc.make Reviewed-by: Luis Chamberlain --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f823511..cad86ea 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ /configure /cov-int /coverage +/gtk-doc.make /kmod-*.tar.* /libtool /stamp-h1 -- cgit v1.2.3 From 82972710196442c503cc1068a05651c354a865fb Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 15 Feb 2022 19:12:05 -0800 Subject: libkmod: Add helper function to iterate lookup options The CHECK_ERR_AND_FINISH macro with conditional code flow changes has been a source of bugs. Get rid of it replacing with a helper function to iterate an array of lookup functions. This helper may also be useful in future to create different lookup APIs in libkmod. Reviewed-by: Luis Chamberlain --- libkmod/libkmod-module.c | 82 ++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 45 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 1b59c3c..7cb6d26 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -499,13 +499,26 @@ KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod) return mod; } -#define CHECK_ERR_AND_FINISH(_err, _label_err, _list, label_finish) \ - do { \ - if ((_err) < 0) \ - goto _label_err; \ - if (*(_list) != NULL) \ - goto finish; \ - } while (0) +typedef int (*lookup_func)(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3))); + +static int __kmod_module_new_from_lookup(struct kmod_ctx *ctx, const lookup_func lookup[], + size_t lookup_count, const char *s, + struct kmod_list **list) +{ + unsigned int i; + + for (i = 0; i < lookup_count; i++) { + int err; + + err = lookup[i](ctx, s, list); + if (err < 0 && err != -ENOSYS) + return err; + else if (*list != NULL) + return 0; + } + + return 0; +} /** * kmod_module_new_from_lookup: @@ -538,8 +551,17 @@ KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx, const char *given_alias, struct kmod_list **list) { - int err; + const lookup_func lookup[] = { + kmod_lookup_alias_from_config, + kmod_lookup_alias_from_moddep_file, + kmod_lookup_alias_from_symbols_file, + kmod_lookup_alias_from_commands, + kmod_lookup_alias_from_aliases_file, + kmod_lookup_alias_from_builtin_file, + kmod_lookup_alias_from_kernel_builtin_file, + }; char alias[PATH_MAX]; + int err; if (ctx == NULL || given_alias == NULL) return -ENOENT; @@ -556,48 +578,18 @@ KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx, DBG(ctx, "input alias=%s, normalized=%s\n", given_alias, alias); - /* Aliases from config file override all the others */ - err = kmod_lookup_alias_from_config(ctx, alias, list); - CHECK_ERR_AND_FINISH(err, fail, list, finish); + err = __kmod_module_new_from_lookup(ctx, lookup, sizeof(lookup), + alias, list); - DBG(ctx, "lookup modules.dep %s\n", alias); - err = kmod_lookup_alias_from_moddep_file(ctx, alias, list); - CHECK_ERR_AND_FINISH(err, fail, list, finish); - - DBG(ctx, "lookup modules.symbols %s\n", alias); - err = kmod_lookup_alias_from_symbols_file(ctx, alias, list); - CHECK_ERR_AND_FINISH(err, fail, list, finish); - - DBG(ctx, "lookup install and remove commands %s\n", alias); - err = kmod_lookup_alias_from_commands(ctx, alias, list); - CHECK_ERR_AND_FINISH(err, fail, list, finish); - - DBG(ctx, "lookup modules.aliases %s\n", alias); - err = kmod_lookup_alias_from_aliases_file(ctx, alias, list); - CHECK_ERR_AND_FINISH(err, fail, list, finish); - - DBG(ctx, "lookup modules.builtin %s\n", alias); - err = kmod_lookup_alias_from_builtin_file(ctx, alias, list); - CHECK_ERR_AND_FINISH(err, fail, list, finish); - - DBG(ctx, "lookup modules.builtin.modinfo %s\n", alias); - err = kmod_lookup_alias_from_kernel_builtin_file(ctx, alias, list); - /* Optional index missing, ignore */ - if (err == -ENOSYS) - err = 0; - CHECK_ERR_AND_FINISH(err, fail, list, finish); + DBG(ctx, "lookup=%s found=%d\n", alias, err >= 0 && *list); + if (err < 0) { + kmod_module_unref_list(*list); + *list = NULL; + } -finish: - DBG(ctx, "lookup %s matches=%d, list=%p\n", alias, err, *list); - return err > 0 ? 0 : err; -fail: - DBG(ctx, "Failed to lookup %s\n", alias); - kmod_module_unref_list(*list); - *list = NULL; return err; } -#undef CHECK_ERR_AND_FINISH /** * kmod_module_unref_list: -- cgit v1.2.3 From a8592204839e291b92218602801d7374f0a9fcf2 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 15 Feb 2022 22:47:06 -0800 Subject: libkmod: Update docs about indexes order New indexes were created without updating the documentation about the order in kmod_module_new_from_lookup(). Add them to the documentation. Reviewed-by: Luis Chamberlain --- libkmod/libkmod-module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 7cb6d26..1c6ff24 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -534,7 +534,7 @@ static int __kmod_module_new_from_lookup(struct kmod_ctx *ctx, const lookup_func * * The search order is: 1. aliases in configuration file; 2. module names in * modules.dep index; 3. symbol aliases in modules.symbols index; 4. aliases - * in modules.alias index. + * from install commands; 5. builtin indexes from kernel. * * The initial refcount is 1, and needs to be decremented to release the * resources of the kmod_module. The returned @list must be released by -- cgit v1.2.3 From 9becaaea25f486d7b0d8237f3d9548c024a9af8f Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 15 Feb 2022 23:10:58 -0800 Subject: libkmod: Add lookup from module name Slightly different than kmod_module_new_from_lookup(): it doesn't consider aliases, only module names. This is useful for cases we want to force a tool to handle something as the module name, without trying to interpret it as an alias. Reviewed-by: Luis Chamberlain --- libkmod/libkmod-module.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ libkmod/libkmod.h | 3 +++ libkmod/libkmod.sym | 1 + 3 files changed, 61 insertions(+) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 1c6ff24..a1839fa 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -591,6 +591,63 @@ KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx, return err; } +/** + * kmod_module_new_from_name_lookup: + * @ctx: kmod library context + * @modname: module name to look for + * @mod: returned module on success + * + * Lookup by module name, without considering possible aliases. This is similar + * to kmod_module_new_from_lookup(), but don't consider as source indexes and + * configurations that work with aliases. When succesful, this always resolves + * to one and only one module. + * + * The search order is: 1. module names in modules.dep index; + * 2. builtin indexes from kernel. + * + * The initial refcount is 1, and needs to be decremented to release the + * resources of the kmod_module. Since libkmod keeps track of all + * kmod_modules created, they are all released upon @ctx destruction too. Do + * not unref @ctx before all the desired operations with the returned list are + * completed. + * + * Returns: 0 on success or < 0 otherwise. It fails if any of the lookup + * methods failed, which is basically due to memory allocation failure. If + * module is not found, it still returns 0, but @mod is left untouched. + */ +KMOD_EXPORT int kmod_module_new_from_name_lookup(struct kmod_ctx *ctx, + const char *modname, + struct kmod_module **mod) +{ + const lookup_func lookup[] = { + kmod_lookup_alias_from_moddep_file, + kmod_lookup_alias_from_builtin_file, + kmod_lookup_alias_from_kernel_builtin_file, + }; + char name_norm[PATH_MAX]; + struct kmod_list *list = NULL; + int err; + + if (ctx == NULL || modname == NULL || mod == NULL) + return -ENOENT; + + modname_normalize(modname, name_norm, NULL); + + DBG(ctx, "input modname=%s, normalized=%s\n", modname, name_norm); + + err = __kmod_module_new_from_lookup(ctx, lookup, sizeof(lookup), + name_norm, &list); + + DBG(ctx, "lookup=%s found=%d\n", name_norm, err >= 0 && list); + + if (err >= 0 && list != NULL) + *mod = kmod_module_get_module(list); + + kmod_module_unref_list(list); + + return err; +} + /** * kmod_module_unref_list: * @list: list of kmod modules diff --git a/libkmod/libkmod.h b/libkmod/libkmod.h index 3cab2e5..fed216b 100644 --- a/libkmod/libkmod.h +++ b/libkmod/libkmod.h @@ -129,6 +129,9 @@ int kmod_module_new_from_path(struct kmod_ctx *ctx, const char *path, struct kmod_module **mod); int kmod_module_new_from_lookup(struct kmod_ctx *ctx, const char *given_alias, struct kmod_list **list); +int kmod_module_new_from_name_lookup(struct kmod_ctx *ctx, + const char *modname, + struct kmod_module **mod); int kmod_module_new_from_loaded(struct kmod_ctx *ctx, struct kmod_list **list); diff --git a/libkmod/libkmod.sym b/libkmod/libkmod.sym index 5f5e1fb..0c04fda 100644 --- a/libkmod/libkmod.sym +++ b/libkmod/libkmod.sym @@ -30,6 +30,7 @@ global: kmod_module_new_from_name; kmod_module_new_from_path; kmod_module_new_from_lookup; + kmod_module_new_from_name_lookup; kmod_module_new_from_loaded; kmod_module_ref; kmod_module_unref; -- cgit v1.2.3 From e343a824998dbbe7571e4d7b8dbb0f635e4c5006 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 15 Feb 2022 23:16:33 -0800 Subject: modinfo: Update help message with "modulename" man page correctly states the a module name can be used in place of a file name: modinfo [-0] [-F field] [-k kernel] [modulename|filename...] Update the help message accordingly. Reviewed-by: Luis Chamberlain --- tools/modinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/modinfo.c b/tools/modinfo.c index f6a971f..f51b7e4 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -337,7 +337,7 @@ static const struct option cmdopts[] = { static void help(void) { printf("Usage:\n" - "\t%s [options] filename [args]\n" + "\t%s [options] [args]\n" "Options:\n" "\t-a, --author Print only 'author'\n" "\t-d, --description Print only 'description'\n" -- cgit v1.2.3 From 94f7683c5a5084b61756c6df29c14041efebcd94 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 15 Feb 2022 23:36:49 -0800 Subject: modinfo: Allow to force arg as module name If the Linux kernel or userspace sets an alias with the same name as a module, they force the tools to use that. However in some situations it may be desired to query the module itself. Getting the module information through modinfo is one such situation. So, add a option to modinfo to explicitly instruct it to handle the argument as a module name. Example, when trying to output information about the crc32 module that is builtin: $ modinfo crc32 filename: /lib/modules/5.15.19-1-MANJARO/kernel/arch/x86/crypto/crc32-pclmul.ko.zst alias: crypto-crc32-pclmul alias: crc32-pclmul alias: crypto-crc32 alias: crc32 license: GPL author: Alexander Boyko srcversion: B6B2FF9236731E69418A2E5 alias: cpu:type:x86,ven*fam*mod*:feature:*0081* depends: retpoline: Y intree: Y name: crc32_pclmul vermagic: 5.15.19-1-MANJARO SMP preempt mod_unload sig_id: PKCS#7 signer: Build time autogenerated kernel key sig_key: 77:FB:AA:BD:48:78:A4:C6:56:18:9A:7E:A6:F3:29:3E:C5:6B:E9:37 sig_hashalgo: sha512 signature: 30:65:02:31:00:B0:D4:49:9D:1D:F1:71:4C:3C:BB:70:B2:3E:46:5D: 38:5A:F1:00:95:FD:7A:96:C4:2C:24:35:A2:1B:0B:A8:1C:29:6F:02: 7A:68:EE:BA:A4:1C:01:4B:86:39:15:3E:66:02:30:7F:7A:66:5E:F2: 2F:98:73:3D:AD:96:66:81:8B:94:6E:F3:3F:44:0F:85:E1:73:3A:9E: F9:C4:BE:9B:88:02:BD:83:04:B9:2E:72:0B:93:BC:82:B6:A1:1B:6A: C2:ED:8C filename: /lib/modules/5.15.19-1-MANJARO/kernel/crypto/crc32_generic.ko.zst alias: crypto-crc32-generic alias: crc32-generic alias: crypto-crc32 alias: crc32 license: GPL description: CRC32 calculations wrapper for lib/crc32 author: Alexander Boyko srcversion: F08036C38DDB06BCD1E6091 depends: retpoline: Y intree: Y name: crc32_generic vermagic: 5.15.19-1-MANJARO SMP preempt mod_unload sig_id: PKCS#7 signer: Build time autogenerated kernel key sig_key: 77:FB:AA:BD:48:78:A4:C6:56:18:9A:7E:A6:F3:29:3E:C5:6B:E9:37 sig_hashalgo: sha512 signature: 30:65:02:31:00:E3:9E:C8:80:15:0E:D7:74:96:B5:25:EA:32:F7:DF: E9:FC:3C:82:D9:B9:B9:37:C5:20:8D:06:31:02:62:B3:54:E8:DF:F2: 7E:E2:7C:A4:CF:49:17:CB:75:DF:2C:7A:2F:02:30:25:DE:7C:2A:2C: 97:3F:65:16:76:B3:71:FB:62:DB:8F:F3:33:65:77:98:F3:57:ED:D7: 87:78:FF:C2:04:55:70:00:10:63:1E:B2:FE:22:D8:E5:6D:5F:95:4E: 7D:2C:6B That is because the Linux kernel exports "crc32" as an alias to those modules, besides being a module itself: $ grep crc32 /lib/modules/$(uname -r)/modules.builtin kernel/lib/crc32.ko $ $ grep "alias crc32 " /lib/modules/$(uname -r)/modules.alias alias crc32 crc32_pclmul alias crc32 crc32_generic With the new -m|--modname option it's possible to query the information about this (builtin) module explicitly: $ modinfo --modname crc32 name: crc32 filename: (builtin) license: GPL file: lib/crc32 description: Various CRC32 calculations author: Matt Domsch Reviewed-by: Luis Chamberlain --- tools/modinfo.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/tools/modinfo.c b/tools/modinfo.c index f51b7e4..d0aab20 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -293,6 +293,24 @@ static int modinfo_path_do(struct kmod_ctx *ctx, const char *path) return err; } +static int modinfo_name_do(struct kmod_ctx *ctx, const char *name) +{ + struct kmod_module *mod = NULL; + int err; + + err = kmod_module_new_from_name_lookup(ctx, name, &mod); + if (err < 0 || mod == NULL) { + ERR("Module name %s not found.\n", name); + return err < 0 ? err : -ENOENT; + } + + err = modinfo_do(mod); + kmod_module_unref(mod); + + return err; +} + + static int modinfo_alias_do(struct kmod_ctx *ctx, const char *alias) { struct kmod_list *l, *list = NULL; @@ -318,7 +336,7 @@ static int modinfo_alias_do(struct kmod_ctx *ctx, const char *alias) return err; } -static const char cmdopts_s[] = "adlpn0F:k:b:Vh"; +static const char cmdopts_s[] = "adlpn0mF:k:b:Vh"; static const struct option cmdopts[] = { {"author", no_argument, 0, 'a'}, {"description", no_argument, 0, 'd'}, @@ -326,6 +344,7 @@ static const struct option cmdopts[] = { {"parameters", no_argument, 0, 'p'}, {"filename", no_argument, 0, 'n'}, {"null", no_argument, 0, '0'}, + {"modname", no_argument, 0, 'm'}, {"field", required_argument, 0, 'F'}, {"set-version", required_argument, 0, 'k'}, {"basedir", required_argument, 0, 'b'}, @@ -345,6 +364,7 @@ static void help(void) "\t-p, --parameters Print only 'parm'\n" "\t-n, --filename Print only 'filename'\n" "\t-0, --null Use \\0 instead of \\n\n" + "\t-m, --modname Handle argument as module name instead of alias or filename\n" "\t-F, --field=FIELD Print only provided FIELD\n" "\t-k, --set-version=VERSION Use VERSION instead of `uname -r`\n" "\t-b, --basedir=DIR Use DIR as filesystem root for /lib/modules\n" @@ -372,6 +392,7 @@ static int do_modinfo(int argc, char *argv[]) const char *kversion = NULL; const char *root = NULL; const char *null_config = NULL; + bool arg_is_modname = false; int i, err; for (;;) { @@ -398,6 +419,9 @@ static int do_modinfo(int argc, char *argv[]) case '0': separator = '\0'; break; + case 'm': + arg_is_modname = true; + break; case 'F': field = optarg; break; @@ -454,7 +478,9 @@ static int do_modinfo(int argc, char *argv[]) const char *name = argv[i]; int r; - if (is_module_filename(name)) + if (arg_is_modname) + r = modinfo_name_do(ctx, name); + else if (is_module_filename(name)) r = modinfo_path_do(ctx, name); else r = modinfo_alias_do(ctx, name); -- cgit v1.2.3 From 571a84c9249257bf70f9111b30509aa121405cab Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 23 Feb 2022 10:19:13 -0800 Subject: libkmod: Fix use of sizeof instead of ARRAY_SIZE Link: https://github.com/kmod-project/kmod/issues/12 Signed-off-by: Lucas De Marchi --- libkmod/libkmod-module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index a1839fa..efdd679 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -578,7 +578,7 @@ KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx, DBG(ctx, "input alias=%s, normalized=%s\n", given_alias, alias); - err = __kmod_module_new_from_lookup(ctx, lookup, sizeof(lookup), + err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup), alias, list); DBG(ctx, "lookup=%s found=%d\n", alias, err >= 0 && *list); @@ -635,7 +635,7 @@ KMOD_EXPORT int kmod_module_new_from_name_lookup(struct kmod_ctx *ctx, DBG(ctx, "input modname=%s, normalized=%s\n", modname, name_norm); - err = __kmod_module_new_from_lookup(ctx, lookup, sizeof(lookup), + err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup), name_norm, &list); DBG(ctx, "lookup=%s found=%d\n", name_norm, err >= 0 && list); -- cgit v1.2.3 From 205827426d7c54c959b95c0f9584fe16a1471bbb Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 3 Mar 2022 00:57:10 -0800 Subject: docs: Add missing functions to documentation Signed-off-by: Lucas De Marchi --- libkmod/docs/libkmod-sections.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libkmod/docs/libkmod-sections.txt b/libkmod/docs/libkmod-sections.txt index e59ab7a..33d9eec 100644 --- a/libkmod/docs/libkmod-sections.txt +++ b/libkmod/docs/libkmod-sections.txt @@ -15,6 +15,7 @@ kmod_get_log_priority kmod_set_log_fn kmod_get_userdata kmod_set_userdata +kmod_get_dirname
@@ -46,6 +47,7 @@ kmod_config_iter_free_iter libkmod-module kmod_module kmod_module_new_from_lookup +kmod_module_new_from_name_lookup kmod_module_new_from_name kmod_module_new_from_path -- cgit v1.2.3 From 7089386eeff8f6942456159ee9a7296403631ffd Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 28 Mar 2022 23:55:03 -0700 Subject: modprobe: Rename rmmod_do_deps_list It's used not only for dependencies, but also for pre and post softdep. Signed-off-by: Lucas De Marchi Reviewed-by: Luis Chamberlain --- tools/modprobe.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index 9387537..eed951f 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -357,7 +357,8 @@ static int rmmod_do_remove_module(struct kmod_module *mod) #define RMMOD_FLAG_IGNORE_BUILTIN 0x2 static int rmmod_do_module(struct kmod_module *mod, int flags); -static int rmmod_do_deps_list(struct kmod_list *list, bool stop_on_errors) +/* Remove modules in reverse order */ +static int rmmod_do_modlist(struct kmod_list *list, bool stop_on_errors) { struct kmod_list *l; @@ -413,12 +414,12 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) } } - rmmod_do_deps_list(post, false); + rmmod_do_modlist(post, false); if ((flags & RMMOD_FLAG_DO_DEPENDENCIES) && remove_dependencies) { struct kmod_list *deps = kmod_module_get_dependencies(mod); - err = rmmod_do_deps_list(deps, true); + err = rmmod_do_modlist(deps, true); if (err < 0) goto error; } @@ -443,7 +444,7 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) if (err < 0) goto error; - rmmod_do_deps_list(pre, false); + rmmod_do_modlist(pre, false); error: kmod_module_unref_list(pre); -- cgit v1.2.3 From f50e2d67575ac5f256fb853ca9d29aeac92d9a57 Mon Sep 17 00:00:00 2001 From: Saul Wold Date: Thu, 31 Mar 2022 14:56:28 -0700 Subject: depmod: Add support for excluding a directory This adds support to depmod to enable a new exclude directive in the depmod.d/*.conf configuration file. Currently depmod already excludes directories named source or build. This change will allow additional directories like .debug to be excluded also via a new exclude directive. depmod.d/exclude.conf example: exclude .debug Signed-off-by: Saul Wold [ Fix warnings and make should_exclude_dir() return bool ] Signed-off-by: Lucas De Marchi --- man/depmod.d.xml | 14 ++++++++++++ tools/depmod.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/man/depmod.d.xml b/man/depmod.d.xml index b315e93..76548e9 100644 --- a/man/depmod.d.xml +++ b/man/depmod.d.xml @@ -131,6 +131,20 @@ + + exclude excludedir + + + + This specifies the trailing directories that will be excluded + during the search for kernel modules. + + + The excludedir is the trailing directory + to exclude + + + diff --git a/tools/depmod.c b/tools/depmod.c index 07a35ba..4117dd1 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -458,6 +458,11 @@ struct cfg_external { char path[]; }; +struct cfg_exclude { + struct cfg_exclude *next; + char exclude_dir[]; +}; + struct cfg { const char *kversion; char dirname[PATH_MAX]; @@ -469,6 +474,7 @@ struct cfg { struct cfg_override *overrides; struct cfg_search *searches; struct cfg_external *externals; + struct cfg_exclude *excludes; }; static enum search_type cfg_define_search_type(const char *path) @@ -580,6 +586,30 @@ static void cfg_external_free(struct cfg_external *ext) free(ext); } +static int cfg_exclude_add(struct cfg *cfg, const char *path) +{ + struct cfg_exclude *exc; + size_t len = strlen(path); + + exc = malloc(sizeof(struct cfg_exclude) + len + 1); + if (exc == NULL) { + ERR("exclude add: out of memory\n"); + return -ENOMEM; + } + memcpy(exc->exclude_dir, path, len + 1); + + DBG("exclude add: %s\n", path); + + exc->next = cfg->excludes; + cfg->excludes = exc; + return 0; +} + +static void cfg_exclude_free(struct cfg_exclude *exc) +{ + free(exc); +} + static int cfg_kernel_matches(const struct cfg *cfg, const char *pattern) { regex_t re; @@ -657,6 +687,11 @@ static int cfg_file_parse(struct cfg *cfg, const char *filename) } cfg_external_add(cfg, dir); + } else if (streq(cmd, "exclude")) { + const char *sp; + while ((sp = strtok_r(NULL, "\t ", &saveptr)) != NULL) { + cfg_exclude_add(cfg, sp); + } } else if (streq(cmd, "include") || streq(cmd, "make_map_files")) { INF("%s:%u: command %s not implemented yet\n", @@ -857,6 +892,12 @@ static void cfg_free(struct cfg *cfg) cfg->externals = cfg->externals->next; cfg_external_free(tmp); } + + while (cfg->excludes) { + struct cfg_exclude *tmp = cfg->excludes; + cfg->excludes = cfg->excludes->next; + cfg_exclude_free(tmp); + } } @@ -1229,6 +1270,25 @@ add: return 0; } +static bool should_exclude_dir(const struct cfg *cfg, const char *name) +{ + struct cfg_exclude *exc; + + if (name[0] == '.' && (name[1] == '\0' || + (name[1] == '.' && name[2] == '\0'))) + return true; + + if (streq(name, "build") || streq(name, "source")) + return true; + + for (exc = cfg->excludes; exc != NULL; exc = exc->next) { + if (streq(name, exc->exclude_dir)) + return true; + } + + return false; +} + static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t baselen, struct scratchbuf *s_path) { struct dirent *de; @@ -1240,11 +1300,9 @@ static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t basel size_t namelen; uint8_t is_dir; - if (name[0] == '.' && (name[1] == '\0' || - (name[1] == '.' && name[2] == '\0'))) - continue; - if (streq(name, "build") || streq(name, "source")) + if (should_exclude_dir(depmod->cfg, name)) continue; + namelen = strlen(name); if (scratchbuf_alloc(s_path, baselen + namelen + 2) < 0) { err = -ENOMEM; -- cgit v1.2.3 From 757b3599236c0fee9e2bb0770eb6b7c84a271276 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 10 Feb 2022 11:14:22 +0900 Subject: modprobe: fix the NULL-termination of new_argv The number of new arguments is (i + argc - 1) as it is set to *p_argc one line below. The correct location of NULL termination is new_argv[i + argc - 1]. Signed-off-by: Masahiro Yamada Signed-off-by: Lucas De Marchi --- tools/modprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index eed951f..48b1c8c 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -744,7 +744,7 @@ static char **prepend_options_from_env(int *p_argc, char **orig_argv) } memcpy(new_argv + i, orig_argv + 1, sizeof(char *) * (argc - 1)); - new_argv[i + argc] = NULL; + new_argv[i + argc - 1] = NULL; *p_argc = i + argc - 1; return new_argv; -- cgit v1.2.3 From d890179b451211c506b7860f125a6ae181c9f5dc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 10 Feb 2022 11:14:23 +0900 Subject: modprobe: remove unneeded variable str_start The variable 'str_start' is not useful here. Replace it with 'str'. Signed-off-by: Masahiro Yamada Signed-off-by: Lucas De Marchi --- tools/modprobe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index 48b1c8c..ca372b8 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -684,7 +684,7 @@ static int options_from_array(char **args, int nargs, char **output) static char **prepend_options_from_env(int *p_argc, char **orig_argv) { const char *p, *env = getenv("MODPROBE_OPTIONS"); - char **new_argv, *str_start, *str_end, *str, *s, *quote; + char **new_argv, *str_end, *str, *s, *quote; int i, argc = *p_argc; size_t envlen, space_count = 0; @@ -702,10 +702,10 @@ static char **prepend_options_from_env(int *p_argc, char **orig_argv) return NULL; new_argv[0] = orig_argv[0]; - str_start = str = (char *) (new_argv + argc + space_count + 3); + str = (char *) (new_argv + argc + space_count + 3); memcpy(str, env, envlen + 1); - str_end = str_start + envlen; + str_end = str + envlen; quote = NULL; for (i = 1, s = str; *s != '\0'; s++) { -- cgit v1.2.3 From 42b32d30c38ef032f287957266a022eb28430bfc Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 29 Mar 2022 02:05:37 -0700 Subject: modprobe: Fix holders removal The idea behind --remove-dependencies was to remove other modules that depend on the current module being removed. It's the reverse dependency list, not the dependency list of the current module: that never works since the current module would still hold a ref on it. Fix it by replacing the call to kmod_module_get_dependencies() with kmod_module_get_holders() when using that option. Also try to cleanup the confusion by renaming the option to --remove-holders: "holder" is the name used in sysfs and by libkmod to refer to a "live" reverse dependency like what we are interested in. Before: ./tools/modprobe -D -r --remove-dependencies video rmmod video After: ./tools/modprobe -D -r --remove-holders video rmmod i915 rmmod thinkpad_acpi rmmod video Signed-off-by: Lucas De Marchi Reviewed-by: Luis Chamberlain --- tools/modprobe.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index ca372b8..32b6f7f 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -54,7 +54,7 @@ static int use_blacklist = 0; static int force = 0; static int strip_modversion = 0; static int strip_vermagic = 0; -static int remove_dependencies = 0; +static int remove_holders = 0; static int quiet_inuse = 0; static const char cmdopts_s[] = "arRibfDcnC:d:S:sqvVh"; @@ -62,6 +62,7 @@ static const struct option cmdopts[] = { {"all", no_argument, 0, 'a'}, {"remove", no_argument, 0, 'r'}, {"remove-dependencies", no_argument, 0, 5}, + {"remove-holders", no_argument, 0, 5}, {"resolve-alias", no_argument, 0, 'R'}, {"first-time", no_argument, 0, 3}, {"ignore-install", no_argument, 0, 'i'}, @@ -107,7 +108,8 @@ static void help(void) "\t be a module name to be inserted\n" "\t or removed (-r)\n" "\t-r, --remove Remove modules instead of inserting\n" - "\t --remove-dependencies Also remove modules depending on it\n" + "\t --remove-dependencies Deprecated: use --remove-holders\n" + "\t --remove-holders Also remove module holders (use together with -r)\n" "\t-R, --resolve-alias Only lookup and print alias and exit\n" "\t --first-time Fail if module already inserted or removed\n" "\t-i, --ignore-install Ignore install commands\n" @@ -353,7 +355,7 @@ static int rmmod_do_remove_module(struct kmod_module *mod) return err; } -#define RMMOD_FLAG_DO_DEPENDENCIES 0x1 +#define RMMOD_FLAG_REMOVE_HOLDERS 0x1 #define RMMOD_FLAG_IGNORE_BUILTIN 0x2 static int rmmod_do_module(struct kmod_module *mod, int flags); @@ -416,10 +418,10 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) rmmod_do_modlist(post, false); - if ((flags & RMMOD_FLAG_DO_DEPENDENCIES) && remove_dependencies) { - struct kmod_list *deps = kmod_module_get_dependencies(mod); + if ((flags & RMMOD_FLAG_REMOVE_HOLDERS) && remove_holders) { + struct kmod_list *holders = kmod_module_get_holders(mod); - err = rmmod_do_modlist(deps, true); + err = rmmod_do_modlist(holders, true); if (err < 0) goto error; } @@ -469,7 +471,7 @@ static int rmmod(struct kmod_ctx *ctx, const char *alias) kmod_list_foreach(l, list) { struct kmod_module *mod = kmod_module_get_module(l); - err = rmmod_do_module(mod, RMMOD_FLAG_DO_DEPENDENCIES); + err = rmmod_do_module(mod, RMMOD_FLAG_REMOVE_HOLDERS); kmod_module_unref(mod); if (err < 0) break; @@ -787,7 +789,7 @@ static int do_modprobe(int argc, char **orig_argv) do_remove = 1; break; case 5: - remove_dependencies = 1; + remove_holders = 1; break; case 'R': lookup_only = 1; -- cgit v1.2.3 From d29ed6ef9f0db54acda5a51993bba7ff6f8ca7cd Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 29 Mar 2022 02:05:39 -0700 Subject: modprobe: move check for remove_holders to caller Do not mix the flags with and additional boolean from arguments. Signed-off-by: Lucas De Marchi Reviewed-by: Luis Chamberlain --- tools/modprobe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index 32b6f7f..45952a6 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -418,7 +418,7 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) rmmod_do_modlist(post, false); - if ((flags & RMMOD_FLAG_REMOVE_HOLDERS) && remove_holders) { + if (flags & RMMOD_FLAG_REMOVE_HOLDERS) { struct kmod_list *holders = kmod_module_get_holders(mod); err = rmmod_do_modlist(holders, true); @@ -471,7 +471,9 @@ static int rmmod(struct kmod_ctx *ctx, const char *alias) kmod_list_foreach(l, list) { struct kmod_module *mod = kmod_module_get_module(l); - err = rmmod_do_module(mod, RMMOD_FLAG_REMOVE_HOLDERS); + int flags = remove_holders ? RMMOD_FLAG_REMOVE_HOLDERS : 0; + + err = rmmod_do_module(mod, flags); kmod_module_unref(mod); if (err < 0) break; -- cgit v1.2.3 From ea3c8adfd39a5f6137482daca21058132ec5ee8d Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 29 Mar 2022 02:05:40 -0700 Subject: modprobe: Make rmmod_do_module() contain all the removal sequence Move the remaining part of the removal sequence dangling in rmmod_do_remove_module() to rmmod_do_module() so we can consider this function is the one controlling all the module removals. While at it, add some comments about the removal order and normalize coding style in this function. Signed-off-by: Lucas De Marchi Reviewed-by: Luis Chamberlain --- tools/modprobe.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index 45952a6..830c667 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -322,7 +322,6 @@ end: static int rmmod_do_remove_module(struct kmod_module *mod) { const char *modname = kmod_module_get_name(mod); - struct kmod_list *deps, *itr; int flags = 0, err; SHOW("rmmod %s\n", kmod_module_get_name(mod)); @@ -341,17 +340,6 @@ static int rmmod_do_remove_module(struct kmod_module *mod) LOG("Module %s is not in kernel.\n", modname); } - deps = kmod_module_get_dependencies(mod); - if (deps != NULL) { - kmod_list_foreach(itr, deps) { - struct kmod_module *dep = kmod_module_get_module(itr); - if (kmod_module_get_refcnt(dep) == 0) - rmmod_do_remove_module(dep); - kmod_module_unref(dep); - } - kmod_module_unref_list(deps); - } - return err; } @@ -394,7 +382,8 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) cmd = kmod_module_get_remove_commands(mod); } - if (cmd == NULL && !ignore_loaded) { + /* Quick check if module is loaded, otherwise there's nothing to do */ + if (!cmd && !ignore_loaded) { int state = kmod_module_get_initstate(mod); if (state < 0) { @@ -416,8 +405,10 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) } } + /* 1. @mod's post-softdeps in reverse order */ rmmod_do_modlist(post, false); + /* 2. Other modules holding @mod */ if (flags & RMMOD_FLAG_REMOVE_HOLDERS) { struct kmod_list *holders = kmod_module_get_holders(mod); @@ -426,7 +417,8 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) goto error; } - if (!ignore_loaded && !cmd) { + /* 3. @mod itself, but check for refcnt first */ + if (!cmd && !ignore_loaded) { int usage = kmod_module_get_refcnt(mod); if (usage > 0) { @@ -438,7 +430,7 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) } } - if (cmd == NULL) + if (!cmd) err = rmmod_do_remove_module(mod); else err = command_do(mod, "remove", cmd, NULL); @@ -446,6 +438,21 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) if (err < 0) goto error; + /* 4. Other modules that became unused: errors are non-fatal */ + if (!cmd) { + struct kmod_list *deps, *itr; + + deps = kmod_module_get_dependencies(mod); + kmod_list_foreach(itr, deps) { + struct kmod_module *dep = kmod_module_get_module(itr); + if (kmod_module_get_refcnt(dep) == 0) + rmmod_do_remove_module(dep); + kmod_module_unref(dep); + } + kmod_module_unref_list(deps); + } + + /* 5. @mod's pre-softdeps in reverse order: errors are non-fatal */ rmmod_do_modlist(pre, false); error: -- cgit v1.2.3 From 07bf5e1520ebf520a65f350a99d6a7f28c482ab5 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 13:49:01 -0700 Subject: depmod: Fix writing over array length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure return value in flush_stream_to() is the length written if the value didn't the size. Fix warning on gcc 12.1: tools/depmod.c: In function ‘output_builtin_alias_bin’: tools/depmod.c:2465:24: warning: array subscript 4096 is above array bounds of ‘char[4096]’ [-Warray-bounds] 2465 | modname[len] = '\0'; | ~~~~~~~^~~~~ tools/depmod.c:2460:22: note: while referencing ‘modname’ 2460 | char modname[PATH_MAX]; | ^~~~~~~ tools/depmod.c:2477:22: warning: array subscript 4096 is above array bounds of ‘char[4096]’ [-Warray-bounds] 2477 | value[len] = '\0'; | ~~~~~^~~~~ tools/depmod.c:2461:22: note: while referencing ‘value’ 2461 | char value[PATH_MAX]; | ^~~~~ Signed-off-by: Lucas De Marchi --- tools/depmod.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/depmod.c b/tools/depmod.c index 4117dd1..364b7d4 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -2430,6 +2430,7 @@ static int flush_stream_to(FILE *in, int endchar, char *dst, size_t dst_sz) if (i == dst_sz) { WRN("Could not flush stream: %d. Partial content: %.*s\n", ENOSPC, (int) dst_sz, dst); + i--; } return c == endchar ? i : 0; -- cgit v1.2.3 From 6f7ab21645694b01e45bae8d8740004f53736c82 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 13:49:02 -0700 Subject: modprobe: re-use modname variable Signed-off-by: Lucas De Marchi --- tools/modprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index 830c667..a825fb5 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -324,7 +324,7 @@ static int rmmod_do_remove_module(struct kmod_module *mod) const char *modname = kmod_module_get_name(mod); int flags = 0, err; - SHOW("rmmod %s\n", kmod_module_get_name(mod)); + SHOW("rmmod %s\n", modname); if (dry_run) return 0; -- cgit v1.2.3 From 081fff2c678cc1b1da1034f638bf5373b35188d5 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 14:50:40 -0700 Subject: modprobe: Move -R to "Query options" Signed-off-by: Lucas De Marchi --- tools/modprobe.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index a825fb5..caaf87f 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -110,7 +110,6 @@ static void help(void) "\t-r, --remove Remove modules instead of inserting\n" "\t --remove-dependencies Deprecated: use --remove-holders\n" "\t --remove-holders Also remove module holders (use together with -r)\n" - "\t-R, --resolve-alias Only lookup and print alias and exit\n" "\t --first-time Fail if module already inserted or removed\n" "\t-i, --ignore-install Ignore install commands\n" "\t-i, --ignore-remove Ignore remove commands\n" @@ -122,6 +121,7 @@ static void help(void) "\t --force-vermagic Ignore module's version magic\n" "\n" "Query Options:\n" + "\t-R, --resolve-alias Only lookup and print alias and exit\n" "\t-D, --show-depends Only print module dependencies and exit\n" "\t-c, --showconfig Print out known configuration and exit\n" "\t-c, --show-config Same as --showconfig\n" @@ -800,9 +800,6 @@ static int do_modprobe(int argc, char **orig_argv) case 5: remove_holders = 1; break; - case 'R': - lookup_only = 1; - break; case 3: first_time = 1; break; @@ -826,6 +823,9 @@ static int do_modprobe(int argc, char **orig_argv) dry_run = 1; do_show = 1; break; + case 'R': + lookup_only = 1; + break; case 'c': do_show_config = 1; break; -- cgit v1.2.3 From 3a92fc63098571bcf259ffe37cd1fdf69429e4af Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 14:50:41 -0700 Subject: libkmod: Allow to ignore log message on module removal Caller may want to handle retries, in which case the log message is not appropriate. Signed-off-by: Lucas De Marchi --- libkmod/libkmod-module.c | 13 +++++++++---- libkmod/libkmod.h | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index efdd679..12d8ed1 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -823,11 +823,13 @@ extern long delete_module(const char *name, unsigned int flags); /** * kmod_module_remove_module: * @mod: kmod module - * @flags: flags to pass to Linux kernel when removing the module. The only valid flag is + * @flags: flags used when removing the module. * KMOD_REMOVE_FORCE: force remove module regardless if it's still in - * use by a kernel subsystem or other process; - * KMOD_REMOVE_NOWAIT is always enforced, causing us to pass O_NONBLOCK to + * use by a kernel subsystem or other process; passed directly to Linux kernel + * KMOD_REMOVE_NOWAIT: is always enforced, causing us to pass O_NONBLOCK to * delete_module(2). + * KMOD_REMOVE_NOLOG: when module removal fails, do not log anything as the + * caller may want to handle retries and log when appropriate. * * Remove a module from Linux kernel. * @@ -836,6 +838,8 @@ extern long delete_module(const char *name, unsigned int flags); KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod, unsigned int flags) { + unsigned int libkmod_flags = flags & 0xff; + int err; if (mod == NULL) @@ -848,7 +852,8 @@ KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod, err = delete_module(mod->name, flags); if (err != 0) { err = -errno; - ERR(mod->ctx, "could not remove '%s': %m\n", mod->name); + if (!(libkmod_flags & KMOD_REMOVE_NOLOG)) + ERR(mod->ctx, "could not remove '%s': %m\n", mod->name); } return err; diff --git a/libkmod/libkmod.h b/libkmod/libkmod.h index fed216b..7251aa7 100644 --- a/libkmod/libkmod.h +++ b/libkmod/libkmod.h @@ -145,6 +145,8 @@ struct kmod_module *kmod_module_get_module(const struct kmod_list *entry); enum kmod_remove { KMOD_REMOVE_FORCE = O_TRUNC, KMOD_REMOVE_NOWAIT = O_NONBLOCK, /* always set */ + /* libkmod-only defines, not passed to kernel */ + KMOD_REMOVE_NOLOG = 1, }; /* Insertion flags */ -- cgit v1.2.3 From 2ab4fbcb77aec709261a07d51c3175153c2a4dca Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 14:50:42 -0700 Subject: module-playground: Add debugfs entry in mod-simple Add a debugfs file in mod-simple for manual tests: insert the module and open the file to have its refcount increased. Signed-off-by: Lucas De Marchi --- testsuite/module-playground/mod-simple.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/testsuite/module-playground/mod-simple.c b/testsuite/module-playground/mod-simple.c index cb38580..503e4d8 100644 --- a/testsuite/module-playground/mod-simple.c +++ b/testsuite/module-playground/mod-simple.c @@ -1,16 +1,32 @@ +#include #include #include +static struct dentry *debugfs_dir; + +static int test_show(struct seq_file *s, void *data) +{ + seq_puts(s, "test"); + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(test); + static int __init test_module_init(void) { + debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); + debugfs_create_file("test", 0444, debugfs_dir, NULL, &test_fops); + return 0; } static void test_module_exit(void) { + debugfs_remove_recursive(debugfs_dir); } + module_init(test_module_init); module_exit(test_module_exit); MODULE_AUTHOR("Lucas De Marchi "); -MODULE_LICENSE("LGPL"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 5622f1dae10cf393bc1b142573ce5bf446334816 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 14:50:43 -0700 Subject: util: Add time-related functions from testsuite This will be useful in future not only to testsuite, but also to tools and library. Signed-off-by: Lucas De Marchi --- shared/util.c | 10 ++++++++++ shared/util.h | 8 ++++++++ testsuite/testsuite.c | 14 +------------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/shared/util.c b/shared/util.c index b487b5f..aeb171f 100644 --- a/shared/util.c +++ b/shared/util.c @@ -466,6 +466,16 @@ unsigned long long ts_usec(const struct timespec *ts) (unsigned long long) ts->tv_nsec / NSEC_PER_USEC; } +unsigned long long now_usec(void) +{ + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) + return 0; + + return ts_usec(&ts); +} + unsigned long long stat_mstamp(const struct stat *st) { #ifdef HAVE_STRUCT_STAT_ST_MTIM diff --git a/shared/util.h b/shared/util.h index c6a31df..734a523 100644 --- a/shared/util.h +++ b/shared/util.h @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -42,7 +43,14 @@ char *path_make_absolute_cwd(const char *p) _must_check_ __attribute__((nonnull( 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); + +/* time-related functions + * ************************************************************************ */ +#define USEC_PER_SEC 1000000ULL +#define USEC_PER_MSEC 1000ULL + unsigned long long ts_usec(const struct timespec *ts); +unsigned long long now_usec(void); /* endianess and alignments */ /* ************************************************************************ */ diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 05df553..6a2d296 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -51,6 +51,7 @@ static const struct option options[] = { }; #define OVERRIDE_LIBDIR ABS_TOP_BUILDDIR "/testsuite/.libs/" +#define TEST_TIMEOUT_USEC 2 * USEC_PER_SEC struct _env_config { const char *key; @@ -62,19 +63,6 @@ struct _env_config { [TC_DELETE_MODULE_RETCODES] = { S_TC_DELETE_MODULE_RETCODES, OVERRIDE_LIBDIR "delete_module.so" }, }; -#define USEC_PER_SEC 1000000ULL -#define USEC_PER_MSEC 1000ULL -#define TEST_TIMEOUT_USEC 2 * USEC_PER_SEC -static unsigned long long now_usec(void) -{ - struct timespec ts; - - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) - return 0; - - return ts_usec(&ts); -} - static void help(void) { const struct option *itr; -- cgit v1.2.3 From ba105fafed8ccabc0a427049a14e093b914f7ddc Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 14:50:44 -0700 Subject: util: Add msec variants for time-related functions Signed-off-by: Lucas De Marchi --- shared/util.c | 16 ++++++++++++++++ shared/util.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/shared/util.c b/shared/util.c index aeb171f..d4452eb 100644 --- a/shared/util.c +++ b/shared/util.c @@ -466,6 +466,12 @@ unsigned long long ts_usec(const struct timespec *ts) (unsigned long long) ts->tv_nsec / NSEC_PER_USEC; } +unsigned long long ts_msec(const struct timespec *ts) +{ + return (unsigned long long) ts->tv_sec * MSEC_PER_SEC + + (unsigned long long) ts->tv_nsec / NSEC_PER_MSEC; +} + unsigned long long now_usec(void) { struct timespec ts; @@ -476,6 +482,16 @@ unsigned long long now_usec(void) return ts_usec(&ts); } +unsigned long long now_msec(void) +{ + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) + return 0; + + return ts_msec(&ts); +} + unsigned long long stat_mstamp(const struct stat *st) { #ifdef HAVE_STRUCT_STAT_ST_MTIM diff --git a/shared/util.h b/shared/util.h index 734a523..bedafa3 100644 --- a/shared/util.h +++ b/shared/util.h @@ -48,9 +48,13 @@ unsigned long long stat_mstamp(const struct stat *st); * ************************************************************************ */ #define USEC_PER_SEC 1000000ULL #define USEC_PER_MSEC 1000ULL +#define MSEC_PER_SEC 1000ULL +#define NSEC_PER_MSEC 1000000ULL unsigned long long ts_usec(const struct timespec *ts); +unsigned long long ts_msec(const struct timespec *ts); unsigned long long now_usec(void); +unsigned long long now_msec(void); /* endianess and alignments */ /* ************************************************************************ */ -- cgit v1.2.3 From 8ab15eceafd46fcaf2f8874af7d52d0622127655 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 14:50:45 -0700 Subject: util: Add exponential backoff sleep Add simple functions to put the current thread to sleep using exponential backoff to split the interval in smaller pieces. Signed-off-by: Lucas De Marchi --- shared/util.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ shared/util.h | 5 +++++ 2 files changed, 51 insertions(+) diff --git a/shared/util.c b/shared/util.c index d4452eb..4b547ff 100644 --- a/shared/util.c +++ b/shared/util.c @@ -472,6 +472,52 @@ unsigned long long ts_msec(const struct timespec *ts) (unsigned long long) ts->tv_nsec / NSEC_PER_MSEC; } +static struct timespec msec_ts(unsigned long long msec) +{ + struct timespec ts = { + .tv_sec = msec / MSEC_PER_SEC, + .tv_nsec = (msec % MSEC_PER_SEC) * NSEC_PER_MSEC, + }; + + return ts; +} + +int sleep_until_msec(unsigned long long msec) +{ + struct timespec ts = msec_ts(msec); + + if (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL) < 0 && + errno != EINTR) + return -errno; + + return 0; +} + +/* + * Exponential retry backoff with tail + */ +unsigned long long get_backoff_delta_msec(unsigned long long t0, + unsigned long long tend, + unsigned long long *delta) +{ + unsigned long long t; + + t = now_msec(); + + if (!*delta) + *delta = 1; + else + *delta <<= 1; + + while (t + *delta > tend) + *delta >>= 1; + + if (!*delta && tend > t) + *delta = tend - t; + + return t + *delta; +} + unsigned long long now_usec(void) { struct timespec ts; diff --git a/shared/util.h b/shared/util.h index bedafa3..7030653 100644 --- a/shared/util.h +++ b/shared/util.h @@ -55,6 +55,11 @@ unsigned long long ts_usec(const struct timespec *ts); unsigned long long ts_msec(const struct timespec *ts); unsigned long long now_usec(void); unsigned long long now_msec(void); +int sleep_until_msec(unsigned long long msec); +unsigned long long get_backoff_delta_msec(unsigned long long t0, + unsigned long long tend, + unsigned long long *delta); + /* endianess and alignments */ /* ************************************************************************ */ -- cgit v1.2.3 From b253f4c835b0a70d200ceed74ef185dc8f87da9d Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 14:50:46 -0700 Subject: testsuite: Add tests for sleep calculation Signed-off-by: Lucas De Marchi --- testsuite/test-util.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/testsuite/test-util.c b/testsuite/test-util.c index 621446b..fb8c9ef 100644 --- a/testsuite/test-util.c +++ b/testsuite/test-util.c @@ -229,4 +229,45 @@ DEFINE_TEST(test_addu64_overflow, ); +static int test_backoff_time(const struct test *t) +{ + unsigned long long delta; + + /* Check exponential increments */ + get_backoff_delta_msec(now_msec(), now_msec() + 10, &delta); + assert_return(delta == 1, EXIT_FAILURE); + get_backoff_delta_msec(now_msec(), now_msec() + 10, &delta); + assert_return(delta == 2, EXIT_FAILURE); + get_backoff_delta_msec(now_msec(), now_msec() + 10, &delta); + assert_return(delta == 4, EXIT_FAILURE); + get_backoff_delta_msec(now_msec(), now_msec() + 10, &delta); + assert_return(delta == 8, EXIT_FAILURE); + + { + unsigned long long t0, tend; + + /* Check tail */ + delta = 4; + tend = now_msec() + 3; + t0 = tend - 10; + get_backoff_delta_msec(t0, tend, &delta); + assert_return(delta == 2, EXIT_FAILURE); + tend = now_msec() + 1; + t0 = tend - 9; + get_backoff_delta_msec(t0, tend, &delta); + assert_return(delta == 1, EXIT_FAILURE); + tend = now_msec(); + t0 = tend - 10; + get_backoff_delta_msec(t0, tend, &delta); + assert_return(delta == 0, EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} +DEFINE_TEST(test_backoff_time, + .description = "check implementation of get_backoff_delta_msec()", + .need_spawn = false, + ); + + TESTSUITE_MAIN(); -- cgit v1.2.3 From 2b98ed888614d9633296a16a677107c556c4fa94 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 3 Jun 2022 14:50:47 -0700 Subject: modprobe: Add --wait Retry module removal if it fails due to EAGAIN. This allows user to pass --wait , during which `modprobe -r` will keep trying to remove the module. Signed-off-by: Lucas De Marchi --- man/modprobe.xml | 17 ++++++++++++++ tools/modprobe.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/man/modprobe.xml b/man/modprobe.xml index 0372b6b..db39c7a 100644 --- a/man/modprobe.xml +++ b/man/modprobe.xml @@ -388,6 +388,23 @@ + + + + + + TIMEOUT_MSEC + + + + This option causes modprobe -r to continue trying to + remove a module if it fails due to the module being busy, i.e. its refcount + is not 0 at the time the call is made. Modprobe tries to remove the module + with an incremental sleep time between each tentative up until the maximum + wait time in milliseconds passed in this option. + + + diff --git a/tools/modprobe.c b/tools/modprobe.c index caaf87f..2a2ae21 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -55,14 +56,18 @@ static int force = 0; static int strip_modversion = 0; static int strip_vermagic = 0; static int remove_holders = 0; +static unsigned long long wait_msec = 0; static int quiet_inuse = 0; -static const char cmdopts_s[] = "arRibfDcnC:d:S:sqvVh"; +static const char cmdopts_s[] = "arw:RibfDcnC:d:S:sqvVh"; static const struct option cmdopts[] = { {"all", no_argument, 0, 'a'}, + {"remove", no_argument, 0, 'r'}, {"remove-dependencies", no_argument, 0, 5}, {"remove-holders", no_argument, 0, 5}, + {"wait", required_argument, 0, 'w'}, + {"resolve-alias", no_argument, 0, 'R'}, {"first-time", no_argument, 0, 3}, {"ignore-install", no_argument, 0, 'i'}, @@ -110,6 +115,9 @@ static void help(void) "\t-r, --remove Remove modules instead of inserting\n" "\t --remove-dependencies Deprecated: use --remove-holders\n" "\t --remove-holders Also remove module holders (use together with -r)\n" + "\t-w, --wait When removing a module, wait up to MSEC for\n" + "\t module's refcount to become 0 so it can be\n" + "\t removed (use together with -r)\n" "\t --first-time Fail if module already inserted or removed\n" "\t-i, --ignore-install Ignore install commands\n" "\t-i, --ignore-remove Ignore remove commands\n" @@ -322,6 +330,8 @@ end: static int rmmod_do_remove_module(struct kmod_module *mod) { const char *modname = kmod_module_get_name(mod); + unsigned long long interval_msec = 0, t0_msec = 0, + tend_msec = 0; int flags = 0, err; SHOW("rmmod %s\n", modname); @@ -332,13 +342,45 @@ static int rmmod_do_remove_module(struct kmod_module *mod) if (force) flags |= KMOD_REMOVE_FORCE; - err = kmod_module_remove_module(mod, flags); - if (err == -EEXIST) { - if (!first_time) - err = 0; - else - LOG("Module %s is not in kernel.\n", modname); - } + if (wait_msec) + flags |= KMOD_REMOVE_NOLOG; + + do { + err = kmod_module_remove_module(mod, flags); + if (err == -EEXIST) { + if (!first_time) + err = 0; + else + LOG("Module %s is not in kernel.\n", modname); + break; + } else if (err == -EAGAIN && wait_msec) { + unsigned long long until_msec; + + if (!t0_msec) { + t0_msec = now_msec(); + tend_msec = t0_msec + wait_msec; + interval_msec = 1; + } + + until_msec = get_backoff_delta_msec(t0_msec, tend_msec, + &interval_msec); + err = sleep_until_msec(until_msec); + + if (!t0_msec) + err = -ENOTSUP; + + if (err < 0) { + ERR("Failed to sleep: %s\n", strerror(-err)); + err = -EAGAIN; + break; + } + } else { + break; + } + } while (interval_msec); + + if (err < 0 && wait_msec) + ERR("could not remove '%s': %s\n", modname, strerror(-err)); return err; } @@ -418,7 +460,7 @@ static int rmmod_do_module(struct kmod_module *mod, int flags) } /* 3. @mod itself, but check for refcnt first */ - if (!cmd && !ignore_loaded) { + if (!cmd && !ignore_loaded && !wait_msec) { int usage = kmod_module_get_refcnt(mod); if (usage > 0) { @@ -800,6 +842,16 @@ static int do_modprobe(int argc, char **orig_argv) case 5: remove_holders = 1; break; + case 'w': { + char *endptr = NULL; + wait_msec = strtoul(optarg, &endptr, 0); + if (!*optarg || *endptr) { + ERR("unexpected wait value '%s'.\n", optarg); + err = -1; + goto done; + } + break; + } case 3: first_time = 1; break; -- cgit v1.2.3 From 202040cbc77cde5a64c247b4226f264e05299f28 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 28 Jun 2022 22:23:34 -0700 Subject: Keep only one readme Signed-off-by: Lucas De Marchi --- README | 126 ----------------------------------------------------------------- 1 file changed, 126 deletions(-) delete mode 100644 README diff --git a/README b/README deleted file mode 100644 index 59eb301..0000000 --- a/README +++ /dev/null @@ -1,126 +0,0 @@ -kmod - Linux kernel module handling - -Information -=========== - -Mailing list: - linux-modules@vger.kernel.org (no subscription needed) - https://lore.kernel.org/linux-modules/ - -Signed packages: - http://www.kernel.org/pub/linux/utils/kernel/kmod/ - -Git: - git://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git - http://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git - https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git - -Gitweb: - http://git.kernel.org/?p=utils/kernel/kmod/kmod.git - https://github.com/kmod-project/kmod - -Irc: - #kmod on irc.freenode.org - -License: - LGPLv2.1+ for libkmod, testsuite and helper libraries - GPLv2+ for tools/* - - -OVERVIEW -======== - -kmod is a set of tools to handle common tasks with Linux kernel modules like -insert, remove, list, check properties, resolve dependencies and aliases. - -These tools are designed on top of libkmod, a library that is shipped with -kmod. See libkmod/README for more details on this library and how to use it. -The aim is to be compatible with tools, configurations and indexes from -module-init-tools project. - -Compilation and installation -============================ - -In order to compiler the source code you need following software packages: - - GCC compiler - - GNU C library - -Optional dependencies: - - ZLIB library - - LZMA library - -Typical configuration: - ./configure CFLAGS="-g -O2" --prefix=/usr \ - --sysconfdir=/etc --libdir=/usr/lib - -Configure automatically searches for all required components and packages. - -To compile and install run: - make && make install - -Hacking -======= - -Run 'autogen.sh' script before configure. If you want to accept the recommended -flags, you just need to run 'autogen.sh c'. Note that the recommended -flags require cython be installed to compile successfully. - -Make sure to read the CODING-STYLE file and the other READMEs: libkmod/README -and testsuite/README. - -Compatibility with module-init-tools -==================================== - -kmod replaces module-init-tools, which is end-of-life. Most of its tools are -rewritten on top of libkmod so it can be used as a drop in replacements. -Somethings however were changed. Reasons vary from "the feature was already -long deprecated on module-init-tools" to "it would be too much trouble to -support it". - -There are several features that are being added in kmod, but we don't -keep track of them here. - -modprobe --------- - -* 'modprobe -l' was marked as deprecated and does not exist anymore - -* 'modprobe -t' is gone, together with 'modprobe -l' - -* modprobe doesn't parse configuration files with names not ending in - '.alias' or '.conf'. modprobe used to warn about these files. - -* modprobe doesn't parse 'config' and 'include' commands in configuration - files. - -* modprobe from m-i-t does not honour softdeps for install commands. E.g.: - config: - - install bli "echo bli" - install bla "echo bla" - softdep bla pre: bli - - With m-i-t, the output of 'modprobe --show-depends bla' will be: - install "echo bla" - - While with kmod: - install "echo bli" - install "echo bla" - -* kmod doesn't dump the configuration as is in the config files. Instead it - dumps the configuration as it was parsed. Therefore, comments and file names - are not dumped, but on the good side we know what the exact configuration - kmod is using. We did this because if we only want to know the entire content - of configuration files, it's enough to use find(1) in modprobe.d directories - -depmod ------- - -* there's no 'depmod -m' option: legacy modules.*map files are gone - -lsmod ------ - -* module-init-tools used /proc/modules to parse module info. kmod uses - /sys/module/*, but there's a fallback to /proc/modules if the latter isn't - available -- cgit v1.2.3 From edc7f3a2d3e1bed358c64ff0ba9276c2610eac02 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 28 Jun 2022 22:24:41 -0700 Subject: README: Update optional dependencies Signed-off-by: Lucas De Marchi --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a83b4ac..590c8a8 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ In order to compiler the source code you need following software packages: Optional dependencies: - ZLIB library - LZMA library + - ZSTD library + - OPENSSL library (signature handling in modinfo) Typical configuration: ./configure CFLAGS="-g -O2" --prefix=/usr \ -- cgit v1.2.3 From f609cb5185acb0955d66795cb297e9fe9d83405a Mon Sep 17 00:00:00 2001 From: HuaxinLu Date: Thu, 30 Jun 2022 14:36:05 +0800 Subject: libkmod: Support SM3 hash algorithm SM3 has been supported in kernel and cryptographic libraries like openssl. This patch adds support for the SM3 algorithm of kmod. Signed-off-by: HuaxinLu --- libkmod/libkmod-signature.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libkmod/libkmod-signature.c b/libkmod/libkmod-signature.c index 4e8748c..4ae5af6 100644 --- a/libkmod/libkmod-signature.c +++ b/libkmod/libkmod-signature.c @@ -56,6 +56,7 @@ enum pkey_hash_algo { PKEY_HASH_SHA384, PKEY_HASH_SHA512, PKEY_HASH_SHA224, + PKEY_HASH_SM3, PKEY_HASH__LAST }; @@ -68,6 +69,7 @@ const char *const pkey_hash_algo[PKEY_HASH__LAST] = { [PKEY_HASH_SHA384] = "sha384", [PKEY_HASH_SHA512] = "sha512", [PKEY_HASH_SHA224] = "sha224", + [PKEY_HASH_SM3] = "sm3", }; enum pkey_id_type { @@ -161,6 +163,10 @@ static int obj_to_hash_algo(const ASN1_OBJECT *o) return PKEY_HASH_SHA512; case NID_sha224: return PKEY_HASH_SHA224; +# ifndef OPENSSL_NO_SM3 + case NID_sm3: + return PKEY_HASH_SM3; +# endif default: return -1; } -- cgit v1.2.3 From 5d46434a63ae0160150a0efdde1914873697e273 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 30 Jun 2022 08:19:17 -0700 Subject: kmod 30 --- Makefile.am | 6 ++--- NEWS | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- configure.ac | 2 +- 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index d859c24..0e48770 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,9 +57,9 @@ SED_PROCESS = \ # increment age. # 6. If any interfaces have been removed or changed since the last public # release, then set age to 0. -LIBKMOD_CURRENT=5 -LIBKMOD_REVISION=7 -LIBKMOD_AGE=3 +LIBKMOD_CURRENT=6 +LIBKMOD_REVISION=0 +LIBKMOD_AGE=4 noinst_LTLIBRARIES = shared/libshared.la shared_libshared_la_SOURCES = \ diff --git a/NEWS b/NEWS index a8c9194..fe95103 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,84 @@ +kmod 30 +======= + +- Improvements + - Stop adding duplicate information on modules.builtin.alias.bin, just use + the modules.builtin.bin index + + - Speedup depmod, particularly under qemu with emulated arch, by + avoiding a lot of open/read/close of modules.alias.bin. On an + emulated ARM rootfs, depmod with only 2 modules was taking ~32s + vs ~0.07s now. + + - Add kmod_module_new_from_name_lookup() which allows doing a lookup by + module name, without considering the aliases. Other than that search + order is similar to kmod_module_new_from_lookup(). + + - modinfo learned the --modname option to explicitely show information + about the module, even if there is an alias with the same name. This + allows showing information about e.g. kernel/lib/crc32.ko, even if + kernel also exports a crc32 alias in modules.alias: + + alias crc32 crc32_pclmul + alias crc32 crc32_generic + + Same behavior will be used to other modules and to aliases provided + by user/distro. + + - depmod.conf learned a new "excludedir" directive so distro/user can + configure more directories to be excluded from its search, besides + the hardcoded values "build" and "source". + + - Better group modprobe options on help output under "Management, Query and General". + + - modprobe learned a --wait option to be used together with -r + when removing a module. This allows modprobe to keep trying the + removal if it fails because the module is still in use. An exponential backoff + time is used for further retries. + + The wait behavior provided by the kernel when not passing O_NONBLOCK + to delete_module() was removed in v3.13 due to not be used and the + consequences of having to support it in the kernel. However there may + be some users, particularly on testsuites for individual susbsystems, that + would want that. So provide a userspace implementation inside modprobe for + such users. "rmmod" doesn't have a --wait as it remains a bare minimal over + the API provided by the kernel. In future the --wait behavior can be added + to libkmod for testsuites not exec'ing modprobe for module removal. + + - kmod_module_remove_module() learned a new flag to silence output when + caller wants to handle them - this is particularly important for the + --wait flag to modprobe, as it's not desired to keep seeing error messages + while waiting for the module to be unused. + + - Add SM3 hash algo support to modinfo output, as already available in the kernel. + +- Bug Fixes + - Fix modinfo output when showing information for a .ko module when running + on a kernel that has that module as builtin. + + - Fix kmod_module_new_from_lookup() returning > 0 rather than 0 + when it matches an alias. + + - Fix modinfo segfault when module doesn't exist. + + - Add missing function in the html documentation: kmod_get_dirname(). + + - Fix modprobe incorrectly handling number of arguments when prepending values from + MODPROBE_OPTIONS environment variable. + + - Fix modprobe -r --remove-dependencies and since "dependencies" was a + misnomer, add the preferred argument option: "--remove-holders". This + is the same name used by the kernel. It allows users to also remove + other modules holding the one that is being removed. + + - Fix off-by-one in max module name length in depmod. + +- Infra/internal + - Start some changes in the out-of-tree test modules in kmod so they are useful + for being really inserted in the kernel rather than relying on kmod's mock + interface. This helps manual testing and may be used to exercise to test + changes in the kernel. + kmod 29 ======= @@ -43,7 +124,6 @@ kmod 29 of the configuration used: now tests will skip if we don't have the build dependencies) - kmod 28 ======= diff --git a/configure.ac b/configure.ac index 136d5b7..6989e93 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.64) AC_INIT([kmod], - [29], + [30], [linux-modules@vger.kernel.org], [kmod], [http://git.kernel.org/?p=utils/kernel/kmod/kmod.git]) -- cgit v1.2.3