Linux Documentation
 help / color / mirror / Atom feed
* [PATCH v6 00/11] kunit: Introduce UAPI testing framework
@ 2026-05-04  9:33 Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 01/11] kbuild: doc: add label for userprogs section Thomas Weißschuh
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier, Masahiro Yamada

Currently testing of userspace and in-kernel API use two different
frameworks. kselftests for the userspace ones and Kunit for the
in-kernel ones. Besides their different scopes, both have different
strengths and limitations:

Kunit:
* Tests are normal kernel code.
* They use the regular kernel toolchain.
* They can be packaged and distributed as modules conveniently.

Kselftests:
* Tests are normal userspace code
* They need a userspace toolchain.
  A kernel cross toolchain is likely not enough.
* A fair amout of userland is required to run the tests,
  which means a full distro or handcrafted rootfs.
* There is no way to conveniently package and run kselftests with a
  given kernel image.
* The kselftests makefiles are not as powerful as regular kbuild.
  For example they are missing proper header dependency tracking or more
  complex compiler option modifications.

Therefore kunit is much easier to run against different kernel
configurations and architectures.
This series aims to combine kselftests and kunit, avoiding both their
limitations. It works by compiling the userspace kselftests as part of
the regular kernel build, embedding them into the kunit kernel or module
and executing them from there. If the kernel toolchain is not fit to
produce userspace because of a missing libc, the kernel's own nolibc can
be used instead.
The structured TAP output from the kselftest is integrated into the
kunit KTAP output transparently, the kunit parser can parse the combined
logs together.

Further room for improvements:
* Call each test in its completely dedicated namespace
* Handle additional test files besides the test executable through
  archives. CPIO, cramfs, etc.
* Expose the blobs in debugfs
* Provide some convience wrappers around compat userprogs
* Figure out a migration path/coexistence solution for
  kunit UAPI and tools/testing/selftests/

Output from the kunit example testcase, note the output of
"example_uapi_tests".

$ ./tools/testing/kunit/kunit.py run --kunitconfig lib/kunit example
...
Running tests with:
$ .kunit/linux kunit.filter_glob=example kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[11:53:53] ================== example (10 subtests) ===================
[11:53:53] [PASSED] example_simple_test
[11:53:53] [SKIPPED] example_skip_test
[11:53:53] [SKIPPED] example_mark_skipped_test
[11:53:53] [PASSED] example_all_expect_macros_test
[11:53:53] [PASSED] example_static_stub_test
[11:53:53] [PASSED] example_static_stub_using_fn_ptr_test
[11:53:53] [PASSED] example_priv_test
[11:53:53] =================== example_params_test  ===================
[11:53:53] [SKIPPED] example value 3
[11:53:53] [PASSED] example value 2
[11:53:53] [PASSED] example value 1
[11:53:53] [SKIPPED] example value 0
[11:53:53] =============== [PASSED] example_params_test ===============
[11:53:53] [PASSED] example_slow_test
[11:53:53] ======================= (4 subtests) =======================
[11:53:53] [PASSED] procfs
[11:53:53] [PASSED] userspace test 2
[11:53:53] [SKIPPED] userspace test 3: some reason
[11:53:53] [PASSED] userspace test 4
[11:53:53] ================ [PASSED] example_uapi_test ================
[11:53:53] ===================== [PASSED] example =====================
[11:53:53] ============================================================
[11:53:53] Testing complete. Ran 16 tests: passed: 11, skipped: 5
[11:53:53] Elapsed time: 67.543s total, 1.823s configuring, 65.655s building, 0.058s running

---
Changes in v6:
- Use usermode helper framework
- Trim now unnecessary new module exports
- Report unhandled output line
- Add SUPERH to ARCH_HAS_NOLIBC
- Remove non-integral patches submitted elsewhere
- Drop CC_CAN_LINK_STATIC support. It is based on CC_CAN_LINK which is
  currently being reworked.
- Use more cleanup helpers
- Split stdout/stderr forwarding into its own patch
- Link to v5: https://lore.kernel.org/r/20250717-kunit-kselftests-v5-0-442b711cde2e@linutronix.de

Changes in v5:
- Initialize output variable of kernel_wait()
- Fix .incbin with in-tree builds
- Keep requirement of KTAP tests to have a number which was removed accidentally
- Only synthesize KTAP subtest failure if the outer one is TestStatus.FAILURE
- Use -I instead of -isystem in NOLIBC_USERCFLAGS to populate dependency files
- +To filesystem developers to all patches
- +To Luis Chamberlain for discussions about usage of usermodehelper
  (see patches 6 and 12)
- Link to v4: https://lore.kernel.org/r/20250626-kunit-kselftests-v4-0-48760534fef5@linutronix.de

Changes in v4:
- Move Kconfig.nolibc from tools/ to init/
- Drop generic userprogs nolibc integration
- Drop generic blob framework
- Pick up review tags from David
- Extend new kunit TAP parser tests
- Add MAINTAINERS entry
- Allow CONFIG_KUNIT_UAPI=m
- Split /proc validation into dedicated UAPI test
- Trim recipient list a bit
- Use KUNIT_FAIL_AND_ABORT() over KUNIT_FAIL()
- Link to v3: https://lore.kernel.org/r/20250611-kunit-kselftests-v3-0-55e3d148cbc6@linutronix.de

Changes in v3:
- Reintroduce CONFIG_CC_CAN_LINK_STATIC
- Enable CONFIG_ARCH_HAS_NOLIBC for m68k and SPARC
- Properly handle 'clean' target for userprogs
- Use ramfs over tmpfs to reduce dependencies
- Inherit userprogs byte order and ABI from kernel
- Drop now unnecessary "#ifndef NOLIBC"
- Pick up review tags
- Drop usage of __private in blob.h,
  sparse complains and it is not really necessary
- Fix execution on loongarch when using clang
- Drop userprogs libgcc handling, it was ugly and is not yet necessary
- Link to v2: https://lore.kernel.org/r/20250407-kunit-kselftests-v2-0-454114e287fd@linutronix.de

Changes in v2:
- Rebase onto v6.15-rc1
- Add documentation and kernel docs
- Resolve invalid kconfig breakages
- Drop already applied patch "kbuild: implement CONFIG_HEADERS_INSTALL for Usermode Linux"
- Drop userprogs CONFIG_WERROR integration, it doesn't need to be part of this series
- Replace patch prefix "kconfig" with "kbuild"
- Rename kunit_uapi_run_executable() to kunit_uapi_run_kselftest()
- Generate private, conflict-free symbols in the blob framework
- Handle kselftest exit codes
- Handle SIGABRT
- Forward output also to kunit debugfs log
- Install a fd=0 stdin filedescriptor
- Link to v1: https://lore.kernel.org/r/20250217-kunit-kselftests-v1-0-42b4524c3b0a@linutronix.de

To: Nathan Chancellor <nathan@kernel.org>
To: Andrew Morton <akpm@linux-foundation.org>
To: Willy Tarreau <w@1wt.eu>
To: Thomas Weißschuh <linux@weissschuh.net>
To: Brendan Higgins <brendan.higgins@linux.dev>
To: David Gow <davidgow@google.com>
To: Rae Moar <rmoar@google.com>
To: Shuah Khan <shuah@kernel.org>
To: Jonathan Corbet <corbet@lwn.net>
To: Nicolas Schier <nicolas.schier@linux.dev>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: linux-kbuild@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
Cc: kunit-dev@googlegroups.com
Cc: linux-doc@vger.kernel.org
Cc: workflows@vger.kernel.org
To: Kees Cook <kees@kernel.org>
To: Alexander Viro <viro@zeniv.linux.org.uk>
To: Christian Brauner <brauner@kernel.org>
To: Jan Kara <jack@suse.cz>
To: Christoph Hellwig <hch@lst.de>
To: Luis Chamberlain <mcgrof@kernel.org>
Cc: linux-mm@kvack.org
Cc: linux-fsdevel@vger.kernel.org
Cc: Nicolas Schier <n.schier@avm.de>
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>

