Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kern/jail_lookup_root.c
39483 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2025 Mark Johnston <[email protected]>
5
*/
6
7
#include <sys/param.h>
8
#include <sys/jail.h>
9
#include <sys/mount.h>
10
#include <sys/stat.h>
11
12
#include <err.h>
13
#include <errno.h>
14
#include <fcntl.h>
15
#include <jail.h>
16
#include <mntopts.h>
17
#include <stdio.h>
18
#include <stdlib.h>
19
20
#include <atf-c.h>
21
22
static void
23
mkdir_checked(const char *dir, mode_t mode)
24
{
25
int error;
26
27
error = mkdir(dir, mode);
28
ATF_REQUIRE_MSG(error == 0 || errno == EEXIST,
29
"mkdir %s: %s", dir, strerror(errno));
30
}
31
32
static void __unused
33
mount_nullfs(const char *dir, const char *target)
34
{
35
struct iovec *iov;
36
char errmsg[1024];
37
int error, iovlen;
38
39
iov = NULL;
40
iovlen = 0;
41
42
build_iovec(&iov, &iovlen, __DECONST(char *, "fstype"),
43
__DECONST(char *, "nullfs"), (size_t)-1);
44
build_iovec(&iov, &iovlen, __DECONST(char *, "fspath"),
45
__DECONST(char *, target), (size_t)-1);
46
build_iovec(&iov, &iovlen, __DECONST(char *, "from"),
47
__DECONST(char *, dir), (size_t)-1);
48
build_iovec(&iov, &iovlen, __DECONST(char *, "errmsg"),
49
errmsg, sizeof(errmsg));
50
51
errmsg[0] = '\0';
52
error = nmount(iov, iovlen, 0);
53
ATF_REQUIRE_MSG(error == 0, "nmount: %s",
54
errmsg[0] != '\0' ? errmsg : strerror(errno));
55
56
free_iovec(&iov, &iovlen);
57
}
58
59
ATF_TC_WITH_CLEANUP(jail_root);
60
ATF_TC_HEAD(jail_root, tc)
61
{
62
atf_tc_set_md_var(tc, "require.user", "root");
63
}
64
ATF_TC_BODY(jail_root, tc)
65
{
66
int error, fd, jid;
67
68
mkdir_checked("./root", 0755);
69
mkdir_checked("./root/a", 0755);
70
mkdir_checked("./root/b", 0755);
71
mkdir_checked("./root/a/c", 0755);
72
73
jid = jail_setv(JAIL_CREATE | JAIL_ATTACH,
74
"name", "nullfs_jail_root_test",
75
"allow.mount", "true",
76
"allow.mount.nullfs", "true",
77
"enforce_statfs", "1",
78
"path", "./root",
79
"persist", NULL,
80
NULL);
81
ATF_REQUIRE_MSG(jid >= 0, "jail_setv: %s", jail_errmsg);
82
83
mount_nullfs("/a", "/b");
84
85
error = chdir("/b/c");
86
ATF_REQUIRE(error == 0);
87
88
error = rename("/a/c", "/c");
89
ATF_REQUIRE(error == 0);
90
91
/* Descending to the jail root should be ok. */
92
error = chdir("..");
93
ATF_REQUIRE(error == 0);
94
95
/* Going beyond the root will trigger an error. */
96
error = chdir("..");
97
ATF_REQUIRE_ERRNO(ENOENT, error != 0);
98
fd = open("..", O_RDONLY | O_DIRECTORY);
99
ATF_REQUIRE_ERRNO(ENOENT, fd < 0);
100
}
101
ATF_TC_CLEANUP(jail_root, tc)
102
{
103
struct statfs fs;
104
fsid_t fsid;
105
int error, jid;
106
107
error = statfs("./root/b", &fs);
108
if (error != 0)
109
err(1, "statfs ./b");
110
fsid = fs.f_fsid;
111
error = statfs("./root", &fs);
112
if (error != 0)
113
err(1, "statfs ./root");
114
if (fsid.val[0] != fs.f_fsid.val[0] ||
115
fsid.val[1] != fs.f_fsid.val[1]) {
116
error = unmount("./root/b", 0);
117
if (error != 0)
118
err(1, "unmount ./root/b");
119
}
120
121
jid = jail_getid("nullfs_jail_root_test");
122
if (jid >= 0) {
123
error = jail_remove(jid);
124
if (error != 0)
125
err(1, "jail_remove");
126
}
127
}
128
129
ATF_TP_ADD_TCS(tp)
130
{
131
ATF_TP_ADD_TC(tp, jail_root);
132
return (atf_no_error());
133
}
134
135