💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Upload › files › be4e446fa44a2281a88e0935eb7… captured on 2023-09-08 at 16:42:42. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-03-20)
-=-=-=-=-=-=-
0 /* See LICENSE for license details. */
1 #include "sandbox.h"
2 #include <strings.h>
3 #include <unistd.h>
4 #include <stdio.h>
5
6 #ifndef NO_SANDBOX
7
8 #ifdef __illumos__
9 #include <priv.h>
10 #include <errno.h>
11
12 #define SANDBOXED
13 int
14 init_privs(const char **privs) {
15
16 int i = 0;
17
18 priv_set_t *pset;
19 if ((pset = priv_allocset()) == NULL) {
20 printf("priv_allocset: %s\n", strerror(errno));
21 return -1;
22 }
23 priv_emptyset(pset);
24 while (privs[i]) {
25 if (priv_addset(pset, privs[i]) != 0) {
26 printf("priv_addset: %s\n", strerror(errno));
27 return -1;
28 }
29 i++;
30 }
31 if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 ||
32 setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 ||
33 setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0) {
34 printf("setppriv: %s\n", strerror(errno));
35 return -1;
36 }
37 priv_freeset(pset);
38 return 0;
39 }
40
41 int
42 sandbox_start(const char* path)
43 {
44 if (!path) return -1;
45 const char* privs[] = {PRIV_NET_ACCESS, PRIV_FILE_WRITE, NULL};
46 if (init_privs(privs)) return -1;
47 return 0;
48 }
49 #endif
50
51 #ifdef __OpenBSD__
52 #define SANDBOXED
53 int
54 sandbox_start(const char* path)
55 {
56 unveil(path, "rwc");
57 unveil(NULL, NULL);
58 pledge("stdio inet rpath wpath cpath", NULL);
59 return 0;
60 }
61 #endif
62
63 #ifdef __linux__
64 #define SANDBOXED
65 #include <sys/syscall.h>
66 #include <unistd.h>
67 #include <stdio.h>
68 #include <fcntl.h>
69 #include <string.h>
70 #include <errno.h>
71 #include <stddef.h>
72 #include <stdint.h>
73 #include <sys/prctl.h>
74 #include <linux/seccomp.h>
75 #include <linux/filter.h>
76 #include <linux/unistd.h>
77 long syscall(long number, ...); /* fix warning */
78
79 #if ENABLE_LANDLOCK || \
80 (!defined(DISABLE_LANDLOCK) && __has_include(<linux/landlock.h>))
81 #include <linux/landlock.h>
82 #define ENABLE_LANDLOCK
83 #endif
84
85 #define SC_ALLOW_(nr) \
86 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, nr, 0, 1), \
87 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
88 #define SC_ALLOW(nr) \
89 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_##nr, 0, 1), \
90 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
91 #define SC_ALLOW_ARG(_nr, _arg, _val) \
92 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (_nr), 0, 6), \
93 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \
94 offsetof(struct seccomp_data, args[(_arg)]) + SC_ARG_LO), \
95 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, \
96 ((_val) & 0xffffffff), 0, 3), \
97 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \
98 offsetof(struct seccomp_data, args[(_arg)]) + SC_ARG_HI), \
99 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, \
100 (((uint32_t)((uint64_t)(_val) >> 32)) & 0xffffffff), 0, 1), \
101 BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW), \
102 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \
103 offsetof(struct seccomp_data, nr))
104
105 struct sock_filter filter[] = {
106 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
107 (offsetof(struct seccomp_data, arch))),
108 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
109 (offsetof(struct seccomp_data, nr))),
110 SC_ALLOW(fstat),
111 SC_ALLOW(stat),
112 SC_ALLOW(setsockopt),
113 SC_ALLOW(accept),
114 SC_ALLOW(listen),
115 SC_ALLOW(bind),
116 SC_ALLOW(mkdir),
117 SC_ALLOW(read),
118 SC_ALLOW(write),
119 SC_ALLOW(readv),
120 SC_ALLOW(writev),
121 SC_ALLOW(creat),
122 SC_ALLOW(open),
123 SC_ALLOW(openat),
124 SC_ALLOW(ioctl),
125 SC_ALLOW(close),
126 SC_ALLOW(exit),
127 SC_ALLOW(exit_group),
128 SC_ALLOW(futex),
129 SC_ALLOW(newfstatat),
130 SC_ALLOW(fcntl),
131 SC_ALLOW(lseek),
132 SC_ALLOW(mprotect),
133 SC_ALLOW(pread64),
134 SC_ALLOW(sendto),
135 SC_ALLOW(recvfrom),
136 SC_ALLOW(socket),
137 SC_ALLOW(getsockopt),
138 SC_ALLOW(poll),
139 SC_ALLOW(mmap),
140 SC_ALLOW(munmap),
141 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
142 };
143
144 #ifdef ENABLE_LANDLOCK
145
146 static int
147 landlock_create_ruleset(const struct landlock_ruleset_attr *attr,
148 size_t size, uint32_t flags)
149 {
150 return syscall(__NR_landlock_create_ruleset, attr, size, flags);
151 }
152
153 static int
154 landlock_add_rule(int ruleset_fd, enum landlock_rule_type type,
155 const void *attr, uint32_t flags)
156 {
157 return syscall(__NR_landlock_add_rule, ruleset_fd, type, attr, flags);
158 }
159
160 static int
161 landlock_restrict_self(int ruleset_fd, __u32 flags)
162 {
163 return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
164 }
165
166 int
167 landlock_unveil(int landlock_fd, int fd, int perms)
168 {
169 int ret, err;
170 struct landlock_path_beneath_attr attr = {0};
171 attr.allowed_access = perms;
172 attr.parent_fd = fd;
173
174 ret = landlock_add_rule(landlock_fd,
175 LANDLOCK_RULE_PATH_BENEATH, &attr, 0);
176 err = errno;
177 close(attr.parent_fd);
178 errno = err;
179 return ret;
180 }
181
182 #include <fcntl.h>
183 int
184 landlock_unveil_path(int landlock_fd, const char* path, int perms)
185 {
186 int fd = open(path, 0);
187 if (fd < 0) return -1;
188 return landlock_unveil(landlock_fd, fd, perms);
189 }
190
191 int
192 landlock_init()
193 {
194 struct landlock_ruleset_attr attr = {0};
195 attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
196 LANDLOCK_ACCESS_FS_WRITE_FILE;
197 return landlock_create_ruleset(&attr, sizeof(attr), 0);
198 }
199
200 int
201 landlock_apply(int fd)
202 {
203 int ret = landlock_restrict_self(fd, 0);
204 int err = errno;
205 close(fd);
206 errno = err;
207 return ret;
208 }
209 #endif
210
211 int
212 sandbox_start(const char* path)
213 {
214 struct sock_fprog prog = {0};
215 int llfd, download;
216
217 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
218 printf("PR_SET_NO_NEW_PRIVS failed\n");
219 return -1;
220 }
221 #ifdef ENABLE_LANDLOCK
222 llfd = landlock_init();
223 if (llfd < 0) {
224 printf("Failed to initialize landlock : %s\n",
225 strerror(errno));
226 printf("The filesystem won't be hidden from the program\n");
227 goto skip_landlock;
228 }
229 download = landlock_unveil_path(llfd, path,
230 LANDLOCK_ACCESS_FS_READ_FILE |
231 LANDLOCK_ACCESS_FS_WRITE_FILE);
232 if (download) {
233 printf("landlock, failed to unveil : %s\n", strerror(errno));
234 return -1;
235 }
236 if (landlock_apply(llfd)) {
237 printf("landlock, failed to restrict process : %s\n",
238 strerror(errno));
239 return -1;
240 }
241 skip_landlock:;
242 #endif
243 prog.len = (unsigned short)(sizeof(filter) / sizeof (filter[0])),
244 prog.filter = filter;
245 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0)) {
246 printf("Failed to enable seccomp\n");
247 return -1;
248 }
249 return 0;
250 }
251 #endif
252 #endif
253
254 #ifndef SANDBOXED
255 int
256 sandbox_start(const char* path)
257 {
258 if (!path) return 0;
259 printf("No sandbox available on your system\n");
260 return 0;
261 }
262 #endif
263