* [LTP] [Patch v2 0/4] tst_kconfig: automatic module load/unload for CONFIG_*=m
@ 2026-10-08 5:21 Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 1/4] lib: add module is loaded check Li Wang
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Li Wang @ 2026-10-08 5:21 UTC (permalink / raw)
To: ltp
Tests that depend on a config set to =m currently load the module
themselves, and may fail with misleading errors when it is missing,
e.g. bind() returning EADDRNOTAVAIL for AF_VSOCK without vsock_loopback.
This series makes tst_kconfig record the module for every
config_module_maps[] entry seen as =m, load them once the kernel
config check passes, and unload them at cleanup time.
Changes in v2:
- Add tst_module_is_loaded() helper.
- Only load/unload modules that are not already loaded.
- Skip automatic loading when KCONFIG_SKIP_CHECK=1, keeping the
semantics consistent with skipping the config check.
- Document the KCONFIG_SKIP_CHECK=1 behaviour for keyctl29/keyctl30
and the vsock/vsock_loopback mapping.
Li Wang (4):
lib: add module is loaded check
tst_kconfig: load and unload kernel modules for CONFIG_*=m
tst_kconfig: add module mappings for vsock/vsock_loopback
testcases: drop manual tst_modprobe() now handled by tst_kconfig
include/tst_kconfig.h | 28 +++++++
include/tst_module.h | 1 +
lib/tst_kconfig.c | 81 +++++++++++++++++++++
lib/tst_module.c | 39 ++++++++++
lib/tst_test.c | 11 ++-
testcases/cve/cve-2025-21756.c | 6 ++
testcases/cve/cve-2026-46331.c | 7 --
testcases/cve/sctphantom.c | 3 -
testcases/kernel/syscalls/keyctl/keyctl29.c | 3 -
testcases/kernel/syscalls/keyctl/keyctl30.c | 3 -
10 files changed, 164 insertions(+), 18 deletions(-)
--
2.56.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* [LTP] [Patch v2 1/4] lib: add module is loaded check
2026-10-08 5:21 [LTP] [Patch v2 0/4] tst_kconfig: automatic module load/unload for CONFIG_*=m Li Wang
@ 2026-10-08 5:21 ` Li Wang
2026-10-08 10:14 ` [LTP] " linuxtestproject.agent
2026-10-08 5:21 ` [LTP] [Patch v2 2/4] tst_kconfig: load and unload kernel modules for CONFIG_*=m Li Wang
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Li Wang @ 2026-10-08 5:21 UTC (permalink / raw)
To: ltp
Add a helper that checks whether a kernel module is loaded by
looking it up in /proc/modules. Module names are normalized so that
hyphens match the underscores used by the kernel.
Signed-off-by: Li Wang <li.wang@linux.dev>
---
include/tst_module.h | 1 +
lib/tst_module.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/include/tst_module.h b/include/tst_module.h
index e55321d19..9b789e289 100644
--- a/include/tst_module.h
+++ b/include/tst_module.h
@@ -49,5 +49,6 @@ static inline void tst_requires_module_signature_disabled(void)
void tst_modprobe(const char *mod_name, char *const argv[]);
void tst_module_reload(const char *mod_name, char *const argv[]);
+bool tst_module_is_loaded(const char *mod_name);
#endif /* TST_MODULE_H */
diff --git a/lib/tst_module.c b/lib/tst_module.c
index cbd2415d5..db341ec57 100644
--- a/lib/tst_module.c
+++ b/lib/tst_module.c
@@ -21,6 +21,7 @@
*/
#define _GNU_SOURCE
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -174,3 +175,41 @@ void tst_module_reload(const char *mod_name, char *const argv[])
tst_module_unload_(NULL, mod_name);
tst_modprobe(mod_name, argv);
}
+
+bool tst_module_is_loaded(const char *mod_name)
+{
+ char line[4096];
+ size_t mod_len = strlen(mod_name);
+ FILE *file;
+
+ file = fopen("/proc/modules", "r");
+ if (!file)
+ return false;
+
+ while (fgets(line, sizeof(line), file)) {
+ char *p = line;
+ size_t i;
+
+ while (*p && !isspace(*p))
+ p++;
+
+ if ((size_t)(p - line) != mod_len)
+ continue;
+
+ for (i = 0; i < mod_len; i++) {
+ char a = (line[i] == '-') ? '_' : line[i];
+ char b = (mod_name[i] == '-') ? '_' : mod_name[i];
+
+ if (a != b)
+ break;
+ }
+
+ if (i == mod_len) {
+ fclose(file);
+ return true;
+ }
+ }
+
+ fclose(file);
+ return false;
+}
--
2.56.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [LTP] [Patch v2 2/4] tst_kconfig: load and unload kernel modules for CONFIG_*=m
2026-10-08 5:21 [LTP] [Patch v2 0/4] tst_kconfig: automatic module load/unload for CONFIG_*=m Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 1/4] lib: add module is loaded check Li Wang
@ 2026-10-08 5:21 ` Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 3/4] tst_kconfig: add module mappings for vsock/vsock_loopback Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 4/4] testcases: drop manual tst_modprobe() now handled by tst_kconfig Li Wang
3 siblings, 0 replies; 8+ messages in thread
From: Li Wang @ 2026-10-08 5:21 UTC (permalink / raw)
To: ltp
Tests that depend on a config set to =m must currently load the
module themselves, and may fail with misleading errors when it is
not loaded, e.g. bind() returning EADDRNOTAVAIL for AF_VSOCK when
vsock_loopback is missing.
Record the module for every config_module_maps[] entry seen as =m
during kconfig_parse_line(), load them in
tst_kconfig_module_load() via tst_modprobe(), and unload them in
reverse order from tst_kconfig_module_unload_all(), called by
do_test_cleanup(). Modules still in use are skipped without
aborting the test.
Loading and unloading are performed only as root; otherwise the
recorded list is left untouched.
Signed-off-by: Li Wang <li.wang@linux.dev>
---
include/tst_kconfig.h | 28 +++++++++++++++
lib/tst_kconfig.c | 79 +++++++++++++++++++++++++++++++++++++++++++
lib/tst_test.c | 11 ++++--
3 files changed, 116 insertions(+), 2 deletions(-)
diff --git a/include/tst_kconfig.h b/include/tst_kconfig.h
index c454f3467..a525429d4 100644
--- a/include/tst_kconfig.h
+++ b/include/tst_kconfig.h
@@ -105,4 +105,32 @@ void tst_kcmdline_parse(struct tst_kcmdline_var params[], size_t params_len);
*/
int tst_has_slow_kconfig(void);
+/**
+ * tst_kconfig_module_load() - Load kernel modules for CONFIG_*=m entries.
+ *
+ * Loads every module recorded during the last kernel config check, in
+ * the order they were discovered. The list is populated by
+ * kconfig_module_record() from kconfig_parse_line() for each CONFIG_*
+ * entry that is set to =m and has a matching entry in
+ * config_module_maps[].
+ *
+ * Loading is skipped when not running as root, and does nothing when
+ * the recorded list is empty.
+ */
+void tst_kconfig_module_load(void);
+
+/**
+ * tst_kconfig_module_unload_all() - Unload modules loaded by
+ * tst_kconfig_module_load().
+ *
+ * Unloads every module recorded by tst_kconfig_module_load(), in
+ * reverse load order so that inter-module dependencies are respected.
+ * Modules still in use are skipped silently, leaving the system state
+ * as close as possible to what it was before the test started.
+ *
+ * Called from do_test_cleanup() so that the modules are released when
+ * the test finishes, regardless of the test result.
+ */
+void tst_kconfig_module_unload_all(void);
+
#endif /* TST_KCONFIG_H__ */
diff --git a/lib/tst_kconfig.c b/lib/tst_kconfig.c
index 49957e28d..fc03966ba 100644
--- a/lib/tst_kconfig.c
+++ b/lib/tst_kconfig.c
@@ -16,8 +16,15 @@
#include "tst_bool_expr.h"
#include "tst_safe_stdio.h"
+#include "tst_module.h"
#include "tst_kconfig_checks.h"
+#define MAX_LOADED_MODULES 16
+
+static const char *loaded_modules[MAX_LOADED_MODULES];
+static unsigned int loaded_module_count;
+static bool modules_loaded;
+
static int kconfig_skip_check(void)
{
char *skipped = getenv("KCONFIG_SKIP_CHECK");
@@ -189,6 +196,38 @@ static void kconfig_module_check(struct tst_kconfig_var *var)
}
}
+static const char *module_name_for_config(const char *cfg)
+{
+ size_t i;
+
+ for (i = 0; config_module_maps[i].config; i++) {
+ if (!strcmp(config_module_maps[i].config, cfg))
+ return config_module_maps[i].module_name;
+ }
+
+ return NULL;
+}
+
+static void kconfig_module_record(const char *cfg)
+{
+ unsigned int i;
+ const char *mod = module_name_for_config(cfg);
+
+ if (!mod)
+ return;
+
+ if (tst_module_is_loaded(mod))
+ return;
+
+ for (i = 0; i < loaded_module_count; i++) {
+ if (!strcmp(loaded_modules[i], mod))
+ return;
+ }
+
+ if (loaded_module_count < MAX_LOADED_MODULES)
+ loaded_modules[loaded_module_count++] = mod;
+}
+
static inline int kconfig_parse_line(const char *line,
struct tst_kconfig_var *vars,
unsigned int vars_len)
@@ -268,6 +307,7 @@ out:
vars[i].choice = 'm';
kconfig_runtime_check(&vars[i]);
kconfig_module_check(&vars[i]);
+ kconfig_module_record(vars[i].id);
return 1;
}
}
@@ -300,6 +340,45 @@ exit:
close_kconfig(fp);
}
+void tst_kconfig_module_load(void)
+{
+ unsigned int i;
+
+ if (geteuid() != 0)
+ return;
+
+ for (i = 0; i < loaded_module_count; i++) {
+ tst_res(TDEBUG, "Loading module '%s'", loaded_modules[i]);
+ tst_modprobe(loaded_modules[i], NULL);
+ }
+
+ modules_loaded = true;
+}
+
+void tst_kconfig_module_unload_all(void)
+{
+ unsigned int i;
+
+ if (!loaded_module_count)
+ return;
+
+ if (!modules_loaded)
+ return;
+
+ if (geteuid() != 0)
+ return;
+
+ for (i = loaded_module_count; i > 0; i--) {
+ const char *const argv[] = { "rmmod", loaded_modules[i - 1], NULL };
+
+ tst_res(TDEBUG, "Unloading module '%s'", loaded_modules[i - 1]);
+ tst_cmd(argv, "/dev/null", "/dev/null", TST_CMD_PASS_RETVAL);
+ }
+
+ loaded_module_count = 0;
+ modules_loaded = false;
+}
+
static size_t array_len(const char *const kconfigs[])
{
size_t i = 0;
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 10ff73397..f55830983 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1471,8 +1471,12 @@ static void do_setup(int argc, char *argv[])
check_supported_kver();
- if (tst_test->needs_kconfigs && tst_kconfig_check(tst_test->needs_kconfigs))
- tst_brk(TCONF, "Aborting due to unsuitable kernel config, see above!");
+ if (tst_test->needs_kconfigs) {
+ if (tst_kconfig_check(tst_test->needs_kconfigs))
+ tst_brk(TCONF, "Aborting due to unsuitable kernel config, see above!");
+
+ tst_kconfig_module_load();
+ }
if (tst_test->needs_root && geteuid() != 0)
tst_brk(TCONF, "Test needs to be run as root");
@@ -1690,6 +1694,9 @@ static void do_cleanup(void)
if (tst_test->restore_wallclock)
tst_wallclock_restore();
+ if (tst_test->needs_kconfigs)
+ tst_kconfig_module_unload_all();
+
cleanup_ipc();
}
--
2.56.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [LTP] [Patch v2 3/4] tst_kconfig: add module mappings for vsock/vsock_loopback
2026-10-08 5:21 [LTP] [Patch v2 0/4] tst_kconfig: automatic module load/unload for CONFIG_*=m Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 1/4] lib: add module is loaded check Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 2/4] tst_kconfig: load and unload kernel modules for CONFIG_*=m Li Wang
@ 2026-10-08 5:21 ` Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 4/4] testcases: drop manual tst_modprobe() now handled by tst_kconfig Li Wang
3 siblings, 0 replies; 8+ messages in thread
From: Li Wang @ 2026-10-08 5:21 UTC (permalink / raw)
To: ltp
Map CONFIG_VSOCKETS and CONFIG_VSOCKETS_LOOPBACK to their kernel
modules (vsock, vsock_loopback), so that tst_kconfig can load them
automatically when the test declares the matching configs.
cve-2025-21756 binds to VMADDR_CID_LOCAL, which requires the
vsock_loopback module. When the module is present but not loaded,
bind() fails with EADDRNOTAVAIL and the test aborts with TBROK
instead of exercising the CVE, so declare both configs in the test's
needs_kconfigs.
The test also needs root to load the modules and to run as the
vsock_loopback transport is not available from an unprivileged user
namespace.
Signed-off-by: Li Wang <li.wang@linux.dev>
---
lib/tst_kconfig.c | 2 ++
testcases/cve/cve-2025-21756.c | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/lib/tst_kconfig.c b/lib/tst_kconfig.c
index fc03966ba..b267c5f30 100644
--- a/lib/tst_kconfig.c
+++ b/lib/tst_kconfig.c
@@ -174,6 +174,8 @@ static struct config_module_map {
{"CONFIG_NET_ACT_PEDIT", "act_pedit"},
{"CONFIG_PKCS8_PRIVATE_KEY_PARSER", "pkcs8_key_parser"},
{"CONFIG_X509_CERTIFICATE_PARSER", "x509_key_parser"},
+ {"CONFIG_VSOCKETS", "vsock"},
+ {"CONFIG_VSOCKETS_LOOPBACK", "vsock_loopback"},
{}
};
diff --git a/testcases/cve/cve-2025-21756.c b/testcases/cve/cve-2025-21756.c
index 4245a4c95..1df8545c9 100644
--- a/testcases/cve/cve-2025-21756.c
+++ b/testcases/cve/cve-2025-21756.c
@@ -85,8 +85,14 @@ static void run(void)
}
static struct tst_test test = {
+ .needs_root = 1,
.test_all = run,
.taint_check = TST_TAINT_W | TST_TAINT_D,
+ .needs_kconfigs = (const char *const[]) {
+ "CONFIG_VSOCKETS",
+ "CONFIG_VSOCKETS_LOOPBACK",
+ NULL
+ },
.tags = (const struct tst_tag[]) {
{"linux-git", "fcdd2242c0231032fc84e1404315c245ae56322a"},
{"CVE", "2025-21756"},
--
2.56.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [LTP] [Patch v2 4/4] testcases: drop manual tst_modprobe() now handled by tst_kconfig
2026-10-08 5:21 [LTP] [Patch v2 0/4] tst_kconfig: automatic module load/unload for CONFIG_*=m Li Wang
` (2 preceding siblings ...)
2026-10-08 5:21 ` [LTP] [Patch v2 3/4] tst_kconfig: add module mappings for vsock/vsock_loopback Li Wang
@ 2026-10-08 5:21 ` Li Wang
3 siblings, 0 replies; 8+ messages in thread
From: Li Wang @ 2026-10-08 5:21 UTC (permalink / raw)
To: ltp
Now that tst_kconfig loads the modules for every CONFIG_*=m entry
listed in config_module_maps[] and unloads them again at cleanup
time, tests no longer have to call tst_modprobe() from setup().
Drop the explicit tst_modprobe() calls, and the now unused
tst_module.h includes, from:
- cve-2026-46331.c: sch_ingress, cls_matchall, act_pedit
- sctphantom.c: sctp
- keyctl29.c: x509_key_parser
- keyctl30.c: pkcs8_key_parser
All four tests already declare the matching configs in
.needs_kconfigs, so tst_kconfig takes care of loading the modules
before setup() runs and unloading them once the test finishes.
BTW, with KCONFIG_SKIP_CHECK=1 the config check returns early,
so the automatic module loading is skipped as well. Users who set
that variable are expected to ensure the required modules are
loaded themselves.
Signed-off-by: Li Wang <li.wang@linux.dev>
---
testcases/cve/cve-2026-46331.c | 7 -------
testcases/cve/sctphantom.c | 3 ---
testcases/kernel/syscalls/keyctl/keyctl29.c | 3 ---
testcases/kernel/syscalls/keyctl/keyctl30.c | 3 ---
4 files changed, 16 deletions(-)
diff --git a/testcases/cve/cve-2026-46331.c b/testcases/cve/cve-2026-46331.c
index 3d32a1cbb..3c8db5042 100644
--- a/testcases/cve/cve-2026-46331.c
+++ b/testcases/cve/cve-2026-46331.c
@@ -44,7 +44,6 @@
#include <linux/rtnetlink.h>
#include "tst_test.h"
-#include "tst_module.h"
#include "tst_net.h"
#include "tst_netdevice.h"
#include "lapi/if_ether.h"
@@ -136,12 +135,6 @@ static void setup(void)
{
struct sockaddr_in addr;
struct passwd *pw;
- static const char *const mods[] = {
- "sch_ingress", "cls_matchall", "act_pedit"
- };
-
- for (unsigned int i = 0; i < ARRAY_SIZE(mods); i++)
- tst_modprobe(mods[i], NULL);
/* Drop privileges so the reproducer runs as an unprivileged user */
pw = SAFE_GETPWNAM("nobody");
diff --git a/testcases/cve/sctphantom.c b/testcases/cve/sctphantom.c
index 83834b848..bdbe40286 100644
--- a/testcases/cve/sctphantom.c
+++ b/testcases/cve/sctphantom.c
@@ -50,7 +50,6 @@
*/
#include "tst_test.h"
-#include "tst_module.h"
#include "tst_checksum.h"
#include "tst_safe_net.h"
@@ -205,8 +204,6 @@ static void setup(void)
};
const struct tst_path_val *sysctl;
- tst_modprobe("sctp", NULL);
-
for (sysctl = sysctls; sysctl->path; sysctl++)
tst_sys_conf_save(sysctl);
diff --git a/testcases/kernel/syscalls/keyctl/keyctl29.c b/testcases/kernel/syscalls/keyctl/keyctl29.c
index afc0a093c..e66b39bcb 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl29.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl29.c
@@ -23,7 +23,6 @@
#include "keyctl_common.h"
#include "keyctl_pkey_data.h"
-#include "tst_module.h"
static key_serial_t cert_key;
static struct keyctl_pkey_query *query_buf;
@@ -32,8 +31,6 @@ static void setup(void)
{
SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
- tst_modprobe("x509_key_parser", NULL);
-
cert_key = add_asymmetric_key_or_tconf("cert", rsa2048_cert,
sizeof(rsa2048_cert),
"CONFIG_X509_CERTIFICATE_PARSER");
diff --git a/testcases/kernel/syscalls/keyctl/keyctl30.c b/testcases/kernel/syscalls/keyctl/keyctl30.c
index ef51bba33..4f43007e0 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl30.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl30.c
@@ -20,7 +20,6 @@
#include "keyctl_common.h"
#include "keyctl_pkey_data.h"
-#include "tst_module.h"
static key_serial_t priv_key;
static struct keyctl_pkey_query *query_buf;
@@ -29,8 +28,6 @@ static void setup(void)
{
SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
- tst_modprobe("pkcs8_key_parser", NULL);
-
priv_key = add_asymmetric_key_or_tconf("priv", rsa2048_pkcs8,
sizeof(rsa2048_pkcs8),
"CONFIG_PKCS8_PRIVATE_KEY_PARSER");
--
2.56.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [LTP] lib: add module is loaded check
2026-10-08 5:21 ` [LTP] [Patch v2 1/4] lib: add module is loaded check Li Wang
@ 2026-10-08 10:14 ` linuxtestproject.agent
2026-10-10 1:43 ` Li Wang
0 siblings, 1 reply; 8+ messages in thread
From: linuxtestproject.agent @ 2026-10-08 10:14 UTC (permalink / raw)
To: Li Wang; +Cc: ltp
Hi Li,
On Thu, 8 Oct 2026, Li Wang wrote:
> lib: add module is loaded check
--- [PATCH 1/4] ---
> diff --git a/include/tst_module.h b/include/tst_module.h
> +bool tst_module_is_loaded(const char *mod_name);
Low: Add kernel-doc for this new public API, including mod_name and the
return value. Document normalization, built-in modules, and the current
false return when /proc/modules cannot be read.
--- [PATCH 2/4] ---
> diff --git a/include/tst_kconfig.h b/include/tst_kconfig.h
> + * Called from do_test_cleanup() so that the modules are released when
> + * the test finishes, regardless of the test result.
Low: The actual caller is do_cleanup(), in the library parent process,
not do_test_cleanup(), which invokes the test's cleanup callback.
Correct the lifecycle description.
> diff --git a/lib/tst_kconfig.c b/lib/tst_kconfig.c
> +#define MAX_LOADED_MODULES 16
> + if (loaded_module_count < MAX_LOADED_MODULES)
> + loaded_modules[loaded_module_count++] = mod;
Medium: This commit already has 19 mappings, so a valid requirement list
with all 19 available as modules passes the config check but queues only
16, silently omitting three required loads. Size the storage from the
mapping table or allocate enough space instead of discarding entries.
> kconfig_module_check(&vars[i]);
> + kconfig_module_record(vars[i].id);
Medium: kconfig_module_check() can change choice to 'n' for an uninstalled
module, but this still queues it. For CONFIG_MMU | CONFIG_CAN_RAW with
MMU=y and an uninstalled CAN_RAW=m, the expression succeeds, then loading
can-raw aborts the otherwise runnable test. Queue only configs that
remain enabled after checking, without making optional branches mandatory.
> + for (i = 0; i < loaded_module_count; i++) {
> + tst_res(TDEBUG, "Loading module '%s'", loaded_modules[i]);
> + tst_modprobe(loaded_modules[i], NULL);
> + }
> +
> + modules_loaded = true;
High: If one modprobe succeeds and a later one aborts, modules_loaded is
still false, so the cleanup helper returns without unloading the earlier
module. Track each successful load immediately and let abort cleanup
unload that successful prefix, not unattempted entries.
> + const char *const argv[] = { "rmmod", loaded_modules[i - 1], NULL };
> + tst_cmd(argv, "/dev/null", "/dev/null", TST_CMD_PASS_RETVAL);
Medium: modprobe also inserts dependencies, but this removes only the
explicitly recorded names. With CONFIG_CAN=m and CONFIG_CAN_RAW=m,
loading can-raw also loads can; removing can-raw leaves the newly loaded,
unused can module behind. Track newly loaded dependencies and remove
only test-owned modules in dependency order.
--- [PATCH 3/4] ---
> The test also needs root to load the modules and to run as the
> vsock_loopback transport is not available from an unprivileged user
> namespace.
> diff --git a/testcases/cve/cve-2025-21756.c b/testcases/cve/cve-2025-21756.c
> + .needs_root = 1,
Low: Root is needed for module insertion, but loopback VSOCK on
nonprivileged ports in the initial namespaces does not require root;
an ordinary nonroot process is not an unprivileged user namespace.
Correct the commit message and document the loading-only requirement in
the test description. Drop privileges for the reproducer after the
framework has loaded the modules.
Verdict - Needs revision
Pre-existing issue: sctphantom's description requests manual module
preloading, although its setup already loaded sctp before this series.
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] lib: add module is loaded check
2026-10-08 10:14 ` [LTP] " linuxtestproject.agent
@ 2026-10-10 1:43 ` Li Wang
0 siblings, 0 replies; 8+ messages in thread
From: Li Wang @ 2026-10-10 1:43 UTC (permalink / raw)
To: linuxtestproject.agent; +Cc: ltp
linuxtestproject.agent@gmail.com wrote:
> --- [PATCH 1/4] ---
>
> > diff --git a/include/tst_module.h b/include/tst_module.h
> > +bool tst_module_is_loaded(const char *mod_name);
>
> Low: Add kernel-doc for this new public API, including mod_name and the
> return value. Document normalization, built-in modules, and the current
> false return when /proc/modules cannot be read.
No need, funtion name is clear enough.
> --- [PATCH 2/4] ---
>
> > diff --git a/include/tst_kconfig.h b/include/tst_kconfig.h
> > + * Called from do_test_cleanup() so that the modules are released when
> > + * the test finishes, regardless of the test result.
>
> Low: The actual caller is do_cleanup(), in the library parent process,
> not do_test_cleanup(), which invokes the test's cleanup callback.
> Correct the lifecycle description.
No. We would do the unload in the lib-cleanup but not test_cleanup.
> > diff --git a/lib/tst_kconfig.c b/lib/tst_kconfig.c
> > +#define MAX_LOADED_MODULES 16
> > + if (loaded_module_count < MAX_LOADED_MODULES)
> > + loaded_modules[loaded_module_count++] = mod;
>
> Medium: This commit already has 19 mappings, so a valid requirement list
> with all 19 available as modules passes the config check but queues only
> 16, silently omitting three required loads. Size the storage from the
> mapping table or allocate enough space instead of discarding entries.
True in theory, but rarely happens in practice. In LTP tests, I haven't
seen any test load more than 16 modules.
But to be on safe side, let's use 32.
> > kconfig_module_check(&vars[i]);
> > + kconfig_module_record(vars[i].id);
>
> Medium: kconfig_module_check() can change choice to 'n' for an uninstalled
> module, but this still queues it. For CONFIG_MMU | CONFIG_CAN_RAW with
> MMU=y and an uninstalled CAN_RAW=m, the expression succeeds, then loading
> can-raw aborts the otherwise runnable test. Queue only configs that
> remain enabled after checking, without making optional branches mandatory.
Good point, let's adding back v1 check:
kconfig_runtime_check(&vars[i]);
kconfig_module_check(&vars[i]);
+ if (vars[i].choice == 'm')
+ kconfig_module_record(vars[i].id);
> > + for (i = 0; i < loaded_module_count; i++) {
> > + tst_res(TDEBUG, "Loading module '%s'", loaded_modules[i]);
> > + tst_modprobe(loaded_modules[i], NULL);
> > + }
> > +
> > + modules_loaded = true;
>
> High: If one modprobe succeeds and a later one aborts, modules_loaded is
> still false, so the cleanup helper returns without unloading the earlier
> module. Track each successful load immediately and let abort cleanup
> unload that successful prefix, not unattempted entries.
No. tst_modprobe() never calls tst_brk() internally, so a failed load
doesn't trigger the abort path at all, execution just continues.
> > + const char *const argv[] = { "rmmod", loaded_modules[i - 1], NULL };
> > + tst_cmd(argv, "/dev/null", "/dev/null", TST_CMD_PASS_RETVAL);
>
> Medium: modprobe also inserts dependencies, but this removes only the
> explicitly recorded names. With CONFIG_CAN=m and CONFIG_CAN_RAW=m,
> loading can-raw also loads can; removing can-raw leaves the newly loaded,
> unused can module behind. Track newly loaded dependencies and remove
> only test-owned modules in dependency order.
Ok, maybe we can consider `modprobe -r`.
> --- [PATCH 3/4] ---
>
> > The test also needs root to load the modules and to run as the
> > vsock_loopback transport is not available from an unprivileged user
> > namespace.
> > diff --git a/testcases/cve/cve-2025-21756.c b/testcases/cve/cve-2025-21756.c
> > + .needs_root = 1,
>
> Low: Root is needed for module insertion, but loopback VSOCK on
> nonprivileged ports in the initial namespaces does not require root;
> an ordinary nonroot process is not an unprivileged user namespace.
> Correct the commit message and document the loading-only requirement in
> the test description. Drop privileges for the reproducer after the
> framework has loaded the modules.
Ok.
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] lib: add module is loaded check
2026-10-10 3:36 [LTP] [PATCH v3 1/4] lib: add module is loaded check Li Wang
@ 2026-10-10 9:38 ` linuxtestproject.agent
0 siblings, 0 replies; 8+ messages in thread
From: linuxtestproject.agent @ 2026-10-10 9:38 UTC (permalink / raw)
To: Li Wang; +Cc: ltp
Hi Li,
On 10 October 2026, Li Wang wrote:
> lib: add module is loaded check
--- [PATCH 1/4] ---
> diff --git a/include/tst_module.h b/include/tst_module.h
> +bool tst_module_is_loaded(const char *mod_name);
Low: The new public helper has no kernel-doc comment. Document mod_name,
hyphen normalization, return values, and whether built-in modules count
as loaded.
--- [PATCH 2/4] ---
> diff --git a/lib/tst_kconfig.c b/lib/tst_kconfig.c
> + for (i = 0; i < loaded_module_count; i++) {
> + tst_res(TDEBUG, "Loading module '%s'", loaded_modules[i]);
> + tst_modprobe(loaded_modules[i], NULL);
> + }
> +
> + modules_loaded = true;
High: If a later modprobe fails, tst_modprobe() aborts before modules_loaded
becomes true, so cleanup skips modules already loaded successfully.
Track each successful load separately and make partial-load cleanup
available before invoking the next modprobe.
> + const char *const argv[] = { "modprobe", "-r",
> + loaded_modules[i - 1], NULL };
High: modprobe -r also removes unused dependencies, including modules
loaded before the test and excluded from this list. For example, removing
can-raw can remove a pre-existing can module; snapshot dependency ownership
and remove only modules loaded by this test.
> + tst_cmd(argv, "/dev/null", "/dev/null", TST_CMD_PASS_RETVAL);
> + }
> +
> + loaded_module_count = 0;
Medium: Every removal error is discarded, both output streams are
suppressed, and the ownership list is then cleared. Keep teardown nonfatal,
but report failed removals with TWARN and the module name instead of
silently leaving new modules loaded.
--- [PATCH 3/4] ---
> diff --git a/testcases/cve/cve-2025-21756.c b/testcases/cve/cve-2025-21756.c
> + .needs_root = 1,
Low: Document the new root requirement in the test description: root is
needed to load the VSOCK modules, while the reproducer runs as nobody.
The commit message explains this, but the exported test description does
not.
Verdict - Needs revision
Pre-existing issue (not a patch finding):
The description in testcases/cve/sctphantom.c says to run modprobe sctp
manually, although setup() already loaded it before this series.
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-10 9:38 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-08 5:21 [LTP] [Patch v2 0/4] tst_kconfig: automatic module load/unload for CONFIG_*=m Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 1/4] lib: add module is loaded check Li Wang
2026-10-08 10:14 ` [LTP] " linuxtestproject.agent
2026-10-10 1:43 ` Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 2/4] tst_kconfig: load and unload kernel modules for CONFIG_*=m Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 3/4] tst_kconfig: add module mappings for vsock/vsock_loopback Li Wang
2026-10-08 5:21 ` [LTP] [Patch v2 4/4] testcases: drop manual tst_modprobe() now handled by tst_kconfig Li Wang
-- strict thread matches above, loose matches on Subject: below --
2026-10-10 3:36 [LTP] [PATCH v3 1/4] lib: add module is loaded check Li Wang
2026-10-10 9:38 ` [LTP] " linuxtestproject.agent
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.