summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_chroot.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libc/sys/t_chroot.c')
-rw-r--r--src/regress/lib/libc/sys/t_chroot.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_chroot.c b/src/regress/lib/libc/sys/t_chroot.c
new file mode 100644
index 0000000000..1fbe392a88
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_chroot.c
@@ -0,0 +1,321 @@
1/* $OpenBSD: t_chroot.c,v 1.1.1.1 2019/11/19 19:57:03 bluhm Exp $ */
2/* $NetBSD: t_chroot.c,v 1.2 2017/01/10 22:36:29 christos Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/cdefs.h>
36__RCSID("$NetBSD: t_chroot.c,v 1.2 2017/01/10 22:36:29 christos Exp $");
37
38#include <sys/wait.h>
39#include <sys/stat.h>
40
41#include "atf-c.h"
42#include <errno.h>
43#include <fcntl.h>
44#include <limits.h>
45#include <pwd.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49
50ATF_TC(chroot_basic);
51ATF_TC_HEAD(chroot_basic, tc)
52{
53 atf_tc_set_md_var(tc, "descr", "A basic test of chroot(2)");
54 atf_tc_set_md_var(tc, "require.user", "root");
55}
56
57ATF_TC_BODY(chroot_basic, tc)
58{
59 char buf[PATH_MAX];
60 int fd, sta;
61 pid_t pid;
62
63 (void)memset(buf, '\0', sizeof(buf));
64 (void)getcwd(buf, sizeof(buf));
65 (void)strlcat(buf, "/dir", sizeof(buf));
66
67 ATF_REQUIRE(mkdir(buf, 0500) == 0);
68 ATF_REQUIRE(chdir(buf) == 0);
69
70 pid = fork();
71 ATF_REQUIRE(pid >= 0);
72
73 if (pid == 0) {
74
75 if (chroot(buf) != 0)
76 _exit(EXIT_FAILURE);
77
78 errno = 0;
79
80 if (chroot("/root") != -1)
81 _exit(EXIT_FAILURE);
82
83 if (errno != ENOENT)
84 _exit(EXIT_FAILURE);
85
86 fd = open("file", O_RDONLY | O_CREAT, 0600);
87
88 if (fd < 0)
89 _exit(EXIT_FAILURE);
90
91 if (close(fd) != 0)
92 _exit(EXIT_FAILURE);
93
94 _exit(EXIT_SUCCESS);
95 }
96
97 (void)wait(&sta);
98
99 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
100 atf_tc_fail("chroot(2) failed");
101
102 (void)chdir("/");
103 (void)strlcat(buf, "/file", sizeof(buf));
104
105 fd = open(buf, O_RDONLY);
106
107 if (fd < 0)
108 atf_tc_fail("chroot(2) did not change the root directory");
109
110 ATF_REQUIRE(close(fd) == 0);
111 ATF_REQUIRE(unlink(buf) == 0);
112}
113
114ATF_TC(chroot_err);
115ATF_TC_HEAD(chroot_err, tc)
116{
117 atf_tc_set_md_var(tc, "descr", "Test error conditions of chroot(2)");
118 atf_tc_set_md_var(tc, "require.user", "root");
119}
120
121ATF_TC_BODY(chroot_err, tc)
122{
123 char buf[PATH_MAX + 1];
124
125 (void)memset(buf, 'x', sizeof(buf));
126
127 errno = 0;
128 ATF_REQUIRE_ERRNO(ENAMETOOLONG, chroot(buf) == -1);
129
130 errno = 0;
131 ATF_REQUIRE_ERRNO(EFAULT, chroot((void *)-1) == -1);
132
133 errno = 0;
134 ATF_REQUIRE_ERRNO(ENOENT, chroot("/a/b/c/d/e/f/g/h/i/j") == -1);
135}
136
137ATF_TC(chroot_perm);
138ATF_TC_HEAD(chroot_perm, tc)
139{
140 atf_tc_set_md_var(tc, "descr", "Test permissions with chroot(2)");
141 atf_tc_set_md_var(tc, "require.user", "unprivileged");
142}
143
144ATF_TC_BODY(chroot_perm, tc)
145{
146 static char buf[LINE_MAX];
147 pid_t pid;
148 int sta;
149
150 (void)memset(buf, '\0', sizeof(buf));
151 ATF_REQUIRE(getcwd(buf, sizeof(buf)) != NULL);
152
153 pid = fork();
154 ATF_REQUIRE(pid >= 0);
155
156 if (pid == 0) {
157
158 errno = 0;
159
160 if (chroot(buf) != -1)
161 _exit(EXIT_FAILURE);
162
163 if (errno != EPERM)
164 _exit(EXIT_FAILURE);
165
166 _exit(EXIT_SUCCESS);
167 }
168
169 (void)wait(&sta);
170
171 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
172 atf_tc_fail("chroot(2) succeeded as unprivileged user");
173}
174
175ATF_TC(fchroot_basic);
176ATF_TC_HEAD(fchroot_basic, tc)
177{
178 atf_tc_set_md_var(tc, "descr", "A basic test of fchroot(2)");
179 atf_tc_set_md_var(tc, "require.user", "root");
180}
181
182ATF_TC_BODY(fchroot_basic, tc)
183{
184 char buf[PATH_MAX];
185 int fd, sta;
186 pid_t pid;
187
188 (void)memset(buf, '\0', sizeof(buf));
189 (void)getcwd(buf, sizeof(buf));
190 (void)strlcat(buf, "/dir", sizeof(buf));
191
192 ATF_REQUIRE(mkdir(buf, 0500) == 0);
193 ATF_REQUIRE(chdir(buf) == 0);
194
195 fd = open(buf, O_RDONLY);
196 ATF_REQUIRE(fd >= 0);
197
198 pid = fork();
199 ATF_REQUIRE(pid >= 0);
200
201 if (pid == 0) {
202
203 if (fchroot(fd) != 0)
204 _exit(EXIT_FAILURE);
205
206 if (close(fd) != 0)
207 _exit(EXIT_FAILURE);
208
209 fd = open("file", O_RDONLY | O_CREAT, 0600);
210
211 if (fd < 0)
212 _exit(EXIT_FAILURE);
213
214 if (close(fd) != 0)
215 _exit(EXIT_FAILURE);
216
217 _exit(EXIT_SUCCESS);
218 }
219
220 (void)wait(&sta);
221
222 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
223 atf_tc_fail("fchroot(2) failed");
224
225 (void)chdir("/");
226 (void)strlcat(buf, "/file", sizeof(buf));
227
228 fd = open(buf, O_RDONLY);
229
230 if (fd < 0)
231 atf_tc_fail("fchroot(2) did not change the root directory");
232
233 ATF_REQUIRE(close(fd) == 0);
234 ATF_REQUIRE(unlink(buf) == 0);
235}
236
237ATF_TC(fchroot_err);
238ATF_TC_HEAD(fchroot_err, tc)
239{
240 atf_tc_set_md_var(tc, "descr", "Test error conditions of fchroot(2)");
241 atf_tc_set_md_var(tc, "require.user", "root");
242}
243
244ATF_TC_BODY(fchroot_err, tc)
245{
246 int fd;
247
248 fd = open("/etc/passwd", O_RDONLY);
249 ATF_REQUIRE(fd >= 0);
250
251 errno = 0;
252 ATF_REQUIRE_ERRNO(EBADF, fchroot(-1) == -1);
253
254 errno = 0;
255 ATF_REQUIRE_ERRNO(ENOTDIR, fchroot(fd) == -1);
256
257 ATF_REQUIRE(close(fd) == 0);
258}
259
260ATF_TC(fchroot_perm);
261ATF_TC_HEAD(fchroot_perm, tc)
262{
263 atf_tc_set_md_var(tc, "descr", "Test permissions with fchroot(2)");
264 atf_tc_set_md_var(tc, "require.user", "root");
265}
266
267ATF_TC_BODY(fchroot_perm, tc)
268{
269 static char buf[LINE_MAX];
270 struct passwd *pw;
271 int fd, sta;
272 pid_t pid;
273
274 (void)memset(buf, '\0', sizeof(buf));
275 ATF_REQUIRE(getcwd(buf, sizeof(buf)) != NULL);
276
277 pw = getpwnam("nobody");
278 fd = open(buf, O_RDONLY);
279
280 ATF_REQUIRE(fd >= 0);
281 ATF_REQUIRE(pw != NULL);
282
283 pid = fork();
284 ATF_REQUIRE(pid >= 0);
285
286 if (pid == 0) {
287
288 (void)setuid(pw->pw_uid);
289
290 errno = 0;
291
292 if (fchroot(fd) != -1)
293 _exit(EXIT_FAILURE);
294
295 if (errno != EPERM)
296 _exit(EXIT_FAILURE);
297
298 _exit(EXIT_SUCCESS);
299 }
300
301 (void)wait(&sta);
302
303 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
304 atf_tc_fail("fchroot(2) succeeded as unprivileged user");
305}
306
307ATF_TP_ADD_TCS(tp)
308{
309
310 ATF_TP_ADD_TC(tp, chroot_basic);
311 ATF_TP_ADD_TC(tp, chroot_err);
312 ATF_TP_ADD_TC(tp, chroot_perm);
313/*
314 * Not available on OpenBSD
315 * ATF_TP_ADD_TC(tp, fchroot_basic);
316 * ATF_TP_ADD_TC(tp, fchroot_err);
317 * ATF_TP_ADD_TC(tp, fchroot_perm);
318 */
319
320 return atf_no_error();
321}