[LTP] [PATCH] syscalls/execve06: Add test for argv[0] = NULL
Cyril Hrubis
chrubis@suse.cz
Mon Jun 13 14:51:53 CEST 2022
Adds a test that kernel sets argv[0] to a dummy empty string if NULL was
passed to the execve() syscall. This was introduced in commit:
commit dcd46d897adb70d63e025f175a00a89797d31a43
Author: Kees Cook <keescook@chromium.org>
Date: Mon Jan 31 16:09:47 2022 -0800
exec: Force single empty string when argv is empty
in order to fix all potential CVEs where userspace programs attempt to
blindly process the argv[] list starting at argv[1]. There was at least
one example of this caught in the wild CVE-2021-4034 in polkit but there
are likely more.
Fixes: #911
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
testcases/kernel/syscalls/execve/.gitignore | 2 +
testcases/kernel/syscalls/execve/execve06.c | 49 +++++++++++++++++++
.../kernel/syscalls/execve/execve06_child.c | 27 ++++++++++
3 files changed, 78 insertions(+)
create mode 100644 testcases/kernel/syscalls/execve/execve06.c
create mode 100644 testcases/kernel/syscalls/execve/execve06_child.c
diff --git a/testcases/kernel/syscalls/execve/.gitignore b/testcases/kernel/syscalls/execve/.gitignore
index 50cabbb83..fee81faf7 100644
--- a/testcases/kernel/syscalls/execve/.gitignore
+++ b/testcases/kernel/syscalls/execve/.gitignore
@@ -4,4 +4,6 @@
/execve03
/execve04
/execve05
+/execve06
+/execve06_child
/execve_child
diff --git a/testcases/kernel/syscalls/execve/execve06.c b/testcases/kernel/syscalls/execve/execve06.c
new file mode 100644
index 000000000..b3280cf76
--- /dev/null
+++ b/testcases/kernel/syscalls/execve/execve06.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test that kernel adds dummy argv[0] if empty argument list was passed to
+ * execve(). This fixes at least one CVE where userspace programs start to
+ * process argument list blindly from argv[1] such as polkit pkexec
+ * CVE-2021-4034.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "tst_test.h"
+
+static void verify_execve(void)
+{
+ pid_t pid;
+ char path[512];
+ char ipc_env_var[1024];
+
+ sprintf(ipc_env_var, IPC_ENV_VAR "=%s", getenv(IPC_ENV_VAR));
+
+ char *const envp[] = {ipc_env_var, NULL};
+ char *const argv[] = {NULL};
+
+ if (tst_get_path("execve06_child", path, sizeof(path)))
+ tst_brk(TCONF, "Couldn't find execve06_child in $PATH");
+
+ pid = SAFE_FORK();
+ if (pid == 0) {
+ execve(path, argv, envp);
+ tst_brk(TFAIL | TERRNO, "Failed to execute execl01_child");
+ }
+}
+
+static struct tst_test test = {
+ .forks_child = 1,
+ .child_needs_reinit = 1,
+ .test_all = verify_execve,
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "dcd46d897adb"},
+ {"CVE", "2021-4034"},
+ {}
+ }
+};
diff --git a/testcases/kernel/syscalls/execve/execve06_child.c b/testcases/kernel/syscalls/execve/execve06_child.c
new file mode 100644
index 000000000..17280d58a
--- /dev/null
+++ b/testcases/kernel/syscalls/execve/execve06_child.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2022 Cyril Hrubis chrubis@suse.cz
+ */
+
+#define TST_NO_DEFAULT_MAIN
+#include <stdlib.h>
+#include "tst_test.h"
+
+int main(int argc, char *argv[])
+{
+ tst_reinit();
+
+ if (argc != 1) {
+ tst_res(TFAIL, "argc is %d, expected 1", argc);
+ return 0;
+ }
+
+ if (!argv[0]) {
+ tst_res(TFAIL, "argv[0] == NULL");
+ return 0;
+ }
+
+ tst_res(TPASS, "argv[0] was filled in by kernel");
+
+ return 0;
+}
--
2.35.1
More information about the ltp
mailing list