Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/lkml/20220201011637.2457646-1-keescook@chromium.org

+79
+1
tools/testing/selftests/exec/Makefile
··· 10 10 TEST_FILES := Makefile 11 11 12 12 TEST_GEN_PROGS += recursion-depth 13 + TEST_GEN_PROGS += null-argv 13 14 14 15 EXTRA_CLEAN := $(OUTPUT)/subdir.moved $(OUTPUT)/execveat.moved $(OUTPUT)/xxxxx* \ 15 16 $(OUTPUT)/S_I*.test
+78
tools/testing/selftests/exec/null-argv.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Test that empty argvs are swapped out for a single empty string. */ 3 + #include <stdio.h> 4 + #include <unistd.h> 5 + #include <sys/types.h> 6 + #include <sys/wait.h> 7 + 8 + #include "../kselftest.h" 9 + 10 + #define FORK(exec) \ 11 + do { \ 12 + pid = fork(); \ 13 + if (pid == 0) { \ 14 + /* Child */ \ 15 + exec; /* Some kind of exec */ \ 16 + perror("# " #exec); \ 17 + return 1; \ 18 + } \ 19 + check_result(pid, #exec); \ 20 + } while (0) 21 + 22 + void check_result(pid_t pid, const char *msg) 23 + { 24 + int wstatus; 25 + 26 + if (pid == (pid_t)-1) { 27 + perror("# fork"); 28 + ksft_test_result_fail("fork failed: %s\n", msg); 29 + return; 30 + } 31 + if (waitpid(pid, &wstatus, 0) < 0) { 32 + perror("# waitpid"); 33 + ksft_test_result_fail("waitpid failed: %s\n", msg); 34 + return; 35 + } 36 + if (!WIFEXITED(wstatus)) { 37 + ksft_test_result_fail("child did not exit: %s\n", msg); 38 + return; 39 + } 40 + if (WEXITSTATUS(wstatus) != 0) { 41 + ksft_test_result_fail("non-zero exit: %s\n", msg); 42 + return; 43 + } 44 + ksft_test_result_pass("%s\n", msg); 45 + } 46 + 47 + int main(int argc, char *argv[], char *envp[]) 48 + { 49 + pid_t pid; 50 + static char * const args[] = { NULL }; 51 + static char * const str[] = { "", NULL }; 52 + 53 + /* argc counting checks */ 54 + if (argc < 1) { 55 + fprintf(stderr, "# FAIL: saw argc == 0 (old kernel?)\n"); 56 + return 1; 57 + } 58 + if (argc != 1) { 59 + fprintf(stderr, "# FAIL: unknown argc (%d)\n", argc); 60 + return 1; 61 + } 62 + if (argv[0][0] == '\0') { 63 + /* Good, we found a NULL terminated string at argv[0]! */ 64 + return 0; 65 + } 66 + 67 + /* Test runner. */ 68 + ksft_print_header(); 69 + ksft_set_plan(5); 70 + 71 + FORK(execve(argv[0], str, NULL)); 72 + FORK(execve(argv[0], NULL, NULL)); 73 + FORK(execve(argv[0], NULL, envp)); 74 + FORK(execve(argv[0], args, NULL)); 75 + FORK(execve(argv[0], args, envp)); 76 + 77 + ksft_exit(ksft_cnt.ksft_pass == ksft_plan); 78 + }