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

selftests/ptrace: add test cases for dead-locks

This adds test cases for ptrace deadlocks.

Additionally fixes a compile problem in get_syscall_info.c,
observed with gcc-4.8.4:

get_syscall_info.c: In function 'get_syscall_info':
get_syscall_info.c:93:3: error: 'for' loop initial declarations are only
allowed in C99 mode
for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) {
^
get_syscall_info.c:93:3: note: use option -std=c99 or -std=gnu99 to compile
your code

Signed-off-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

authored by

Bernd Edlinger and committed by
Eric W. Biederman
2de4e823 3e74fabd

+88 -2
+2 -2
tools/testing/selftests/ptrace/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 - CFLAGS += -iquote../../../../include/uapi -Wall 2 + CFLAGS += -std=c99 -pthread -iquote../../../../include/uapi -Wall 3 3 4 - TEST_GEN_PROGS := get_syscall_info peeksiginfo 4 + TEST_GEN_PROGS := get_syscall_info peeksiginfo vmaccess 5 5 6 6 include ../lib.mk
+86
tools/testing/selftests/ptrace/vmaccess.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (c) 2020 Bernd Edlinger <bernd.edlinger@hotmail.de> 4 + * All rights reserved. 5 + * 6 + * Check whether /proc/$pid/mem can be accessed without causing deadlocks 7 + * when de_thread is blocked with ->cred_guard_mutex held. 8 + */ 9 + 10 + #include "../kselftest_harness.h" 11 + #include <stdio.h> 12 + #include <fcntl.h> 13 + #include <pthread.h> 14 + #include <signal.h> 15 + #include <unistd.h> 16 + #include <sys/ptrace.h> 17 + 18 + static void *thread(void *arg) 19 + { 20 + ptrace(PTRACE_TRACEME, 0, 0L, 0L); 21 + return NULL; 22 + } 23 + 24 + TEST(vmaccess) 25 + { 26 + int f, pid = fork(); 27 + char mm[64]; 28 + 29 + if (!pid) { 30 + pthread_t pt; 31 + 32 + pthread_create(&pt, NULL, thread, NULL); 33 + pthread_join(pt, NULL); 34 + execlp("true", "true", NULL); 35 + } 36 + 37 + sleep(1); 38 + sprintf(mm, "/proc/%d/mem", pid); 39 + f = open(mm, O_RDONLY); 40 + ASSERT_GE(f, 0); 41 + close(f); 42 + f = kill(pid, SIGCONT); 43 + ASSERT_EQ(f, 0); 44 + } 45 + 46 + TEST(attach) 47 + { 48 + int s, k, pid = fork(); 49 + 50 + if (!pid) { 51 + pthread_t pt; 52 + 53 + pthread_create(&pt, NULL, thread, NULL); 54 + pthread_join(pt, NULL); 55 + execlp("sleep", "sleep", "2", NULL); 56 + } 57 + 58 + sleep(1); 59 + k = ptrace(PTRACE_ATTACH, pid, 0L, 0L); 60 + ASSERT_EQ(errno, EAGAIN); 61 + ASSERT_EQ(k, -1); 62 + k = waitpid(-1, &s, WNOHANG); 63 + ASSERT_NE(k, -1); 64 + ASSERT_NE(k, 0); 65 + ASSERT_NE(k, pid); 66 + ASSERT_EQ(WIFEXITED(s), 1); 67 + ASSERT_EQ(WEXITSTATUS(s), 0); 68 + sleep(1); 69 + k = ptrace(PTRACE_ATTACH, pid, 0L, 0L); 70 + ASSERT_EQ(k, 0); 71 + k = waitpid(-1, &s, 0); 72 + ASSERT_EQ(k, pid); 73 + ASSERT_EQ(WIFSTOPPED(s), 1); 74 + ASSERT_EQ(WSTOPSIG(s), SIGSTOP); 75 + k = ptrace(PTRACE_DETACH, pid, 0L, 0L); 76 + ASSERT_EQ(k, 0); 77 + k = waitpid(-1, &s, 0); 78 + ASSERT_EQ(k, pid); 79 + ASSERT_EQ(WIFEXITED(s), 1); 80 + ASSERT_EQ(WEXITSTATUS(s), 0); 81 + k = waitpid(-1, NULL, 0); 82 + ASSERT_EQ(k, -1); 83 + ASSERT_EQ(errno, ECHILD); 84 + } 85 + 86 + TEST_HARNESS_MAIN