---
Thomas Weißschuh (11):
      kbuild: doc: add label for userprogs section
      exec: add dirfd parameter to kernel_execve()
      umh: add dirfd parameter
      mount: add support for __free(kern_unmount)
      init: add nolibc build support
      kunit: qemu_configs: loongarch: Enable LSX/LSAX
      kunit: Introduce UAPI testing framework
      kunit: uapi: Forward test executable output to KUnit log
      kunit: uapi: Add example for UAPI tests
      kunit: uapi: Introduce preinit executable
      kunit: uapi: Validate usability of /proc

 Documentation/dev-tools/kunit/api/index.rst   |   5 +
 Documentation/dev-tools/kunit/api/uapi.rst    |  14 +
 Documentation/kbuild/makefiles.rst            |   2 +
 MAINTAINERS                                   |  11 +
 fs/coredump.c                                 |   2 +-
 fs/exec.c                                     |   4 +-
 include/kunit/uapi.h                          |  77 ++++++
 include/linux/binfmts.h                       |   2 +-
 include/linux/mount.h                         |   2 +
 include/linux/umh.h                           |   3 +-
 init/Kconfig                                  |   2 +
 init/Kconfig.nolibc                           |  16 ++
 init/Makefile.nolibc                          |  13 +
 init/main.c                                   |   2 +-
 kernel/module/kmod.c                          |   2 +-
 kernel/umh.c                                  |   9 +-
 lib/kobject_uevent.c                          |   2 +-
 lib/kunit/Kconfig                             |  16 ++
 lib/kunit/Makefile                            |  26 ++
 lib/kunit/kunit-example-test.c                |  15 ++
 lib/kunit/kunit-example-uapi.c                |  22 ++
 lib/kunit/kunit-test-uapi.c                   |  51 ++++
 lib/kunit/kunit-test.c                        |  24 +-
 lib/kunit/kunit-uapi.c                        | 351 ++++++++++++++++++++++++++
 lib/kunit/uapi-preinit.c                      |  68 +++++
 security/keys/request_key.c                   |   2 +-
 tools/testing/kunit/qemu_configs/loongarch.py |   2 +
 27 files changed, 732 insertions(+), 13 deletions(-)
---
base-commit: 813d26ba48f9e3909d39966857421500faef508a
change-id: 20241015-kunit-kselftests-56273bc40442

Best regards,
--  
Thomas Weißschuh <thomas.weissschuh@linutronix.de>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v6 01/11] kbuild: doc: add label for userprogs section
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 02/11] exec: add dirfd parameter to kernel_execve() Thomas Weißschuh
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier, Masahiro Yamada

Some upcoming documentation will link directly to the userprogs section.

Add a label to the section so it can be referenced.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Nicolas Schier <n.schier@avm.de>
Acked-by: Masahiro Yamada <masahiroy@kernel.org>
---
 Documentation/kbuild/makefiles.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
index 24a4708d26e8..6e54ad4cfecb 100644
--- a/Documentation/kbuild/makefiles.rst
+++ b/Documentation/kbuild/makefiles.rst
@@ -891,6 +891,8 @@ This is possible in two ways:
     This will tell kbuild to build lxdialog even if not referenced in
     any rule.
 
+.. _kbuild_userprogs:
+
 Userspace Program support
 =========================
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 02/11] exec: add dirfd parameter to kernel_execve()
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 01/11] kbuild: doc: add label for userprogs section Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 03/11] umh: add dirfd parameter Thomas Weißschuh
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

Allow callers to specify the directory against which to resolve the
program filename. Enables running executables from private mounts.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
 fs/exec.c               | 4 ++--
 include/linux/binfmts.h | 2 +-
 init/main.c             | 2 +-
 kernel/umh.c            | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index ba12b4c466f6..affae4b4f6f6 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1846,7 +1846,7 @@ static int do_execveat_common(int fd, struct filename *filename,
 	return bprm_execve(bprm);
 }
 
-int kernel_execve(const char *kernel_filename,
+int kernel_execve(int dirfd, const char *kernel_filename,
 		  const char *const *argv, const char *const *envp)
 {
 	int retval;
@@ -1856,7 +1856,7 @@ int kernel_execve(const char *kernel_filename,
 		return -EINVAL;
 
 	CLASS(filename_kernel, filename)(kernel_filename);
-	CLASS(bprm, bprm)(AT_FDCWD, filename, 0);
+	CLASS(bprm, bprm)(dirfd, filename, 0);
 	if (IS_ERR(bprm))
 		return PTR_ERR(bprm);
 
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 65abd5ab8836..04e2b7a85b2b 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -144,7 +144,7 @@ int copy_string_kernel(const char *arg, struct linux_binprm *bprm);
 extern void set_binfmt(struct linux_binfmt *new);
 extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t);
 
-int kernel_execve(const char *filename,
+int kernel_execve(int dirfd, const char *filename,
 		  const char *const *argv, const char *const *envp);
 
 #endif /* _LINUX_BINFMTS_H */
diff --git a/init/main.c b/init/main.c
index 96f93bb06c49..551d03681234 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1511,7 +1511,7 @@ static int run_init_process(const char *init_filename)
 	pr_debug("  with environment:\n");
 	for (p = envp_init; *p; p++)
 		pr_debug("    %s\n", *p);
-	return kernel_execve(init_filename, argv_init, envp_init);
+	return kernel_execve(AT_FDCWD, init_filename, argv_init, envp_init);
 }
 
 static int try_to_run_init_process(const char *init_filename)
diff --git a/kernel/umh.c b/kernel/umh.c
index cffda97d961c..bab134fa8c36 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -106,7 +106,7 @@ static int call_usermodehelper_exec_async(void *data)
 	commit_creds(new);
 
 	wait_for_initramfs();
-	retval = kernel_execve(sub_info->path,
+	retval = kernel_execve(AT_FDCWD, sub_info->path,
 			       (const char *const *)sub_info->argv,
 			       (const char *const *)sub_info->envp);
 out:

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 03/11] umh: add dirfd parameter
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 01/11] kbuild: doc: add label for userprogs section Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 02/11] exec: add dirfd parameter to kernel_execve() Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 04/11] mount: add support for __free(kern_unmount) Thomas Weißschuh
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

Allow callers to specify the directory against which to resolve the
helper's filename. Enables the running of helpers from private mounts.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
 fs/coredump.c               | 2 +-
 include/linux/umh.h         | 3 ++-
 kernel/module/kmod.c        | 2 +-
 kernel/umh.c                | 9 ++++++---
 lib/kobject_uevent.c        | 2 +-
 security/keys/request_key.c | 2 +-
 6 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/fs/coredump.c b/fs/coredump.c
