diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 0d89b666fcad12a542d3e2ffacedd26b122c5449..b1d9851f1a14ecd7fb48a20c5500058811259142 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -12,7 +12,14 @@ kunit-objs +=				test.o \
 					device.o \
 					platform.o
 
-obj-$(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
+obj-$(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..748599786aaa802982335e536ddae122f5cc2be5
--- /dev/null
+++ b/lib/kunit/uapi-preinit.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit Userspace environment setup.
+ *
+ * Copyright (C) 2025, Linuxtronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ */
+
+#ifndef NOLIBC
+#include <sys/mount.h>
+#include <sys/stat.h>
+#endif
+
+#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 9fbba13669e8e5cf349e596636f2cdc4adce4978..d43a1a1e5084ab1c7c4515e3c44fd3e819524737 100644
--- a/lib/kunit/uapi.c
+++ b/lib/kunit/uapi.c
@@ -19,6 +19,8 @@
 #include <kunit/test.h>
 #include <kunit/uapi.h>
 
+#define KUNIT_UAPI_PREINIT	"preinit"
+
 static struct vfsmount *kunit_uapi_mount_tmpfs(void)
 {
 	struct file_system_type *type;
@@ -118,7 +120,7 @@ static int kunit_uapi_user_mode_thread_init(void *data)
 	kernel_sigaction(SIGKILL, SIG_DFL);
 
 	complete(&ctx->setup_done);
-	ctx->exec_err = kernel_execve(ctx->executable, argv, NULL);
+	ctx->exec_err = kernel_execve(KUNIT_UAPI_PREINIT, argv, NULL);
 	if (!ctx->exec_err)
 		return 0;
 	do_exit(0);
@@ -213,6 +215,8 @@ static int kunit_uapi_run_executable_in_mount(struct kunit *test, const char *ex
 
 void kunit_uapi_run_executable(struct kunit *test, const struct blob *blob)
 {
+	DECLARE_BLOB(kunit_uapi_preinit);
+
 	const char *exe_name = kbasename(blob->path);
 	struct vfsmount *mnt;
 	int err;
@@ -222,8 +226,15 @@ void kunit_uapi_run_executable(struct kunit *test, const struct blob *blob)
 	if (IS_ERR(mnt))
 		return;
 
-	err = kunit_uapi_write_file(mnt, exe_name, 0700, blob->data, blob_size(blob));
-	KUNIT_EXPECT_EQ_MSG(test, 0, err, "Could not add test executable: %pe", ERR_PTR(err));
+	err = kunit_uapi_write_file(mnt, KUNIT_UAPI_PREINIT, 0755,
+				    kunit_uapi_preinit.data, blob_size(&kunit_uapi_preinit));
+	KUNIT_EXPECT_EQ_MSG(test, 0, err, "Could not add preinit executable: %pe", ERR_PTR(err));
+
+	if (!err) {
+		err = kunit_uapi_write_file(mnt, exe_name, 0755, blob->data, blob_size(blob));
+		KUNIT_EXPECT_EQ_MSG(test, 0, err, "Could not add test executable: %pe",
+				    ERR_PTR(err));
+	}
 
 	if (!err) {
 		err = kunit_uapi_run_executable_in_mount(test, exe_name, mnt);
