💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › d09d5c04e379ebed65fbd53e3a2fd… captured on 2023-12-28 at 15:45:05. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 /*
1 * ISC License
2 * Copyright (c) 2023 RMF <rawmonk@firemail.cc>
3 */
4 #if defined (__linux__) && !defined (DISABLE_SANDBOX)
5 #include <linux/seccomp.h>
6 #define _DEFAULT_SOURCE
7 #include <sys/syscall.h>
8 #include <sys/resource.h>
9 #include <sys/prctl.h>
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include "macro.h"
16 #include "sandbox.h"
17 #include "storage.h"
18 #include "error.h"
19 #include "config.h"
20
21 #ifdef ENABLE_SECCOMP_FILTER
22 #include <linux/filter.h>
23 #include <stddef.h>
24
25 #define SC_ALLOW(nr) \
26 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_##nr, 0, 1), \
27 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
28
29 struct sock_filter filter[] = {
30 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
31 (offsetof(struct seccomp_data, arch))),
32 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
33 (offsetof(struct seccomp_data, nr))),
34 SC_ALLOW(readv),
35 SC_ALLOW(writev),
36 #ifdef __NR_open
37 SC_ALLOW(open),
38 #endif
39 SC_ALLOW(dup),
40 #ifdef __NR_dup2
41 SC_ALLOW(dup2),
42 #endif
43 SC_ALLOW(pipe2),
44 SC_ALLOW(recvmsg),
45 SC_ALLOW(getsockname),
46 SC_ALLOW(fstat),
47 #ifdef __NR_stat
48 SC_ALLOW(stat),
49 #endif
50 #ifdef __NR_pipe
51 SC_ALLOW(pipe),
52 #endif
53 SC_ALLOW(setsockopt),
54 SC_ALLOW(read),
55 SC_ALLOW(write),
56 SC_ALLOW(openat),
57 SC_ALLOW(close),
58 SC_ALLOW(exit),
59 SC_ALLOW(ioctl),
60 SC_ALLOW(exit_group),
61 SC_ALLOW(futex),
62 SC_ALLOW(sysinfo),
63 SC_ALLOW(brk),
64 SC_ALLOW(newfstatat),
65 SC_ALLOW(getpid),
66 SC_ALLOW(getrandom),
67 SC_ALLOW(mmap),
68 SC_ALLOW(fcntl),
69 SC_ALLOW(lseek),
70 SC_ALLOW(rt_sigaction),
71 SC_ALLOW(rt_sigprocmask),
72 SC_ALLOW(rt_sigreturn),
73 SC_ALLOW(mprotect),
74 SC_ALLOW(pread64),
75 SC_ALLOW(uname),
76 SC_ALLOW(ppoll),
77 SC_ALLOW(bind),
78 SC_ALLOW(sendto),
79 SC_ALLOW(recvfrom),
80 SC_ALLOW(socket),
81 SC_ALLOW(socketpair),
82 SC_ALLOW(connect),
83 SC_ALLOW(getsockopt),
84 #ifdef __NR_poll
85 SC_ALLOW(poll),
86 #endif
87 SC_ALLOW(clone),
88 #ifdef __NR_clone3
89 SC_ALLOW(clone3),
90 #endif
91 SC_ALLOW(clock_nanosleep),
92 SC_ALLOW(nanosleep),
93 SC_ALLOW(rseq),
94 SC_ALLOW(set_robust_list),
95 SC_ALLOW(munmap),
96 SC_ALLOW(madvise),
97 SC_ALLOW(mremap),
98 #ifdef __NR_select
99 SC_ALLOW(select),
100 #endif
101 SC_ALLOW(membarrier),
102 SC_ALLOW(sendmmsg),
103 #ifdef __NR_pselect6
104 SC_ALLOW(pselect6),
105 #endif
106 SC_ALLOW(getdents),
107 SC_ALLOW(getdents64),
108 SC_ALLOW(unlink),
109 SC_ALLOW(unlinkat),
110 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
111 };
112
113 int enable_seccomp() {
114 struct sock_fprog prog;
115 prog.len = (unsigned short)(sizeof(filter) / sizeof (filter[0]));
116 prog.filter = filter;
117 return prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0);
118 }
119 #endif
120
121 #ifdef HAS_LANDLOCK
122 #include <linux/landlock.h>
123
124 static int landlock_create_ruleset(
125 const struct landlock_ruleset_attr *attr,
126 size_t size, uint32_t flags) {
127 return syscall(SYS_landlock_create_ruleset, attr, size, flags);
128 }
129
130 static int landlock_add_rule(int ruleset_fd,
131 enum landlock_rule_type type,
132 const void *attr, uint32_t flags) {
133 return syscall(SYS_landlock_add_rule, ruleset_fd, type, attr, flags);
134 }
135
136 static int landlock_restrict_self(int ruleset_fd, __u32 flags) {
137 return syscall(SYS_landlock_restrict_self, ruleset_fd, flags);
138 }
139
140 int landlock_unveil(int landlock_fd, int fd, int perms)
141 {
142 int ret, err;
143 struct landlock_path_beneath_attr attr = {0};
144 attr.allowed_access = perms;
145 attr.parent_fd = fd;
146
147 ret = landlock_add_rule(landlock_fd, LANDLOCK_RULE_PATH_BENEATH,
148 &attr, 0);
149 err = errno;
150 close(attr.parent_fd);
151 errno = err;
152 return ret;
153 }
154
155 int landlock_unveil_path(int landlock_fd, const char* path, int perms) {
156 int fd = open(path, 0);
157 if (fd < 0) return -1;
158 return landlock_unveil(landlock_fd, fd, perms);
159 }
160
161 int landlock_init() {
162 struct landlock_ruleset_attr attr = {0};
163 attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
164 LANDLOCK_ACCESS_FS_READ_DIR |
165 LANDLOCK_ACCESS_FS_WRITE_FILE |
166 LANDLOCK_ACCESS_FS_MAKE_REG;
167 return landlock_create_ruleset(&attr, sizeof(attr), 0);
168 }
169
170 int landlock_apply(int fd)
171 {
172 int ret = landlock_restrict_self(fd, 0);
173 int err = errno;
174 close(fd);
175 errno = err;
176 return ret;
177 }
178 #endif
179
180 int sandbox_init() {
181
182 char path[2048], download_path[2048];
183 #ifdef HAS_LANDLOCK
184 int fd;
185 #endif
186 int ret;
187 struct rlimit limit;
188
189 if (!config.enableSandbox) return 0;
190
191 /* prevents from creating large file */
192 limit.rlim_max = limit.rlim_cur = config.maximumBodyLength;
193 if (setrlimit(RLIMIT_FSIZE, &limit))
194 return ERROR_SANDBOX_FAILURE;
195
196 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
197 return ERROR_SANDBOX_FAILURE;
198
199 if ((ret = storage_path(V(path)))) return ret;
200 if ((ret = storage_download_path(V(download_path)))) return ret;
201
202 #ifdef HAS_LANDLOCK
203 /* restrict filesystem access */
204 fd = landlock_init();
205 if (fd < 0) return ERROR_SANDBOX_FAILURE;
206 ret = landlock_unveil_path(fd, path,
207 LANDLOCK_ACCESS_FS_READ_FILE |
208 LANDLOCK_ACCESS_FS_WRITE_FILE |
209 LANDLOCK_ACCESS_FS_MAKE_REG);
210 ret |= landlock_unveil_path(fd, download_path,
211 LANDLOCK_ACCESS_FS_WRITE_FILE |
212 LANDLOCK_ACCESS_FS_MAKE_REG);
213 ret |= landlock_unveil_path(fd, "/etc/hosts",
214 LANDLOCK_ACCESS_FS_READ_FILE);
215 ret |= landlock_unveil_path(fd, "/etc/resolv.conf",
216 LANDLOCK_ACCESS_FS_READ_FILE);
217
218 if (ret) return ERROR_SANDBOX_FAILURE;
219
220 if (landlock_apply(fd)) return ERROR_SANDBOX_FAILURE;
221 #endif
222
223 #ifdef ENABLE_SECCOMP_FILTER
224 if (enable_seccomp()) return ERROR_SANDBOX_FAILURE;
225 #endif
226
227 return 0;
228 }
229
230 int sandbox_isolate() {
231 if (!config.enableSandbox) return 0;
232 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT))
233 return ERROR_SANDBOX_FAILURE;
234 return 0;
235 }
236
237 int sandbox_set_name(const char *name) {
238 if (prctl(PR_SET_NAME, name))
239 return ERROR_SANDBOX_FAILURE;
240 return 0;
241 }
242 #else
243 typedef int hide_warning;
244 #endif
245