1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
4 * Author: Yang Xu <[email protected]
5 *
6 * ptrace() returns -1 and sets errno to EPERM if tracer doesn't have
7 * CAP_SYS_PTRACE capability for the process. Such as nobody user.
8 */
9
10 #include <errno.h>
11 #include <signal.h>
12 #include <sys/wait.h>
13 #include <pwd.h>
14 #include <stdlib.h>
15 #include <sys/ptrace.h>
16 #include "tst_test.h"
17
18 uid_t uid;
19
verify_ptrace(void)20 static void verify_ptrace(void)
21 {
22 int child_pid[2];
23
24 child_pid[0] = SAFE_FORK();
25 if (!child_pid[0])
26 pause();
27
28 child_pid[1] = SAFE_FORK();
29 if (!child_pid[1]) {
30 SAFE_SETUID(uid);
31 TEST(ptrace(PTRACE_ATTACH, child_pid[0], NULL, NULL));
32
33 if (TST_RET == 0) {
34 tst_res(TFAIL, "ptrace() succeeded unexpectedly");
35 exit(0);
36 }
37
38 if (TST_RET != -1) {
39 tst_res(TFAIL,
40 "Invalid ptrace() return value %ld", TST_RET);
41 exit(0);
42 }
43
44 if (TST_ERR == EPERM)
45 tst_res(TPASS | TTERRNO, "ptrace() failed as expected");
46 else
47 tst_res(TFAIL | TTERRNO, "ptrace() expected EPERM, but got");
48 exit(0);
49 }
50 SAFE_WAITPID(child_pid[1], NULL, 0);
51 SAFE_KILL(child_pid[0], SIGKILL);
52 SAFE_WAITPID(child_pid[0], NULL, 0);
53 }
54
setup(void)55 static void setup(void)
56 {
57 struct passwd *pw;
58
59 pw = SAFE_GETPWNAM("nobody");
60 uid = pw->pw_uid;
61 }
62
63 static struct tst_test test = {
64 .setup = setup,
65 .test_all = verify_ptrace,
66 .forks_child = 1,
67 .needs_root = 1,
68 };
69