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
87