On Wed, 11 Jun 2025 at 15:38, Thomas Weißschuh thomas.weissschuh@linutronix.de wrote:
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
Looks good and works here.
Reviewed-by: David Gow davidgow@google.com
(Although, personally, _I wish_ it were more idiomatic to mount things from kernelspace.)
Cheers, -- David
lib/kunit/Makefile | 9 ++++++- lib/kunit/uapi-preinit.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/kunit/uapi.c | 11 +++++++-- 3 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile index e406a31df1df834a87961663de0b7921b59481c2..19493ec320c61e2ccbb58e8b2e943e9a4ec447e2 100644 --- a/lib/kunit/Makefile +++ b/lib/kunit/Makefile @@ -12,7 +12,14 @@ kunit-objs += test.o \ device.o \ platform.o
-kunit-$(CONFIG_KUNIT_UAPI) += uapi.o +userprogs += uapi-preinit +uapi-preinit-nolibc := $(CONFIG_ARCH_HAS_NOLIBC) +uapi-preinit-userccflags += -static \
-include include/generated/autoconf.h \
-include $(srctree)/tools/include/linux/kconfig.h
+blobs += uapi-preinit.blob.o +uapi-preinit.blob-symbol := kunit_uapi_preinit +kunit-$(CONFIG_KUNIT_UAPI) += uapi.o uapi-preinit.blob.o
ifeq ($(CONFIG_KUNIT_DEBUGFS),y) kunit-objs += debugfs.o diff --git a/lib/kunit/uapi-preinit.c b/lib/kunit/uapi-preinit.c new file mode 100644 index 0000000000000000000000000000000000000000..81182039965a8c93aebb2d5d76f4113bfef277a6 --- /dev/null +++ b/lib/kunit/uapi-preinit.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- KUnit Userspace environment setup.
- Copyright (C) 2025, 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"
+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 = 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);
if (IS_ENABLED(CONFIG_DEVTMPFS)) {
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;
+} diff --git a/lib/kunit/uapi.c b/lib/kunit/uapi.c index 121146dda533b3f90aca37c20bd0e7a1d20cb3b5..bccc081a6538507724c1ef340203cfd147170dc4 100644 --- a/lib/kunit/uapi.c +++ b/lib/kunit/uapi.c @@ -139,7 +139,7 @@ static int kunit_uapi_user_mode_thread_init(void *data) kernel_sigaction(SIGABRT, SIG_DFL);
complete(&ctx->setup_done);
ctx->exec_err = kernel_execve(ctx->executable, argv, NULL);
ctx->exec_err = kernel_execve(kbasename(BLOB(kunit_uapi_preinit)->path), argv, NULL); if (!ctx->exec_err) return 0; do_exit(0);
@@ -239,6 +239,7 @@ static int kunit_uapi_run_executable_in_mount(struct kunit *test, const char *ex
static int kunit_uapi_run_executable(struct kunit *test, const struct blob *executable) {
const struct blob *preinit = BLOB(kunit_uapi_preinit); const char *exe_name = kbasename(executable->path); struct vfsmount *mnt; int err;
@@ -247,7 +248,13 @@ static int kunit_uapi_run_executable(struct kunit *test, const struct blob *exec if (IS_ERR(mnt)) return PTR_ERR(mnt);
err = kunit_uapi_write_file(mnt, exe_name, 0755, executable->data, blob_size(executable));
err = kunit_uapi_write_file(mnt, kbasename(preinit->path), 0755,
preinit->data,
blob_size(preinit));
if (!err)
err = kunit_uapi_write_file(mnt, exe_name, 0755,
executable->data, blob_size(executable)); if (!err) err = kunit_uapi_run_executable_in_mount(test, exe_name, mnt);
-- 2.49.0