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