0 /* See LICENSE file for copyright and license details. */
1
2 #ifdef __linux__
3 #include <sys/syscall.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <fcntl.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <sys/prctl.h>
12 #include <linux/seccomp.h>
13 #include <linux/filter.h>
14 #include <linux/unistd.h>
15 #include "util.h"
16 #include "conf.h"
17
18 long syscall(long number, ...); /* fix warning */
19
20 #if ENABLE_LANDLOCK || \
21 (!defined(DISABLE_LANDLOCK) && __has_include(<linux/landlock.h>))
22 #include <linux/landlock.h>
23 #define ENABLE_LANDLOCK
24 #endif
25
26 #define SC_ALLOW_(nr) \
27 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, nr, 0, 1), \
28 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
29 #define SC_ALLOW(nr) \
30 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_##nr, 0, 1), \
31 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
32 #define SC_ALLOW_ARG(_nr, _arg, _val) \
33 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (_nr), 0, 6), \
34 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \
35 offsetof(struct seccomp_data, args[(_arg)]) + SC_ARG_LO), \
36 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, \
37 ((_val) & 0xffffffff), 0, 3), \
38 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \
39 offsetof(struct seccomp_data, args[(_arg)]) + SC_ARG_HI), \
40 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, \
41 (((uint32_t)((uint64_t)(_val) >> 32)) & 0xffffffff), 0, 1), \
42 BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW), \
43 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \
44 offsetof(struct seccomp_data, nr))
45
46 struct sock_filter filter[] = {
47 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
48 (offsetof(struct seccomp_data, arch))),
49 BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
50 (offsetof(struct seccomp_data, nr))),
51 SC_ALLOW(fstat),
52 SC_ALLOW(stat),
53 SC_ALLOW(setsockopt),
54 SC_ALLOW(accept),
55 SC_ALLOW(listen),
56 SC_ALLOW(bind),
57 SC_ALLOW(mkdir),
58 SC_ALLOW(read),
59 SC_ALLOW(write),
60 SC_ALLOW(readv),
61 SC_ALLOW(writev),
62 SC_ALLOW(creat),
63 SC_ALLOW(open),
64 SC_ALLOW(openat),
65 SC_ALLOW(ioctl),
66 SC_ALLOW(close),
67 SC_ALLOW(exit),
68 SC_ALLOW(exit_group),
69 SC_ALLOW(futex),
70 SC_ALLOW(newfstatat),
71 SC_ALLOW(fcntl),
72 SC_ALLOW(lseek),
73 SC_ALLOW(pread64),
74 SC_ALLOW(sendto),
75 SC_ALLOW(recvfrom),
76 SC_ALLOW(socket),
77 SC_ALLOW(getsockopt),
78 SC_ALLOW(poll),
79 SC_ALLOW(mmap),
80 SC_ALLOW(munmap),
81 SC_ALLOW(rt_sigaction),
82 SC_ALLOW(getpid),
83 SC_ALLOW(getrandom),
84 SC_ALLOW(brk),
85 SC_ALLOW(socketpair),
86 SC_ALLOW(mprotect),
87 SC_ALLOW(clone),
88 SC_ALLOW(clone3),
89 SC_ALLOW(set_robust_list),
90 SC_ALLOW(exit_group),
91 SC_ALLOW(connect),
92 SC_ALLOW(sched_getaffinity),
93 SC_ALLOW(rt_sigprocmask),
94 SC_ALLOW(rseq),
95 SC_ALLOW(uname),
96 SC_ALLOW(dup),
97 SC_ALLOW(writev),
98 SC_ALLOW(madvise),
99 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
100 };
101
102 #ifdef ENABLE_LANDLOCK
103
104 #include <fcntl.h>
105
106 static int landlock_create_ruleset(const struct landlock_ruleset_attr *attr,
107 size_t size, uint32_t flags) {
108 return syscall(__NR_landlock_create_ruleset, attr, size, flags);
109 }
110
111 static int landlock_add_rule(int ruleset_fd, enum landlock_rule_type type,
112 const void *attr, uint32_t flags) {
113 return syscall(__NR_landlock_add_rule, ruleset_fd, type, attr, flags);
114 }
115
116 static int landlock_restrict_self(int ruleset_fd, __u32 flags) {
117 return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
118 }
119
120 int landlock_unveil(int landlock_fd, int fd, int perms) {
121 int ret, err;
122 struct landlock_path_beneath_attr attr = {0};
123 attr.allowed_access = perms;
124 attr.parent_fd = fd;
125
126 ret = landlock_add_rule(landlock_fd,
127 LANDLOCK_RULE_PATH_BENEATH, &attr, 0);
128 err = errno;
129 close(attr.parent_fd);
130 errno = err;
131 return ret;
132 }
133
134 int landlock_unveil_path(int landlock_fd, const char* path, int perms) {
135 int fd = open(path, 0);
136 if (fd < 0) return -1;
137 return landlock_unveil(landlock_fd, fd, perms);
138 }
139
140 int landlock_init() {
141 struct landlock_ruleset_attr attr = {0};
142 attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
143 LANDLOCK_ACCESS_FS_WRITE_FILE;
144 return landlock_create_ruleset(&attr, sizeof(attr), 0);
145 }
146
147 int landlock_apply(int fd) {
148 int ret = landlock_restrict_self(fd, 0);
149 int err = errno;
150 close(fd);
151 errno = err;
152 return ret;
153 }
154 #endif
155
156 int sandbox() {
157
158 struct sock_fprog prog = {0};
159 #ifdef ENABLE_LANDLOCK
160 int llfd, fail;
161 #endif
162
163 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
164 printf("PR_SET_NO_NEW_PRIVS failed\n");
165 return -1;
166 }
167 #ifdef ENABLE_LANDLOCK
168 llfd = landlock_init();
169 if (llfd < 0) {
170 printf("Failed to initialize landlock : %s\n",
171 strerror(errno));
172 printf("The filesystem won't be hidden from the program\n");
173 goto skip_landlock;
174 }
175 fail = 0;
176 fail |= landlock_unveil_path(llfd, conf.clients,
177 LANDLOCK_ACCESS_FS_READ_FILE |
178 LANDLOCK_ACCESS_FS_WRITE_FILE);
179 fail |= landlock_unveil_path(llfd, "/etc/resolv.conf",
180 LANDLOCK_ACCESS_FS_READ_FILE);
181 fail |= landlock_unveil_path(llfd, "/etc/hosts",
182 LANDLOCK_ACCESS_FS_READ_FILE);
183 if (fail) {
184 printf("landlock, failed to unveil : %s\n", strerror(errno));
185 return -1;
186 }
187 if (landlock_apply(llfd)) {
188 printf("landlock, failed to restrict process : %s\n",
189 strerror(errno));
190 return -1;
191 }
192 skip_landlock:;
193 #endif
194 prog.len = (unsigned short)(sizeof(filter) / sizeof (filter[0])),
195 prog.filter = filter;
196 if (0 && prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0)) {
197 printf("Failed to enable seccomp\n");
198 return -1;
199 }
200 return 0;
201 }
202
203 #else
204 typedef int hide_warning;
205 #endif
206