summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_ptrace.c
diff options
context:
space:
mode:
authorcvs2svn <admin@example.com>2025-04-14 17:32:06 +0000
committercvs2svn <admin@example.com>2025-04-14 17:32:06 +0000
commiteb8dd9dca1228af0cd132f515509051ecfabf6f6 (patch)
treeedb6da6af7e865d488dc1a29309f1e1ec226e603 /src/regress/lib/libc/sys/t_ptrace.c
parent247f0352e0ed72a4f476db9dc91f4d982bc83eb2 (diff)
downloadopenbsd-tb_20250414.tar.gz
openbsd-tb_20250414.tar.bz2
openbsd-tb_20250414.zip
This commit was manufactured by cvs2git to create tag 'tb_20250414'.tb_20250414
Diffstat (limited to 'src/regress/lib/libc/sys/t_ptrace.c')
-rw-r--r--src/regress/lib/libc/sys/t_ptrace.c232
1 files changed, 0 insertions, 232 deletions
diff --git a/src/regress/lib/libc/sys/t_ptrace.c b/src/regress/lib/libc/sys/t_ptrace.c
deleted file mode 100644
index 4b87acfdd2..0000000000
--- a/src/regress/lib/libc/sys/t_ptrace.c
+++ /dev/null
@@ -1,232 +0,0 @@
1/* $OpenBSD: t_ptrace.c,v 1.5 2021/12/13 16:56:48 deraadt Exp $ */
2/* $NetBSD: t_ptrace.c,v 1.4 2018/05/14 12:44:40 kamil Exp $ */
3
4/*-
5 * Copyright (c) 2016 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "macros.h"
31
32#include <sys/types.h>
33#include <sys/ptrace.h>
34#include <sys/stat.h>
35#include <sys/sysctl.h>
36#include <err.h>
37#include <errno.h>
38#include <limits.h>
39#include <unistd.h>
40
41#include "atf-c.h"
42
43#include "h_macros.h"
44
45/*
46 * A child process cannot call atf functions and expect them to magically
47 * work like in the parent.
48 * The printf(3) messaging from a child will not work out of the box as well
49 * without estabilishing a communication protocol with its parent. To not
50 * overcomplicate the tests - do not log from a child and use err(3)/errx(3)
51 * wrapped with FORKEE_ASSERT()/FORKEE_ASSERTX() as that is guaranteed to work.
52 */
53#define FORKEE_ASSERTX(x) \
54do { \
55 int ret = (x); \
56 if (!ret) \
57 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s", \
58 __FILE__, __LINE__, __func__, #x); \
59} while (0)
60
61#define FORKEE_ASSERT(x) \
62do { \
63 int ret = (x); \
64 if (!ret) \
65 err(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s", \
66 __FILE__, __LINE__, __func__, #x); \
67} while (0)
68
69ATF_TC(attach_pid0);
70ATF_TC_HEAD(attach_pid0, tc)
71{
72 atf_tc_set_md_var(tc, "descr",
73 "Assert that a debugger cannot attach to PID 0");
74}
75
76ATF_TC_BODY(attach_pid0, tc)
77{
78 errno = 0;
79 ATF_REQUIRE_ERRNO(EPERM, ptrace(PT_ATTACH, 0, NULL, 0) == -1);
80}
81
82ATF_TC(attach_pid1);
83ATF_TC_HEAD(attach_pid1, tc)
84{
85 atf_tc_set_md_var(tc, "descr",
86 "Assert that a debugger cannot attach to PID 1 (as non-root)");
87
88 atf_tc_set_md_var(tc, "require.user", "unprivileged");
89}
90
91ATF_TC_BODY(attach_pid1, tc)
92{
93 ATF_REQUIRE_ERRNO(EPERM, ptrace(PT_ATTACH, 1, NULL, 0) == -1);
94}
95
96ATF_TC(attach_pid1_securelevel);
97ATF_TC_HEAD(attach_pid1_securelevel, tc)
98{
99 atf_tc_set_md_var(tc, "descr",
100 "Assert that a debugger cannot attach to PID 1 with "
101 "securelevel >= 0 (as root)");
102
103 atf_tc_set_md_var(tc, "require.user", "root");
104}
105
106ATF_TC_BODY(attach_pid1_securelevel, tc)
107{
108 int level;
109 size_t len = sizeof(level);
110
111 ATF_REQUIRE(sysctlbyname("kern.securelevel", &level, &len, NULL, 0)
112 != -1);
113
114 if (level < 0) {
115 atf_tc_skip("Test must be run with securelevel >= 0");
116 }
117
118 ATF_REQUIRE_ERRNO(EPERM, ptrace(PT_ATTACH, 1, NULL, 0) == -1);
119}
120
121ATF_TC(attach_self);
122ATF_TC_HEAD(attach_self, tc)
123{
124 atf_tc_set_md_var(tc, "descr",
125 "Assert that a debugger cannot attach to self (as it's nonsense)");
126}
127
128ATF_TC_BODY(attach_self, tc)
129{
130 ATF_REQUIRE_ERRNO(EINVAL, ptrace(PT_ATTACH, getpid(), NULL, 0) == -1);
131}
132
133ATF_TC(attach_chroot);
134ATF_TC_HEAD(attach_chroot, tc)
135{
136 atf_tc_set_md_var(tc, "descr",
137 "Assert that a debugger cannot trace another process unless the "
138 "process's root directory is at or below the tracing process's "
139 "root");
140
141 atf_tc_set_md_var(tc, "require.user", "root");
142}
143
144ATF_TC_BODY(attach_chroot, tc)
145{
146 char buf[PATH_MAX];
147 pid_t child;
148 int fds_toparent[2], fds_fromparent[2];
149 int rv;
150 uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
151
152 (void)memset(buf, '\0', sizeof(buf));
153 ATF_REQUIRE(getcwd(buf, sizeof(buf)) != NULL);
154 (void)strlcat(buf, "/dir", sizeof(buf));
155
156 ATF_REQUIRE(mkdir(buf, 0500) == 0);
157 ATF_REQUIRE(chdir(buf) == 0);
158
159 ATF_REQUIRE(pipe(fds_toparent) == 0);
160 ATF_REQUIRE(pipe(fds_fromparent) == 0);
161 child = atf_utils_fork();
162 if (child == 0) {
163 FORKEE_ASSERT(close(fds_toparent[0]) == 0);
164 FORKEE_ASSERT(close(fds_fromparent[1]) == 0);
165
166 FORKEE_ASSERT(chroot(buf) == 0);
167
168 rv = write(fds_toparent[1], &msg, sizeof(msg));
169 FORKEE_ASSERTX(rv == sizeof(msg));
170
171#ifdef __OpenBSD__
172 ATF_REQUIRE_ERRNO(EINVAL,
173#else
174 ATF_REQUIRE_ERRNO(EPERM,
175#endif
176 ptrace(PT_ATTACH, getppid(), NULL, 0) == -1);
177
178 rv = read(fds_fromparent[0], &msg, sizeof(msg));
179 FORKEE_ASSERTX(rv == sizeof(msg));
180
181 _exit(0);
182 }
183 ATF_REQUIRE(close(fds_toparent[1]) == 0);
184 ATF_REQUIRE(close(fds_fromparent[0]) == 0);
185
186 printf("Waiting for chrooting of the child PID %d\n", child);
187 rv = read(fds_toparent[0], &msg, sizeof(msg));
188 ATF_REQUIRE(rv == sizeof(msg));
189
190 printf("Child is ready, it will try to PT_ATTACH to parent\n");
191 rv = write(fds_fromparent[1], &msg, sizeof(msg));
192 ATF_REQUIRE(rv == sizeof(msg));
193
194 printf("fds_fromparent is no longer needed - close it\n");
195 ATF_REQUIRE(close(fds_fromparent[1]) == 0);
196
197 printf("fds_toparent is no longer needed - close it\n");
198 ATF_REQUIRE(close(fds_toparent[0]) == 0);
199}
200
201ATF_TC(traceme_twice);
202ATF_TC_HEAD(traceme_twice, tc)
203{
204 atf_tc_set_md_var(tc, "descr",
205 "Assert that a process cannot mark its parent a debugger twice");
206}
207
208ATF_TC_BODY(traceme_twice, tc)
209{
210
211 printf("Mark the parent process (PID %d) a debugger of PID %d\n",
212 getppid(), getpid());
213 ATF_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) == 0);
214
215 printf("Mark the parent process (PID %d) a debugger of PID %d again\n",
216 getppid(), getpid());
217 ATF_REQUIRE_ERRNO(EBUSY, ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
218}
219
220ATF_TP_ADD_TCS(tp)
221{
222 setvbuf(stdout, NULL, _IONBF, 0);
223 setvbuf(stderr, NULL, _IONBF, 0);
224 ATF_TP_ADD_TC(tp, attach_pid0);
225 ATF_TP_ADD_TC(tp, attach_pid1);
226 ATF_TP_ADD_TC(tp, attach_pid1_securelevel);
227 ATF_TP_ADD_TC(tp, attach_self);
228 ATF_TP_ADD_TC(tp, attach_chroot);
229 ATF_TP_ADD_TC(tp, traceme_twice);
230
231 return atf_no_error();
232}