Commit 9132c394 authored by Kees Cook's avatar Kees Cook
Browse files

selftests/exec: Test for empty string on NULL argv



Test for the NULL argv argument producing a single empty string on exec.

Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Yang Yingliang <yangyingliang@huawei.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/lkml/20220201011637.2457646-1-keescook@chromium.org
parent dcd46d89
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir
TEST_FILES := Makefile

TEST_GEN_PROGS += recursion-depth
TEST_GEN_PROGS += null-argv

EXTRA_CLEAN := $(OUTPUT)/subdir.moved $(OUTPUT)/execveat.moved $(OUTPUT)/xxxxx*	\
	       $(OUTPUT)/S_I*.test
+78 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Test that empty argvs are swapped out for a single empty string. */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "../kselftest.h"

#define FORK(exec)				\
do {						\
	pid = fork();				\
	if (pid == 0) {				\
		/* Child */			\
		exec; /* Some kind of exec */	\
		perror("# " #exec);		\
		return 1;			\
	}					\
	check_result(pid, #exec);		\
} while (0)

void check_result(pid_t pid, const char *msg)
{
	int wstatus;

	if (pid == (pid_t)-1) {
		perror("# fork");
		ksft_test_result_fail("fork failed: %s\n", msg);
		return;
	}
	if (waitpid(pid, &wstatus, 0) < 0) {
		perror("# waitpid");
		ksft_test_result_fail("waitpid failed: %s\n", msg);
		return;
	}
	if (!WIFEXITED(wstatus)) {
		ksft_test_result_fail("child did not exit: %s\n", msg);
		return;
	}
	if (WEXITSTATUS(wstatus) != 0) {
		ksft_test_result_fail("non-zero exit: %s\n", msg);
		return;
	}
	ksft_test_result_pass("%s\n", msg);
}

int main(int argc, char *argv[], char *envp[])
{
	pid_t pid;
	static char * const args[] = { NULL };
	static char * const str[] = { "", NULL };

	/* argc counting checks */
	if (argc < 1) {
		fprintf(stderr, "# FAIL: saw argc == 0 (old kernel?)\n");
		return 1;
	}
	if (argc != 1) {
		fprintf(stderr, "# FAIL: unknown argc (%d)\n", argc);
		return 1;
	}
	if (argv[0][0] == '\0') {
		/* Good, we found a NULL terminated string at argv[0]! */
		return 0;
	}

	/* Test runner. */
	ksft_print_header();
	ksft_set_plan(5);

	FORK(execve(argv[0], str, NULL));
	FORK(execve(argv[0], NULL, NULL));
	FORK(execve(argv[0], NULL, envp));
	FORK(execve(argv[0], args, NULL));
	FORK(execve(argv[0], args, envp));

	ksft_exit(ksft_cnt.ksft_pass == ksft_plan);
}