[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