index bb6fdb1f458e..45df2387be3d 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -1015,7 +1015,7 @@ static bool coredump_pipe(struct core_name *cn, struct coredump_params *cprm,
 		helper_argv[argi] = cn->corename + argv[argi];
 	helper_argv[argi] = NULL;
 
-	sub_info = call_usermodehelper_setup(helper_argv[0], helper_argv, NULL,
+	sub_info = call_usermodehelper_setup(AT_FDCWD, helper_argv[0], helper_argv, NULL,
 					     GFP_KERNEL, umh_coredump_setup,
 					     NULL, cprm);
 	if (!sub_info)
diff --git a/include/linux/umh.h b/include/linux/umh.h
index daa6a7048c11..6670b9ff85d4 100644
--- a/include/linux/umh.h
+++ b/include/linux/umh.h
@@ -20,6 +20,7 @@ struct file;
 struct subprocess_info {
 	struct work_struct work;
 	struct completion *complete;
+	int dirfd;
 	const char *path;
 	char **argv;
 	char **envp;
@@ -34,7 +35,7 @@ extern int
 call_usermodehelper(const char *path, char **argv, char **envp, int wait);
 
 extern struct subprocess_info *
-call_usermodehelper_setup(const char *path, char **argv, char **envp,
+call_usermodehelper_setup(int dirfd, const char *path, char **argv, char **envp,
 			  gfp_t gfp_mask,
 			  int (*init)(struct subprocess_info *info, struct cred *new),
 			  void (*cleanup)(struct subprocess_info *), void *data);
diff --git a/kernel/module/kmod.c b/kernel/module/kmod.c
index a25dccdf7aa7..a85c57a707af 100644
--- a/kernel/module/kmod.c
+++ b/kernel/module/kmod.c
@@ -95,7 +95,7 @@ static int call_modprobe(char *orig_module_name, int wait)
 	argv[3] = module_name;	/* check free_modprobe_argv() */
 	argv[4] = NULL;
 
-	info = call_usermodehelper_setup(modprobe_path, argv, envp, GFP_KERNEL,
+	info = call_usermodehelper_setup(AT_FDCWD, modprobe_path, argv, envp, GFP_KERNEL,
 					 NULL, free_modprobe_argv, NULL);
 	if (!info)
 		goto free_module_name;
diff --git a/kernel/umh.c b/kernel/umh.c
index bab134fa8c36..5cdcba6005d9 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -106,7 +106,7 @@ static int call_usermodehelper_exec_async(void *data)
 	commit_creds(new);
 
 	wait_for_initramfs();
-	retval = kernel_execve(AT_FDCWD, sub_info->path,
+	retval = kernel_execve(sub_info->dirfd, sub_info->path,
 			       (const char *const *)sub_info->argv,
 			       (const char *const *)sub_info->envp);
 out:
@@ -331,6 +331,7 @@ static void helper_unlock(void)
 
 /**
  * call_usermodehelper_setup - prepare to call a usermode helper
+ * @dirfd: directory to resolve path against
  * @path: path to usermode executable
  * @argv: arg vector for process
  * @envp: environment for process
@@ -352,7 +353,7 @@ static void helper_unlock(void)
  * Function must be runnable in either a process context or the
  * context in which call_usermodehelper_exec is called.
  */
-struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv,
+struct subprocess_info *call_usermodehelper_setup(int dirfd, const char *path, char **argv,
 		char **envp, gfp_t gfp_mask,
 		int (*init)(struct subprocess_info *info, struct cred *new),
 		void (*cleanup)(struct subprocess_info *info),
@@ -366,8 +367,10 @@ struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv,
 	INIT_WORK(&sub_info->work, call_usermodehelper_exec_work);
 
 #ifdef CONFIG_STATIC_USERMODEHELPER
+	sub_info->dirfd = AT_FDCWD;
 	sub_info->path = CONFIG_STATIC_USERMODEHELPER_PATH;
 #else
+	sub_info->dirfd = dirfd;
 	sub_info->path = path;
 #endif
 	sub_info->argv = argv;
@@ -484,7 +487,7 @@ int call_usermodehelper(const char *path, char **argv, char **envp, int wait)
 	struct subprocess_info *info;
 	gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
 
-	info = call_usermodehelper_setup(path, argv, envp, gfp_mask,
+	info = call_usermodehelper_setup(AT_FDCWD, path, argv, envp, gfp_mask,
 					 NULL, NULL, NULL);
 	if (info == NULL)
 		return -ENOMEM;
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index ddbc4d7482d2..426ac83f1d2a 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -628,7 +628,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
 			goto exit;
 
 		retval = -ENOMEM;
-		info = call_usermodehelper_setup(env->argv[0], env->argv,
+		info = call_usermodehelper_setup(AT_FDCWD, env->argv[0], env->argv,
 						 env->envp, GFP_KERNEL,
 						 NULL, cleanup_uevent_env, env);
 		if (info) {
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index a7673ad86d18..f6f3d4bc0bda 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -101,7 +101,7 @@ static int call_usermodehelper_keys(const char *path, char **argv, char **envp,
 {
 	struct subprocess_info *info;
 
-	info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL,
+	info = call_usermodehelper_setup(AT_FDCWD, path, argv, envp, GFP_KERNEL,
 					  umh_keys_init, umh_keys_cleanup,
 					  session_keyring);
 	if (!info)

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 04/11] mount: add support for __free(kern_unmount)
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (2 preceding siblings ...)
  2026-05-04  9:33 ` [PATCH v6 03/11] umh: add dirfd parameter Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 05/11] init: add nolibc build support Thomas Weißschuh
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

Allow usage of kern_unmount from the automatic __free cleanup logic.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
 include/linux/mount.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/mount.h b/include/linux/mount.h
index acfe7ef86a1b..d8689ce61a42 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -10,6 +10,7 @@
 #ifndef _LINUX_MOUNT_H
 #define _LINUX_MOUNT_H
 
+#include <linux/cleanup.h>
 #include <linux/types.h>
 #include <asm/barrier.h>
 
@@ -99,6 +100,7 @@ extern bool our_mnt(struct vfsmount *mnt);
 
 extern struct vfsmount *kern_mount(struct file_system_type *);
 extern void kern_unmount(struct vfsmount *mnt);
+DEFINE_FREE(kern_unmount, struct vfsmount *, if (_T) kern_unmount(_T));
 extern int may_umount_tree(struct vfsmount *);
 extern int may_umount(struct vfsmount *);
 int do_mount(const char *, const char __user *,

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 05/11] init: add nolibc build support
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (3 preceding siblings ...)
  2026-05-04  9:33 ` [PATCH v6 04/11] mount: add support for __free(kern_unmount) Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 06/11] kunit: qemu_configs: loongarch: Enable LSX/LSAX Thomas Weißschuh
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

Building userspace applications through the kbuild "userprogs" framework
requires a libc. Kernel toolchains often do not contain a libc.
In this case it is useful to use the nolibc library from the kernel tree.
Nolibc does not support all architectures and requires compiler flags.

Add a kconfig option, so users can know where it is available and provide a
variable for common options.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Nicolas Schier <n.schier@avm.de>
---
 MAINTAINERS          |  2 ++
 init/Kconfig         |  2 ++
 init/Kconfig.nolibc  | 16 ++++++++++++++++
 init/Makefile.nolibc | 13 +++++++++++++
 4 files changed, 33 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2fb1c75afd16..be4f6242b3fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18960,6 +18960,8 @@ M:	Willy Tarreau <w@1wt.eu>
 M:	Thomas Weißschuh <linux@weissschuh.net>
 S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc.git
+F:	init/Kconfig.nolibc
+F:	init/Makefile.nolibc
 F:	tools/include/nolibc/
 F:	tools/testing/selftests/nolibc/
 
diff --git a/init/Kconfig b/init/Kconfig
index 3bb92a3f6cc1..c37d9227ba72 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -106,6 +106,8 @@ config CC_CAN_LINK
 	default $(cc_can_link_user,$(m64-flag)) if 64BIT
 	default $(cc_can_link_user,$(m32-flag))
 
+source "init/Kconfig.nolibc"
+
 # Fixed in GCC 14, 13.3, 12.4 and 11.5
 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921
 config GCC_ASM_GOTO_OUTPUT_BROKEN
diff --git a/init/Kconfig.nolibc b/init/Kconfig.nolibc
new file mode 100644
index 000000000000..07488ef18f4f
--- /dev/null
+++ b/init/Kconfig.nolibc
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARCH_HAS_NOLIBC
+	bool
+	default y if ARM
+	default y if ARM64
+	default y if LOONGARCH
+	default y if M68K
+	default y if MIPS
+	default y if PPC
+	default y if RISCV
+	default y if S390
+	default y if SPARC
+	default y if SUPERH
+	default y if UML_X86
+	default y if X86
diff --git a/init/Makefile.nolibc b/init/Makefile.nolibc
new file mode 100644
index 000000000000..dacc78ab4c81
--- /dev/null
+++ b/init/Makefile.nolibc
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+# Compiler flags, which are necessary to build userspace applications with the
+# in-kernel libc "nolibc".
+
+ifeq ($(and $(CONFIG_ARCH_HAS_NOLIBC),$(CONFIG_HEADERS_INSTALL)),y)
+
+NOLIBC_USERCFLAGS := -nostdlib -nostdinc -static -ffreestanding \
+		     -fno-asynchronous-unwind-tables -fno-stack-protector \
+		     -I$(objtree)/usr/include -I$(srctree)/tools/include/nolibc/
+
+NOLIBC_USERLDFLAGS := -nostdlib -nostdinc -static
+
+endif # CONFIG_ARCH_HAS_NOLIBC && CONFIG_HEADERS_INSTALL

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 06/11] kunit: qemu_configs: loongarch: Enable LSX/LSAX
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (4 preceding siblings ...)
  2026-05-04  9:33 ` [PATCH v6 05/11] init: add nolibc build support Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 07/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

The upcoming kunit UAPI framework will run userspace executables as part of
kunit. These may use the LSX or LASX instructions.

Make sure the kunit kernel can handle these instructions.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: David Gow <davidgow@google.com>
---
 tools/testing/kunit/qemu_configs/loongarch.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/testing/kunit/qemu_configs/loongarch.py b/tools/testing/kunit/qemu_configs/loongarch.py
index a92422967d1d..1dba755284f1 100644
--- a/tools/testing/kunit/qemu_configs/loongarch.py
+++ b/tools/testing/kunit/qemu_configs/loongarch.py
@@ -11,6 +11,8 @@ CONFIG_PVPANIC_PCI=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_CPU_HAS_LSX=y
+CONFIG_CPU_HAS_LASX=y
 ''',
 			   qemu_arch='loongarch64',
 			   kernel_path='arch/loongarch/boot/vmlinux.elf',

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 07/11] kunit: Introduce UAPI testing framework
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (5 preceding siblings ...)
  2026-05-04  9:33 ` [PATCH v6 06/11] kunit: qemu_configs: loongarch: Enable LSX/LSAX Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 08/11] kunit: uapi: Forward test executable output to KUnit log Thomas Weißschuh
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

Enable running UAPI tests as part of kunit.
The selftests are embedded into the kernel image and their output is
forwarded to kunit for unified reporting.

The implementation reuses parts of usermode drivers and usermode
helpers. However these frameworks are not used directly as they make it
impossible to retrieve a thread's exit code.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
 Documentation/dev-tools/kunit/api/index.rst |   5 +
 Documentation/dev-tools/kunit/api/uapi.rst  |  14 ++
 MAINTAINERS                                 |   6 +
 include/kunit/uapi.h                        |  77 +++++++++++
 lib/kunit/Kconfig                           |  16 +++
 lib/kunit/Makefile                          |   2 +
 lib/kunit/kunit-uapi.c                      | 193 ++++++++++++++++++++++++++++
 7 files changed, 313 insertions(+)

diff --git a/Documentation/dev-tools/kunit/api/index.rst b/Documentation/dev-tools/kunit/api/index.rst
index 5cdb552a0808..34d8fee9a970 100644
--- a/Documentation/dev-tools/kunit/api/index.rst
+++ b/Documentation/dev-tools/kunit/api/index.rst
@@ -9,6 +9,7 @@ API Reference
 	test
 	resource
 	functionredirection
+	uapi
 	clk
 	of
 	platformdevice
@@ -32,6 +33,10 @@ Documentation/dev-tools/kunit/api/functionredirection.rst
 
  - Documents the KUnit Function Redirection API
 
+Documentation/dev-tools/kunit/api/uapi.rst
+
+ - Documents the KUnit Userspace testing API
+
 Driver KUnit API
 ================
 
diff --git a/Documentation/dev-tools/kunit/api/uapi.rst b/Documentation/dev-tools/kunit/api/uapi.rst
new file mode 100644
index 000000000000..1f01b5c6c9db
--- /dev/null
+++ b/Documentation/dev-tools/kunit/api/uapi.rst
@@ -0,0 +1,14 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==================
+Userspace Test API
+==================
+
+This file documents all of the userspace testing API.
+Userspace tests are built as :ref:`kbuild userprogs <kbuild_userprogs>`,
+linked statically and without any external dependencies.
+
+For the widest platform compatibility they should use nolibc, as provided by `init/Makefile.nolibc`.
+
+.. kernel-doc:: include/kunit/uapi.h
+   :internal:
diff --git a/MAINTAINERS b/MAINTAINERS
index be4f6242b3fc..e29ca56f7334 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14395,6 +14395,12 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/leds/backlight/kinetic,ktz8866.yaml
 F:	drivers/video/backlight/ktz8866.c
 
+KUNIT UAPI TESTING FRAMEWORK (in addition to KERNEL UNIT TESTING FRAMEWORK)
+M:	Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+S:	Maintained
+F:	include/kunit/uapi.h
+F:	lib/kunit/kunit-uapi.c
+
 KVM PARAVIRT (KVM/paravirt)
 M:	Paolo Bonzini <pbonzini@redhat.com>
 R:	Vitaly Kuznetsov <vkuznets@redhat.com>
diff --git a/include/kunit/uapi.h b/include/kunit/uapi.h
new file mode 100644
index 000000000000..1e0585355124
--- /dev/null
+++ b/include/kunit/uapi.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KUnit Userspace testing API.
+ *
+ * Copyright (C) 2026, Linutronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ */
+
+#ifndef _KUNIT_UAPI_H
+#define _KUNIT_UAPI_H
+
+#include <linux/types.h>
+
+struct kunit;
+
+/**
+ * struct kunit_uapi_blob - Blob embedded build artifact
+ * @path: Path of the embedded artifact.
+ * @data: Start of the embedded data in memory.
+ * @end: End of the embedded data in memory.
+ */
+struct kunit_uapi_blob {
+	const char *const path;
+	const u8 *data;
+	const u8 *end;
+};
+
+#if IS_ENABLED(CONFIG_KUNIT_UAPI)
+
+/**
+ * KUNIT_UAPI_EMBED_BLOB() - Embed another build artifact into the kernel
+ * @_name: The name of symbol under which the artifact is embedded.
+ * @_path: Path to the artifact on disk.
+ *
+ * Embeds a build artifact like a userspace executable into the kernel or current module.
+ * The build artifact is read from disk and needs to be already built.
+ */
+#define KUNIT_UAPI_EMBED_BLOB(_name, _path)					\
+	asm (									\
+	"	.pushsection .rodata, \"a\"				\n"	\
+	"	.global " __stringify(CONCATENATE(_name, _data)) "	\n"	\
+	__stringify(CONCATENATE(_name, _data)) ":			\n"	\
+	"	.incbin " __stringify(_path) "				\n"	\
+	"	.size " __stringify(CONCATENATE(_name, _data)) ", "		\
+			". - " __stringify(CONCATENATE(_name, _data)) "	\n"	\
+	"	.global " __stringify(CONCATENATE(_name, _end)) "	\n"	\
+	__stringify(CONCATENATE(_name, _end)) ":			\n"	\
+	"	.popsection						\n"	\
+	);									\
+										\
+	extern const char CONCATENATE(_name, _data)[];				\
+	extern const char CONCATENATE(_name, _end)[];				\
+										\
+	static const struct kunit_uapi_blob _name = {				\
+		.path	= _path,						\
+		.data	= CONCATENATE(_name, _data),				\
+		.end	= CONCATENATE(_name, _end),				\
+	}									\
+
+#else /* !CONFIG_KUNIT_UAPI */
+
+/* Unresolved external reference, to be optimized away */
+#define KUNIT_UAPI_EMBED_BLOB(_name, _path)					\
+	extern const struct kunit_uapi_blob _name
+
+#endif /* CONFIG_KUNIT_UAPI */
+
+/**
+ * kunit_uapi_run_kselftest() - Run a userspace kselftest as part of kunit
+ * @test: The test context object.
+ * @executable: kselftest executable to run
+ *
+ * Runs the kselftest and forwards its TAP output and exit status to kunit.
+ */
+void kunit_uapi_run_kselftest(struct kunit *test, const struct kunit_uapi_blob *executable);
+
+#endif /* _KUNIT_UAPI_H */
diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig
index 498cc51e493d..f3dc9fac811a 100644
--- a/lib/kunit/Kconfig
+++ b/lib/kunit/Kconfig
@@ -141,4 +141,20 @@ config KUNIT_UML_PCI
 
 	  If unsure, say N.
 
+config KUNIT_UAPI
+	tristate "KUnit UAPI testing framework"
+	depends on KUNIT
+	depends on ARCH_HAS_NOLIBC
+	depends on !STATIC_USERMODEHELPER
+	depends on !LTO_CLANG # https://github.com/llvm/llvm-project/issues/112920
+	select HEADERS_INSTALL
+	select DEVTMPFS
+	default KUNIT
+	help
+	  Enables support for building and running userspace selftests as part of kunit.
+	  These tests should be statically linked and use kselftest.h or kselftest_harness.h
+	  for status reporting.
+
+	  In most cases this should be left as its default.
+
 endif # KUNIT
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 656f1fa35abc..6059621a2d32 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -12,6 +12,8 @@ kunit-objs +=				test.o \
 					device.o \
 					platform.o
 
+obj-$(CONFIG_KUNIT_UAPI) +=		kunit-uapi.o
+
 ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
 kunit-objs +=				debugfs.o
 endif
diff --git a/lib/kunit/kunit-uapi.c b/lib/kunit/kunit-uapi.c
new file mode 100644
index 000000000000..485b79fd193d
--- /dev/null
+++ b/lib/kunit/kunit-uapi.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit Userspace testing API.
+ *
+ * Copyright (C) 2026, Linutronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ */
+
+#include <linux/binfmts.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fs_struct.h>
+#include <linux/pid.h>
+#include <linux/pipe_fs_i.h>
+#include <linux/sched/task.h>
+#include <linux/seq_buf.h>
+#include <linux/types.h>
+#include <linux/umh.h>
+
+#include <kunit/test-bug.h>
+#include <kunit/test.h>
+#include <kunit/uapi.h>
+
+enum {
+	KSFT_PASS	= 0,
+	KSFT_FAIL	= 1,
+	KSFT_XFAIL	= 2,
+	KSFT_XPASS	= 3,
+	KSFT_SKIP	= 4,
+};
+
+static struct vfsmount *kunit_uapi_mount_fs(const char *name)
+{
+	struct file_system_type *type;
+
+	type = get_fs_type(name);
+	if (!type)
+		return ERR_PTR(-ENODEV);
+
+	return kern_mount(type);
+}
+
+static int kunit_uapi_write_file(struct vfsmount *mnt, const char *name, mode_t mode,
+				 const u8 *data, size_t size)
+{
+	struct file *file;
+	ssize_t written;
+
+	file = file_open_root_mnt(mnt, name, O_CREAT | O_WRONLY, mode);
+	if (IS_ERR(file))
+		return PTR_ERR(file);
+
+	written = kernel_write(file, data, size, NULL);
+	filp_close(file, NULL);
+	if (written != size) {
+		if (written >= 0)
+			return -ENOMEM;
+		return written;
+	}
+
+	return 0;
+}
+
+static const char *kunit_uapi_executable_target(const struct kunit_uapi_blob *executable)
+{
+	return kbasename(executable->path);
+}
+
+static int kunit_uapi_write_executable(struct vfsmount *mnt,
+				       const struct kunit_uapi_blob *executable)
+{
+	return kunit_uapi_write_file(mnt, kunit_uapi_executable_target(executable), 0755,
+				     executable->data, executable->end - executable->data);
+}
+
+struct kunit_uapi_usermodehelper_ctx {
+	struct vfsmount *mnt;
+	struct kunit *test;
+};
+
+static int kunit_uapi_get_cwd(struct vfsmount *mnt)
+{
+	CLASS(get_unused_fd, fd)(O_RDONLY);
+	if (fd < 0)
+		return fd;
+
+	struct file *file __free(fput) = file_open_root_mnt(mnt, "/", O_DIRECTORY, 0);
+	if (IS_ERR(file))
+		return PTR_ERR(file);
+
+	fd_install(fd, no_free_ptr(file));
+
+	return take_fd(fd);
+}
+
+static int kunit_uapi_usermodehelper_init(struct subprocess_info *info, struct cred *new)
+{
+	struct kunit_uapi_usermodehelper_ctx *ctx = info->data;
+	int dirfd;
+
+	dirfd = kunit_uapi_get_cwd(ctx->mnt);
+	if (dirfd < 0)
+		return dirfd;
+
+	kernel_sigaction(SIGKILL, SIG_DFL);
+	kernel_sigaction(SIGABRT, SIG_DFL);
+
+	current->kunit_test = ctx->test;
+
+	info->dirfd = dirfd;
+
+	return 0;
+}
+
+static int kunit_uapi_run_executable_in_mount(struct kunit *test,
+					      const struct kunit_uapi_blob *executable,
+					      struct vfsmount *mnt)
+{
+	const char *executable_target = kunit_uapi_executable_target(executable);
+	struct kunit_uapi_usermodehelper_ctx ctx = {
+		.test	= test,
+		.mnt	= mnt,
+	};
+	struct subprocess_info *info;
+	const char *const argv[] = {
+		executable_target,
+		NULL
+	};
+
+	info = call_usermodehelper_setup(AT_FDCWD, executable_target, (char **)argv, NULL,
+					 GFP_KERNEL, kunit_uapi_usermodehelper_init, NULL, &ctx);
+	if (!info)
+		return -ENOMEM;
+
+	/* Flush delayed fput so exec can open the file read-only */
+	flush_delayed_fput();
+
+	return call_usermodehelper_exec(info, UMH_WAIT_PROC);
+}
+
+static int kunit_uapi_run_executable(struct kunit *test, const struct kunit_uapi_blob *executable)
+{
+	int err;
+
+	struct vfsmount *mnt __free(kern_unmount) = kunit_uapi_mount_fs("ramfs");
+	if (IS_ERR(mnt))
+		return PTR_ERR(mnt);
+
+	err = kunit_uapi_write_executable(mnt, executable);
+	if (err)
+		return err;
+
+	err = kunit_uapi_run_executable_in_mount(test, executable, mnt);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+void kunit_uapi_run_kselftest(struct kunit *test, const struct kunit_uapi_blob *executable)
+{
+	u8 exit_code, exit_signal;
+	int err;
+
+	err = kunit_uapi_run_executable(test, executable);
+	if (err < 0)
+		KUNIT_FAIL_AND_ABORT(test, "Could not run test executable: %pe\n", ERR_PTR(err));
+
+	exit_code = err >> 8;
+	exit_signal = err & 0xff;
+
+	if (exit_signal)
+		KUNIT_FAIL_AND_ABORT(test, "kselftest exited with signal: %d\n", exit_signal);
+	else if (exit_code == KSFT_PASS)
+		; /* Noop */
+	else if (exit_code == KSFT_FAIL)
+		KUNIT_FAIL_AND_ABORT(test, "kselftest exited with code KSFT_FAIL\n");
+	else if (exit_code == KSFT_XPASS)
+		KUNIT_FAIL_AND_ABORT(test, "kselftest exited with code KSFT_XPASS\n");
+	else if (exit_code == KSFT_XFAIL)
+		; /* Noop */
+	else if (exit_code == KSFT_SKIP)
+		kunit_mark_skipped(test, "kselftest exited with code KSFT_SKIP\n");
+	else
+		KUNIT_FAIL_AND_ABORT(test, "kselftest exited with unknown exit code: %d\n",
+				     exit_code);
+}
+EXPORT_SYMBOL_GPL(kunit_uapi_run_kselftest);
+
+MODULE_DESCRIPTION("KUnit UAPI testing framework");
+MODULE_AUTHOR("Thomas Weißschuh <thomas.weissschuh@linutronix.de");
+MODULE_LICENSE("GPL");

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 08/11] kunit: uapi: Forward test executable output to KUnit log
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (6 preceding siblings ...)
  2026-05-04  9:33 ` [PATCH v6 07/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 09/11] kunit: uapi: Add example for UAPI tests Thomas Weißschuh
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

The output of the test executable should be grouped together with the
regular KUnit output and also be available in debugfs.
Install a custom miscdevice as stdout and stderr which forwards the
written data to the KUnit log.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
 lib/kunit/kunit-uapi.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 154 insertions(+), 1 deletion(-)

diff --git a/lib/kunit/kunit-uapi.c b/lib/kunit/kunit-uapi.c
index 485b79fd193d..7f0309a827a5 100644
--- a/lib/kunit/kunit-uapi.c
+++ b/lib/kunit/kunit-uapi.c
@@ -11,6 +11,7 @@
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/fs_struct.h>
+#include <linux/miscdevice.h>
 #include <linux/pid.h>
 #include <linux/pipe_fs_i.h>
 #include <linux/sched/task.h>
@@ -22,6 +23,8 @@
 #include <kunit/test.h>
 #include <kunit/uapi.h>
 
+#define KUNIT_LOG_DEVICE "kunit-log"
+
 enum {
 	KSFT_PASS	= 0,
 	KSFT_FAIL	= 1,
@@ -94,10 +97,48 @@ static int kunit_uapi_get_cwd(struct vfsmount *mnt)
 	return take_fd(fd);
 }
 
+static int kunit_uapi_open_standard_streams(void)
+{
+	struct vfsmount *devtmpfs __free(kern_unmount) = kunit_uapi_mount_fs("devtmpfs");
+	if (IS_ERR(devtmpfs))
+		return PTR_ERR(devtmpfs);
+
+	CLASS(get_unused_fd, stdin_fd)(O_RDONLY);
+	if (stdin_fd < 0)
+		return stdin_fd;
+
+	CLASS(get_unused_fd, stdout_fd)(O_WRONLY);
+	if (stdout_fd < 0)
+		return stdout_fd;
+
+	CLASS(get_unused_fd, stderr_fd)(O_WRONLY);
+	if (stderr_fd < 0)
+		return stderr_fd;
+
+	struct file *logfile __free(fput) = file_open_root_mnt(devtmpfs, KUNIT_LOG_DEVICE,
+							       O_RDWR, 0);
+	if (IS_ERR(logfile))
+		return PTR_ERR(logfile);
+
+	fd_install(stdin_fd, no_free_ptr(logfile));
+	fd_install(stdout_fd, fget(stdin_fd));
+	fd_install(stderr_fd, fget(stdin_fd));
+
+	take_fd(stdin_fd);
+	take_fd(stdout_fd);
+	take_fd(stderr_fd);
+
+	return 0;
+}
+
 static int kunit_uapi_usermodehelper_init(struct subprocess_info *info, struct cred *new)
 {
 	struct kunit_uapi_usermodehelper_ctx *ctx = info->data;
-	int dirfd;
+	int ret, dirfd;
+
+	ret = kunit_uapi_open_standard_streams();
+	if (ret)
+		return ret;
 
 	dirfd = kunit_uapi_get_cwd(ctx->mnt);
 	if (dirfd < 0)
@@ -188,6 +229,118 @@ void kunit_uapi_run_kselftest(struct kunit *test, const struct kunit_uapi_blob *
 }
 EXPORT_SYMBOL_GPL(kunit_uapi_run_kselftest);
 
+struct kunit_uapi_log_private {
+	struct mutex mutex;
+	struct seq_buf buf;
+	char data[4096];
+};
+
+static int kunit_uapi_log_open(struct inode *ino, struct file *file)
+{
+	struct kunit_uapi_log_private *priv;
+
+	priv = kmalloc_obj(*priv);
+	if (!priv)
+		return -ENOMEM;
+
+	mutex_init(&priv->mutex);
+	seq_buf_init(&priv->buf, priv->data, sizeof(priv->data));
+
+	file->private_data = priv;
+
+	return 0;
+}
+
+static void kunit_uapi_log_str(struct kunit *test, const char *str, size_t len)
+{
+	kunit_log(KERN_INFO, test, KUNIT_SUBSUBTEST_INDENT "%.*s", (int)len, str);
+}
+
+static void kunit_uapi_print_buf_to_log(struct kunit *test, struct seq_buf *s)
+{
+	const char *start, *lf;
+
+	if (s->size == 0 || s->len == 0)
+		return;
+
+	start = seq_buf_str(s);
+	while ((lf = strchr(start, '\n'))) {
+		kunit_uapi_log_str(test, start, lf - start + 1);
+		start = ++lf;
+	}
+
+	/* Remove printed data from buffer */
+	memmove(s->buffer, start, start - s->buffer);
+	s->len -= start - s->buffer;
+}
+
+static ssize_t kunit_uapi_log_write(struct file *file, const char __user *ubuf, size_t count,
+				    loff_t *off)
+{
+	struct kunit_uapi_log_private *priv = file->private_data;
+	struct seq_buf *buf = &priv->buf;
+	struct kunit *test;
+
+	test = kunit_get_current_test();
+	if (!test)
+		return -ENODEV;
+
+	guard(mutex)(&priv->mutex);
+
+	if (seq_buf_has_overflowed(buf))
+		return -E2BIG;
+
+	if (buf->size < buf->len + count) {
+		seq_buf_set_overflow(buf);
+		kunit_warn(test, "KUnit UAPI line buffer has overflowed\n");
+		return -E2BIG;
+	}
+
+	if (copy_from_user(buf->buffer + buf->len, ubuf, count))
+		return -EFAULT;
+
+	buf->len += count;
+
+	kunit_uapi_print_buf_to_log(test, &priv->buf);
+
+	return count;
+}
+
+static int kunit_uapi_log_release(struct inode *ino, struct file *file)
+{
+	struct kunit_uapi_log_private *priv = file->private_data;
+	struct kunit *test;
+
+	mutex_destroy(&priv->mutex);
+
+	test = kunit_get_current_test();
+	if (!test) {
+		kfree(priv);
+		return -ENODEV;
+	}
+
+	/* Flush last partial line */
+	kunit_uapi_log_str(test, priv->buf.buffer, priv->buf.len);
+	kunit_uapi_log_str(test, "\n", 1);
+
+	kfree(priv);
+	return 0;
+}
+
+static const struct file_operations kunit_uapi_log_fops = {
+	.owner		= THIS_MODULE,
+	.open		= kunit_uapi_log_open,
+	.release	= kunit_uapi_log_release,
+	.write		= kunit_uapi_log_write,
+};
+
+static struct miscdevice kunit_uapi_log = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= KUNIT_LOG_DEVICE,
+	.fops	= &kunit_uapi_log_fops,
+};
+module_misc_device(kunit_uapi_log);
+
 MODULE_DESCRIPTION("KUnit UAPI testing framework");
 MODULE_AUTHOR("Thomas Weißschuh <thomas.weissschuh@linutronix.de");
 MODULE_LICENSE("GPL");

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 09/11] kunit: uapi: Add example for UAPI tests
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (7 preceding siblings ...)
  2026-05-04  9:33 ` [PATCH v6 08/11] kunit: uapi: Forward test executable output to KUnit log Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 10/11] kunit: uapi: Introduce preinit executable Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 11/11] kunit: uapi: Validate usability of /proc Thomas Weißschuh
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

Extend the example to show how to run a userspace executable.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: David Gow <davidgow@google.com>
---
 MAINTAINERS                    |  1 +
 lib/kunit/Makefile             | 10 ++++++++++
 lib/kunit/kunit-example-test.c | 15 +++++++++++++++
 lib/kunit/kunit-example-uapi.c | 22 ++++++++++++++++++++++
 4 files changed, 48 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e29ca56f7334..b7358d89df70 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14399,6 +14399,7 @@ KUNIT UAPI TESTING FRAMEWORK (in addition to KERNEL UNIT TESTING FRAMEWORK)
 M:	Thomas Weißschuh <thomas.weissschuh@linutronix.de>
 S:	Maintained
 F:	include/kunit/uapi.h
+F:	lib/kunit/kunit-example-uapi.c
 F:	lib/kunit/kunit-uapi.c
 
 KVM PARAVIRT (KVM/paravirt)
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 6059621a2d32..2434470e9985 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -1,3 +1,5 @@
+include $(srctree)/init/Makefile.nolibc
+
 obj-$(CONFIG_KUNIT) +=			kunit.o
 
 kunit-objs +=				test.o \
@@ -31,3 +33,11 @@ obj-$(CONFIG_KUNIT_TEST) +=		assert_test.o
 endif
 
 obj-$(CONFIG_KUNIT_EXAMPLE_TEST) +=	kunit-example-test.o
+
+userprogs +=				kunit-example-uapi
+kunit-example-uapi-userccflags :=	-static $(NOLIBC_USERCFLAGS)
+
+ifdef CONFIG_KUNIT_UAPI
+CFLAGS_kunit-example-test.o :=		-Wa,-I$(obj)
+$(obj)/kunit-example-test.o: $(obj)/kunit-example-uapi
+endif
diff --git a/lib/kunit/kunit-example-test.c b/lib/kunit/kunit-example-test.c
index 0bae7b7ca0b0..febabc995405 100644
--- a/lib/kunit/kunit-example-test.c
+++ b/lib/kunit/kunit-example-test.c
@@ -8,6 +8,7 @@
 
 #include <kunit/test.h>
 #include <kunit/static_stub.h>
+#include <kunit/uapi.h>
 
 /*
  * This is the most fundamental element of KUnit, the test case. A test case
@@ -489,6 +490,19 @@ static void example_params_test_with_init_dynamic_arr(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, param_val - param_val, 0);
 }
 
+/*
+ * This test shows the usage of UAPI tests.
+ */
+static void example_uapi_test(struct kunit *test)
+{
+	KUNIT_UAPI_EMBED_BLOB(kunit_example_uapi, "kunit-example-uapi");
+
+	if (IS_ENABLED(CONFIG_KUNIT_UAPI))
+		kunit_uapi_run_kselftest(test, &kunit_example_uapi);
+	else
+		kunit_skip(test, "CONFIG_KUNIT_UAPI is not enabled");
+}
+
 /*
  * Here we make a list of all the test cases we want to add to the test suite
  * below.
@@ -514,6 +528,7 @@ static struct kunit_case example_test_cases[] = {
 				   kunit_array_gen_params, example_param_init_dynamic_arr,
 				   example_param_exit_dynamic_arr),
 	KUNIT_CASE_SLOW(example_slow_test),
+	KUNIT_CASE(example_uapi_test),
 	{}
 };
 
diff --git a/lib/kunit/kunit-example-uapi.c b/lib/kunit/kunit-example-uapi.c
new file mode 100644
index 000000000000..5875b0d680d4
--- /dev/null
+++ b/lib/kunit/kunit-example-uapi.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit Userspace example test.
+ *
+ * Copyright (C) 2026, Linutronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ *
+ * This is *userspace* code.
+ */
+
+#include "../../tools/testing/selftests/kselftest.h"
+
+int main(void)
+{
+	ksft_print_header();
+	ksft_set_plan(4);
+	ksft_test_result_pass("userspace test 1\n");
+	ksft_test_result_pass("userspace test 2\n");
+	ksft_test_result_skip("userspace test 3: some reason\n");
+	ksft_test_result_pass("userspace test 4\n");
+	ksft_finished();
+}

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 10/11] kunit: uapi: Introduce preinit executable
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (8 preceding siblings ...)
  2026-05-04  9:33 ` [PATCH v6 09/11] kunit: uapi: Add example for UAPI tests Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  2026-05-04  9:33 ` [PATCH v6 11/11] kunit: uapi: Validate usability of /proc Thomas Weißschuh
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

UAPI selftests may expect a "normal" userspace environment.
For example the normal kernel API pseudo-filesystems should be mounted.
This could be done from kernel code but it is non-idiomatic.

Add a preinit userspace executable which performs these setup steps
before running the final test executable.
This preinit executable is only ever run from the kernel.
Give it access to autoconf.h and kconfig.h to adapt itself to the
tested kernel.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: David Gow <davidgow@google.com>
---
 MAINTAINERS              |  1 +
 lib/kunit/Makefile       |  5 ++++
 lib/kunit/kunit-uapi.c   | 11 +++++---
 lib/kunit/uapi-preinit.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index b7358d89df70..4e8cf9fa7aa9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14401,6 +14401,7 @@ S:	Maintained
 F:	include/kunit/uapi.h
 F:	lib/kunit/kunit-example-uapi.c
 F:	lib/kunit/kunit-uapi.c
+F:	lib/kunit/uapi-preinit.c
 
 KVM PARAVIRT (KVM/paravirt)
 M:	Paolo Bonzini <pbonzini@redhat.com>
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 2434470e9985..05991d69aa70 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -14,8 +14,13 @@ kunit-objs +=				test.o \
 					device.o \
 					platform.o
 
+userprogs +=				uapi-preinit
+uapi-preinit-userccflags +=		-static $(NOLIBC_USERCFLAGS)
 obj-$(CONFIG_KUNIT_UAPI) +=		kunit-uapi.o
 
+CFLAGS_kunit-uapi.o :=			-Wa,-I$(obj)
+$(obj)/kunit-uapi.o: $(obj)/uapi-preinit
+
 ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
 kunit-objs +=				debugfs.o
 endif
diff --git a/lib/kunit/kunit-uapi.c b/lib/kunit/kunit-uapi.c
index 7f0309a827a5..702d26878ccd 100644
--- a/lib/kunit/kunit-uapi.c
+++ b/lib/kunit/kunit-uapi.c
@@ -33,6 +33,8 @@ enum {
 	KSFT_SKIP	= 4,
 };
 
+KUNIT_UAPI_EMBED_BLOB(kunit_uapi_preinit, "uapi-preinit");
+
 static struct vfsmount *kunit_uapi_mount_fs(const char *name)
 {
 	struct file_system_type *type;
@@ -158,18 +160,17 @@ static int kunit_uapi_run_executable_in_mount(struct kunit *test,
 					      const struct kunit_uapi_blob *executable,
 					      struct vfsmount *mnt)
 {
-	const char *executable_target = kunit_uapi_executable_target(executable);
 	struct kunit_uapi_usermodehelper_ctx ctx = {
 		.test	= test,
 		.mnt	= mnt,
 	};
 	struct subprocess_info *info;
 	const char *const argv[] = {
-		executable_target,
+		kunit_uapi_executable_target(executable),
 		NULL
 	};
 
-	info = call_usermodehelper_setup(AT_FDCWD, executable_target, (char **)argv, NULL,
+	info = call_usermodehelper_setup(AT_FDCWD, kunit_uapi_preinit.path, (char **)argv, NULL,
 					 GFP_KERNEL, kunit_uapi_usermodehelper_init, NULL, &ctx);
 	if (!info)
 		return -ENOMEM;
@@ -192,6 +193,10 @@ static int kunit_uapi_run_executable(struct kunit *test, const struct kunit_uapi
 	if (err)
 		return err;
 
+	err = kunit_uapi_write_executable(mnt, &kunit_uapi_preinit);
+	if (err)
+		return err;
+
 	err = kunit_uapi_run_executable_in_mount(test, executable, mnt);
 	if (err)
 		return err;
diff --git a/lib/kunit/uapi-preinit.c b/lib/kunit/uapi-preinit.c
new file mode 100644
index 000000000000..686737ea3c76
--- /dev/null
+++ b/lib/kunit/uapi-preinit.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit Userspace environment setup.
+ *
+ * Copyright (C) 2026, Linutronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ *
+ * This is *userspace* code.
+ */
+
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include "../../tools/testing/selftests/kselftest.h"
+
+#define KUNIT_UAPI_CHDIR_FD 3
+
+static int setup_api_mount(const char *target, const char *fstype)
+{
+	int ret;
+
+	ret = mkdir(target, 0755);
+	if (ret && errno != EEXIST)
+		return -errno;
+
+	ret = mount("none", target, fstype, 0, NULL);
+	if (ret && errno != EBUSY)
+		return -errno;
+
+	return 0;
+}
+
+static void exit_failure(const char *stage, int err)
+{
+	/* If preinit fails synthesize a failed test report. */
+	ksft_print_header();
+	ksft_set_plan(1);
+	ksft_test_result_fail("Failed during test setup: %s: %s\n", stage, strerror(-err));
+	ksft_finished();
+}
+
+int main(int argc, char **argv, char **envp)
+{
+	int ret;
+
+	ret = fchdir(KUNIT_UAPI_CHDIR_FD);
+	close(KUNIT_UAPI_CHDIR_FD);
+	if (ret)
+		exit_failure("fchdir", ret);
+
+	ret = setup_api_mount("/proc", "proc");
+	if (ret)
+		exit_failure("mount /proc", ret);
+
+	ret = setup_api_mount("/sys", "sysfs");
+	if (ret)
+		exit_failure("mount /sys", ret);
+
+	ret = setup_api_mount("/dev", "devtmpfs");
+	if (ret)
+		exit_failure("mount /dev", ret);
+
+	ret = execve(argv[0], argv, envp);
+	if (ret)
+		exit_failure("execve", ret);
+
+	return 0;
+}

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 11/11] kunit: uapi: Validate usability of /proc
  2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
                   ` (9 preceding siblings ...)
  2026-05-04  9:33 ` [PATCH v6 10/11] kunit: uapi: Introduce preinit executable Thomas Weißschuh
@ 2026-05-04  9:33 ` Thomas Weißschuh
  10 siblings, 0 replies; 12+ messages in thread
From: Thomas Weißschuh @ 2026-05-04  9:33 UTC (permalink / raw)
  To: Nathan Chancellor, Andrew Morton, Willy Tarreau,
	Thomas Weißschuh, Brendan Higgins, Shuah Khan,
	Jonathan Corbet, Nicolas Schier, Kees Cook, Alexander Viro,
	Christian Brauner, Jan Kara, Christoph Hellwig, Luis Chamberlain,
	David Gow, Rae Moar
  Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev, linux-doc,
	workflows, linux-mm, linux-fsdevel, Thomas Weißschuh,
	Christophe Leroy, Nicolas Schier

Show that the selftests are executed from a fairly "normal"
userspace context.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
 MAINTAINERS                 |  1 +
 lib/kunit/Makefile          |  9 ++++++++
 lib/kunit/kunit-test-uapi.c | 51 +++++++++++++++++++++++++++++++++++++++++++++
 lib/kunit/kunit-test.c      | 24 ++++++++++++++++++++-
 4 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4e8cf9fa7aa9..693aafe4d3f9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14400,6 +14400,7 @@ M:	Thomas Weißschuh <thomas.weissschuh@linutronix.de>
 S:	Maintained
 F:	include/kunit/uapi.h
 F:	lib/kunit/kunit-example-uapi.c
+F:	lib/kunit/kunit-test-uapi.c
 F:	lib/kunit/kunit-uapi.c
 F:	lib/kunit/uapi-preinit.c
 
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 05991d69aa70..1a4af6b66524 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -29,6 +29,15 @@ endif
 obj-$(if $(CONFIG_KUNIT),y) +=		hooks.o
 
 obj-$(CONFIG_KUNIT_TEST) +=		kunit-test.o
+
+userprogs +=				kunit-test-uapi
+kunit-test-uapi-userccflags :=		-static $(NOLIBC_USERCFLAGS)
+
+ifdef CONFIG_KUNIT_UAPI
+CFLAGS_kunit-test.o :=			-Wa,-I$(obj)
+$(obj)/kunit-test.o: $(obj)/kunit-test-uapi
+endif
+
 obj-$(CONFIG_KUNIT_TEST) +=		platform-test.o
 
 # string-stream-test compiles built-in only.
diff --git a/lib/kunit/kunit-test-uapi.c b/lib/kunit/kunit-test-uapi.c
new file mode 100644
index 000000000000..2e75e57865e3
--- /dev/null
+++ b/lib/kunit/kunit-test-uapi.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit Userspace selftest.
+ *
+ * Copyright (C) 2026, Linutronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ *
+ * This is *userspace* code.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "../../tools/testing/selftests/kselftest.h"
+
+static void test_procfs(void)
+{
+	char buf[256];
+	ssize_t r;
+	int fd;
+
+	fd = open("/proc/self/comm", O_RDONLY);
+	if (fd == -1) {
+		ksft_test_result_fail("procfs: open() failed: %s\n", strerror(errno));
+		return;
+	}
+
+	r = read(fd, buf, sizeof(buf));
+	close(fd);
+
+	if (r == -1) {
+		ksft_test_result_fail("procfs: read() failed: %s\n", strerror(errno));
+		return;
+	}
+
+	if (r != 16 || strncmp("kunit-test-uapi\n", buf, 16) != 0) {
+		ksft_test_result_fail("procfs: incorrect comm\n");
+		return;
+	}
+
+	ksft_test_result_pass("procfs\n");
+}
+
+int main(void)
+{
+	ksft_print_header();
+	ksft_set_plan(1);
+	test_procfs();
+	ksft_finished();
+}
diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c
index 126e30879dad..b62e24fb9c55 100644
--- a/lib/kunit/kunit-test.c
+++ b/lib/kunit/kunit-test.c
@@ -9,6 +9,7 @@
 #include <kunit/test.h>
 #include <kunit/test-bug.h>
 #include <kunit/static_stub.h>
+#include <kunit/uapi.h>
 
 #include <linux/device.h>
 #include <kunit/device.h>
@@ -914,10 +915,31 @@ static struct kunit_suite kunit_stub_test_suite = {
 	.test_cases = kunit_stub_test_cases,
 };
 
+static void kunit_uapi_test(struct kunit *test)
+{
+	KUNIT_UAPI_EMBED_BLOB(kunit_test_uapi, "kunit-test-uapi");
+
+	if (IS_ENABLED(CONFIG_KUNIT_UAPI))
+		kunit_uapi_run_kselftest(test, &kunit_test_uapi);
+	else
+		kunit_skip(test, "CONFIG_KUNIT_UAPI is not enabled");
+}
+
+static struct kunit_case kunit_uapi_test_cases[] = {
+	KUNIT_CASE(kunit_uapi_test),
+	{}
+};
+
+static struct kunit_suite kunit_uapi_test_suite = {
+	.name = "kunit_uapi",
+	.test_cases = kunit_uapi_test_cases,
+};
+
 kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
 		  &kunit_log_test_suite, &kunit_status_test_suite,
 		  &kunit_current_test_suite, &kunit_device_test_suite,
-		  &kunit_fault_test_suite, &kunit_stub_test_suite);
+		  &kunit_fault_test_suite, &kunit_stub_test_suite,
+		  &kunit_uapi_test_suite);
 
 MODULE_DESCRIPTION("KUnit test for core test infrastructure");
 MODULE_LICENSE("GPL v2");

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-05-04  9:33 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-04  9:33 [PATCH v6 00/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 01/11] kbuild: doc: add label for userprogs section Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 02/11] exec: add dirfd parameter to kernel_execve() Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 03/11] umh: add dirfd parameter Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 04/11] mount: add support for __free(kern_unmount) Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 05/11] init: add nolibc build support Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 06/11] kunit: qemu_configs: loongarch: Enable LSX/LSAX Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 07/11] kunit: Introduce UAPI testing framework Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 08/11] kunit: uapi: Forward test executable output to KUnit log Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 09/11] kunit: uapi: Add example for UAPI tests Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 10/11] kunit: uapi: Introduce preinit executable Thomas Weißschuh
2026-05-04  9:33 ` [PATCH v6 11/11] kunit: uapi: Validate usability of /proc Thomas Weißschuh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox