Blame


1 e29dbd72 2021-01-23 op /*
2 1a49166d 2021-01-23 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 e29dbd72 2021-01-23 op *
4 e29dbd72 2021-01-23 op * Permission to use, copy, modify, and distribute this software for any
5 e29dbd72 2021-01-23 op * purpose with or without fee is hereby granted, provided that the above
6 e29dbd72 2021-01-23 op * copyright notice and this permission notice appear in all copies.
7 e29dbd72 2021-01-23 op *
8 e29dbd72 2021-01-23 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 e29dbd72 2021-01-23 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 e29dbd72 2021-01-23 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 e29dbd72 2021-01-23 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 e29dbd72 2021-01-23 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 e29dbd72 2021-01-23 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 e29dbd72 2021-01-23 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 e29dbd72 2021-01-23 op */
16 e29dbd72 2021-01-23 op
17 dafb57b8 2021-01-15 op #include "gmid.h"
18 dafb57b8 2021-01-15 op
19 dafb57b8 2021-01-15 op #if defined(__FreeBSD__)
20 dafb57b8 2021-01-15 op
21 dafb57b8 2021-01-15 op #include <sys/capsicum.h>
22 dafb57b8 2021-01-15 op
23 dafb57b8 2021-01-15 op void
24 62e001b0 2021-03-20 op sandbox_server_process(void)
25 dafb57b8 2021-01-15 op {
26 dafb57b8 2021-01-15 op if (cap_enter() == -1)
27 8e56d6ad 2021-02-11 op fatal("cap_enter");
28 dafb57b8 2021-01-15 op }
29 dafb57b8 2021-01-15 op
30 62e001b0 2021-03-20 op void
31 62e001b0 2021-03-20 op sandbox_executor_process(void)
32 62e001b0 2021-03-20 op {
33 62e001b0 2021-03-20 op /* We cannot capsicum the executor process because it needs
34 62e001b0 2021-03-20 op * to fork(2)+execve(2) cgi scripts */
35 62e001b0 2021-03-20 op return;
36 62e001b0 2021-03-20 op }
37 62e001b0 2021-03-20 op
38 62e001b0 2021-03-20 op void
39 62e001b0 2021-03-20 op sandbox_logger_process(void)
40 62e001b0 2021-03-20 op {
41 62e001b0 2021-03-20 op if (cap_enter() == -1)
42 62e001b0 2021-03-20 op fatal("cap_enter");
43 62e001b0 2021-03-20 op }
44 62e001b0 2021-03-20 op
45 dafb57b8 2021-01-15 op #elif defined(__linux__)
46 dafb57b8 2021-01-15 op
47 71b7eb2f 2021-01-17 op #include <sys/prctl.h>
48 71b7eb2f 2021-01-17 op #include <sys/syscall.h>
49 71b7eb2f 2021-01-17 op #include <sys/syscall.h>
50 71b7eb2f 2021-01-17 op #include <sys/types.h>
51 71b7eb2f 2021-01-17 op
52 71b7eb2f 2021-01-17 op #include <linux/audit.h>
53 71b7eb2f 2021-01-17 op #include <linux/filter.h>
54 71b7eb2f 2021-01-17 op #include <linux/seccomp.h>
55 71b7eb2f 2021-01-17 op
56 71b7eb2f 2021-01-17 op #include <errno.h>
57 3c0375e4 2021-01-20 op #include <fcntl.h>
58 71b7eb2f 2021-01-17 op #include <stddef.h>
59 71b7eb2f 2021-01-17 op #include <stdio.h>
60 71b7eb2f 2021-01-17 op #include <string.h>
61 71b7eb2f 2021-01-17 op
62 71b7eb2f 2021-01-17 op /* thanks chromium' src/seccomp.c */
63 71b7eb2f 2021-01-17 op #if defined(__i386__)
64 71b7eb2f 2021-01-17 op # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386
65 71b7eb2f 2021-01-17 op #elif defined(__x86_64__)
66 71b7eb2f 2021-01-17 op # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64
67 71b7eb2f 2021-01-17 op #elif defined(__arm__)
68 71b7eb2f 2021-01-17 op # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM
69 71b7eb2f 2021-01-17 op #elif defined(__aarch64__)
70 71b7eb2f 2021-01-17 op # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64
71 71b7eb2f 2021-01-17 op #elif defined(__mips__)
72 71b7eb2f 2021-01-17 op # if defined(__mips64)
73 71b7eb2f 2021-01-17 op # if defined(__MIPSEB__)
74 71b7eb2f 2021-01-17 op # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64
75 71b7eb2f 2021-01-17 op # else
76 71b7eb2f 2021-01-17 op # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64
77 71b7eb2f 2021-01-17 op # endif
78 71b7eb2f 2021-01-17 op # else
79 71b7eb2f 2021-01-17 op # if defined(__MIPSEB__)
80 71b7eb2f 2021-01-17 op # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS
81 71b7eb2f 2021-01-17 op # else
82 71b7eb2f 2021-01-17 op # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL
83 71b7eb2f 2021-01-17 op # endif
84 71b7eb2f 2021-01-17 op # endif
85 71b7eb2f 2021-01-17 op #else
86 71b7eb2f 2021-01-17 op # error "Platform does not support seccomp filter yet"
87 71b7eb2f 2021-01-17 op #endif
88 71b7eb2f 2021-01-17 op
89 71b7eb2f 2021-01-17 op /* uncomment to enable debugging. ONLY FOR DEVELOPMENT */
90 71b7eb2f 2021-01-17 op /* #define SC_DEBUG */
91 71b7eb2f 2021-01-17 op
92 71b7eb2f 2021-01-17 op #ifdef SC_DEBUG
93 71b7eb2f 2021-01-17 op # define SC_FAIL SECCOMP_RET_TRAP
94 71b7eb2f 2021-01-17 op #else
95 71b7eb2f 2021-01-17 op # define SC_FAIL SECCOMP_RET_KILL
96 71b7eb2f 2021-01-17 op #endif
97 71b7eb2f 2021-01-17 op
98 71b7eb2f 2021-01-17 op /* make the filter more readable */
99 71b7eb2f 2021-01-17 op #define SC_ALLOW(nr) \
100 71b7eb2f 2021-01-17 op BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_##nr, 0, 1), \
101 71b7eb2f 2021-01-17 op BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
102 71b7eb2f 2021-01-17 op
103 71b7eb2f 2021-01-17 op #ifdef SC_DEBUG
104 71b7eb2f 2021-01-17 op
105 71b7eb2f 2021-01-17 op #include <signal.h>
106 71b7eb2f 2021-01-17 op #include <unistd.h>
107 71b7eb2f 2021-01-17 op
108 71b7eb2f 2021-01-17 op static void
109 71b7eb2f 2021-01-17 op sandbox_seccomp_violation(int signum, siginfo_t *info, void *ctx)
110 71b7eb2f 2021-01-17 op {
111 71b7eb2f 2021-01-17 op (void)signum;
112 71b7eb2f 2021-01-17 op (void)ctx;
113 71b7eb2f 2021-01-17 op
114 71b7eb2f 2021-01-17 op fprintf(stderr, "%s: unexpected system call (arch:0x%x,syscall:%d @ %p)\n",
115 71b7eb2f 2021-01-17 op __func__, info->si_arch, info->si_syscall, info->si_call_addr);
116 71b7eb2f 2021-01-17 op _exit(1);
117 71b7eb2f 2021-01-17 op }
118 71b7eb2f 2021-01-17 op
119 71b7eb2f 2021-01-17 op static void
120 71b7eb2f 2021-01-17 op sandbox_seccomp_catch_sigsys(void)
121 71b7eb2f 2021-01-17 op {
122 71b7eb2f 2021-01-17 op struct sigaction act;
123 71b7eb2f 2021-01-17 op sigset_t mask;
124 71b7eb2f 2021-01-17 op
125 71b7eb2f 2021-01-17 op memset(&act, 0, sizeof(act));
126 71b7eb2f 2021-01-17 op sigemptyset(&mask);
127 71b7eb2f 2021-01-17 op sigaddset(&mask, SIGSYS);
128 71b7eb2f 2021-01-17 op
129 71b7eb2f 2021-01-17 op act.sa_sigaction = &sandbox_seccomp_violation;
130 71b7eb2f 2021-01-17 op act.sa_flags = SA_SIGINFO;
131 8e56d6ad 2021-02-11 op if (sigaction(SIGSYS, &act, NULL) == -1)
132 8e56d6ad 2021-02-11 op fatal("%s: sigaction(SIGSYS): %s",
133 71b7eb2f 2021-01-17 op __func__, strerror(errno));
134 8e56d6ad 2021-02-11 op
135 8e56d6ad 2021-02-11 op if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
136 8e56d6ad 2021-02-11 op fatal("%s: sigprocmask(SIGSYS): %s\n",
137 71b7eb2f 2021-01-17 op __func__, strerror(errno));
138 71b7eb2f 2021-01-17 op }
139 71b7eb2f 2021-01-17 op #endif /* SC_DEBUG */
140 71b7eb2f 2021-01-17 op
141 dafb57b8 2021-01-15 op void
142 62e001b0 2021-03-20 op sandbox_server_process(void)
143 dafb57b8 2021-01-15 op {
144 71b7eb2f 2021-01-17 op struct sock_filter filter[] = {
145 71b7eb2f 2021-01-17 op /* load the *current* architecture */
146 71b7eb2f 2021-01-17 op BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
147 71b7eb2f 2021-01-17 op (offsetof(struct seccomp_data, arch))),
148 71b7eb2f 2021-01-17 op /* ensure it's the same that we've been compiled on */
149 71b7eb2f 2021-01-17 op BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,
150 71b7eb2f 2021-01-17 op SECCOMP_AUDIT_ARCH, 1, 0),
151 71b7eb2f 2021-01-17 op /* if not, kill the program */
152 71b7eb2f 2021-01-17 op BPF_STMT(BPF_RET | BPF_K, SC_FAIL),
153 71b7eb2f 2021-01-17 op
154 71b7eb2f 2021-01-17 op /* load the syscall number */
155 71b7eb2f 2021-01-17 op BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
156 71b7eb2f 2021-01-17 op (offsetof(struct seccomp_data, nr))),
157 71b7eb2f 2021-01-17 op
158 71b7eb2f 2021-01-17 op /* allow logging on stdout */
159 71b7eb2f 2021-01-17 op SC_ALLOW(write),
160 71b7eb2f 2021-01-17 op SC_ALLOW(writev),
161 71b7eb2f 2021-01-17 op SC_ALLOW(readv),
162 71b7eb2f 2021-01-17 op
163 71b7eb2f 2021-01-17 op /* these are used to serve the files. note how we
164 71b7eb2f 2021-01-17 op * allow openat but not open. */
165 4c857c0a 2021-02-10 op #ifdef __NR_epoll_wait
166 4c857c0a 2021-02-10 op /* epoll_wait(2) isn't present on aarch64, at least */
167 f6b9a079 2021-02-10 op SC_ALLOW(epoll_wait),
168 4c857c0a 2021-02-10 op #endif
169 df58efff 2021-02-08 op SC_ALLOW(epoll_pwait),
170 df58efff 2021-02-08 op SC_ALLOW(epoll_ctl),
171 3cb3dd4d 2021-02-12 op SC_ALLOW(accept),
172 df58efff 2021-02-08 op SC_ALLOW(accept4),
173 71b7eb2f 2021-01-17 op SC_ALLOW(read),
174 71b7eb2f 2021-01-17 op SC_ALLOW(openat),
175 71b7eb2f 2021-01-17 op SC_ALLOW(fstat),
176 6827d278 2021-02-10 op SC_ALLOW(newfstatat),
177 71b7eb2f 2021-01-17 op SC_ALLOW(close),
178 71b7eb2f 2021-01-17 op SC_ALLOW(lseek),
179 71b7eb2f 2021-01-17 op SC_ALLOW(brk),
180 71b7eb2f 2021-01-17 op SC_ALLOW(mmap),
181 71b7eb2f 2021-01-17 op SC_ALLOW(munmap),
182 c214d1ab 2021-02-08 op
183 9899a837 2021-02-23 op /* for imsg */
184 9899a837 2021-02-23 op SC_ALLOW(sendmsg),
185 e3d81f49 2021-03-20 op SC_ALLOW(prlimit64),
186 9899a837 2021-02-23 op
187 c214d1ab 2021-02-08 op /* needed for signal handling */
188 c214d1ab 2021-02-08 op SC_ALLOW(rt_sigreturn),
189 c214d1ab 2021-02-08 op SC_ALLOW(rt_sigaction),
190 71b7eb2f 2021-01-17 op
191 71b7eb2f 2021-01-17 op /* we need recvmsg to receive fd */
192 71b7eb2f 2021-01-17 op SC_ALLOW(recvmsg),
193 71b7eb2f 2021-01-17 op
194 71b7eb2f 2021-01-17 op /* XXX: ??? */
195 71b7eb2f 2021-01-17 op SC_ALLOW(getpid),
196 71b7eb2f 2021-01-17 op
197 df58efff 2021-02-08 op /* alpine on amd64 */
198 f2b3a519 2021-01-20 op SC_ALLOW(clock_gettime),
199 df58efff 2021-02-08 op SC_ALLOW(madvise),
200 f2b3a519 2021-01-20 op
201 2d3f837a 2021-01-25 op /* void on aarch64 does a gettrandom */
202 2d3f837a 2021-01-25 op SC_ALLOW(getrandom),
203 6827d278 2021-02-10 op
204 6827d278 2021-02-10 op /* arch on amd64 */
205 6827d278 2021-02-10 op SC_ALLOW(gettimeofday),
206 2d3f837a 2021-01-25 op
207 f88311e5 2021-01-24 op /* for directory listing */
208 f88311e5 2021-01-24 op SC_ALLOW(getdents64),
209 f88311e5 2021-01-24 op
210 71b7eb2f 2021-01-17 op SC_ALLOW(exit),
211 71b7eb2f 2021-01-17 op SC_ALLOW(exit_group),
212 df58efff 2021-02-08 op
213 c214d1ab 2021-02-08 op /* allow only F_GETFL, F_SETFL & F_SETFD fcntl */
214 f88311e5 2021-01-24 op BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_fcntl, 0, 8),
215 de4f7131 2021-01-20 op BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
216 3c0375e4 2021-01-20 op (offsetof(struct seccomp_data, args[1]))),
217 3c0375e4 2021-01-20 op BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, F_GETFL, 0, 1),
218 3c0375e4 2021-01-20 op BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
219 3c0375e4 2021-01-20 op BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, F_SETFL, 0, 1),
220 3c0375e4 2021-01-20 op BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
221 f88311e5 2021-01-24 op BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, F_SETFD, 0, 1),
222 f88311e5 2021-01-24 op BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
223 3c0375e4 2021-01-20 op BPF_STMT(BPF_RET | BPF_K, SC_FAIL),
224 61f8d630 2021-01-20 op
225 f2b3a519 2021-01-20 op /* re-load the syscall number */
226 de4f7131 2021-01-20 op BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
227 de4f7131 2021-01-20 op (offsetof(struct seccomp_data, nr))),
228 de4f7131 2021-01-20 op
229 71b7eb2f 2021-01-17 op /* allow ioctl but only on fd 1, glibc doing stuff? */
230 71b7eb2f 2021-01-17 op BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_ioctl, 0, 3),
231 71b7eb2f 2021-01-17 op BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
232 71b7eb2f 2021-01-17 op (offsetof(struct seccomp_data, args[0]))),
233 71b7eb2f 2021-01-17 op BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 0, 1),
234 71b7eb2f 2021-01-17 op BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
235 71b7eb2f 2021-01-17 op
236 71b7eb2f 2021-01-17 op /* disallow enything else */
237 71b7eb2f 2021-01-17 op BPF_STMT(BPF_RET | BPF_K, SC_FAIL),
238 71b7eb2f 2021-01-17 op };
239 71b7eb2f 2021-01-17 op
240 71b7eb2f 2021-01-17 op struct sock_fprog prog = {
241 71b7eb2f 2021-01-17 op .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
242 71b7eb2f 2021-01-17 op .filter = filter,
243 71b7eb2f 2021-01-17 op };
244 71b7eb2f 2021-01-17 op
245 71b7eb2f 2021-01-17 op #ifdef SC_DEBUG
246 71b7eb2f 2021-01-17 op sandbox_seccomp_catch_sigsys();
247 71b7eb2f 2021-01-17 op #endif
248 71b7eb2f 2021-01-17 op
249 8e56d6ad 2021-02-11 op if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
250 8e56d6ad 2021-02-11 op fatal("%s: prctl(PR_SET_NO_NEW_PRIVS): %s",
251 71b7eb2f 2021-01-17 op __func__, strerror(errno));
252 71b7eb2f 2021-01-17 op
253 8e56d6ad 2021-02-11 op if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) == -1)
254 8e56d6ad 2021-02-11 op fatal("%s: prctl(PR_SET_SECCOMP): %s\n",
255 71b7eb2f 2021-01-17 op __func__, strerror(errno));
256 dafb57b8 2021-01-15 op }
257 dafb57b8 2021-01-15 op
258 62e001b0 2021-03-20 op void
259 62e001b0 2021-03-20 op sandbox_executor_process(void)
260 62e001b0 2021-03-20 op {
261 62e001b0 2021-03-20 op /* We cannot use seccomp for the executor process because we
262 62e001b0 2021-03-20 op * don't know what the child will do. Also, our filter will
263 62e001b0 2021-03-20 op * be inherited so the child cannot set its own seccomp
264 62e001b0 2021-03-20 op * policy. */
265 62e001b0 2021-03-20 op return;
266 62e001b0 2021-03-20 op }
267 62e001b0 2021-03-20 op
268 62e001b0 2021-03-20 op void
269 62e001b0 2021-03-20 op sandbox_logger_process(void)
270 62e001b0 2021-03-20 op {
271 62e001b0 2021-03-20 op /* To be honest, here we could use a seccomp policy to only
272 62e001b0 2021-03-20 op * allow writev(2) and memory allocations. */
273 62e001b0 2021-03-20 op return;
274 62e001b0 2021-03-20 op }
275 62e001b0 2021-03-20 op
276 dafb57b8 2021-01-15 op #elif defined(__OpenBSD__)
277 dafb57b8 2021-01-15 op
278 dafb57b8 2021-01-15 op #include <unistd.h>
279 dafb57b8 2021-01-15 op
280 dafb57b8 2021-01-15 op void
281 62e001b0 2021-03-20 op sandbox_server_process(void)
282 dafb57b8 2021-01-15 op {
283 dafb57b8 2021-01-15 op struct vhost *h;
284 dafb57b8 2021-01-15 op
285 b8e64ccd 2021-03-31 op TAILQ_FOREACH(h, &hosts, vhosts) {
286 2d3cc76f 2021-01-25 op if (unveil(h->dir, "r") == -1)
287 8e56d6ad 2021-02-11 op fatal("unveil %s for domain %s", h->dir, h->domain);
288 dafb57b8 2021-01-15 op }
289 dafb57b8 2021-01-15 op
290 881a9dd9 2021-01-16 op if (pledge("stdio recvfd rpath inet", NULL) == -1)
291 8e56d6ad 2021-02-11 op fatal("pledge");
292 dafb57b8 2021-01-15 op }
293 dafb57b8 2021-01-15 op
294 dafb57b8 2021-01-15 op void
295 62e001b0 2021-03-20 op sandbox_executor_process(void)
296 dafb57b8 2021-01-15 op {
297 b8e64ccd 2021-03-31 op struct vhost *h;
298 62e001b0 2021-03-20 op
299 b8e64ccd 2021-03-31 op TAILQ_FOREACH(h, &hosts, vhosts) {
300 62e001b0 2021-03-20 op /* r so we can chdir into the correct directory */
301 b8e64ccd 2021-03-31 op if (unveil(h->dir, "rx") == -1)
302 62e001b0 2021-03-20 op err(1, "unveil %s for domain %s",
303 b8e64ccd 2021-03-31 op h->dir, h->domain);
304 62e001b0 2021-03-20 op }
305 62e001b0 2021-03-20 op
306 62e001b0 2021-03-20 op /* rpath to chdir into the correct directory */
307 62e001b0 2021-03-20 op if (pledge("stdio rpath sendfd proc exec", NULL))
308 62e001b0 2021-03-20 op err(1, "pledge");
309 62e001b0 2021-03-20 op }
310 62e001b0 2021-03-20 op
311 62e001b0 2021-03-20 op void
312 62e001b0 2021-03-20 op sandbox_logger_process(void)
313 62e001b0 2021-03-20 op {
314 62e001b0 2021-03-20 op if (pledge("stdio", NULL) == -1)
315 62e001b0 2021-03-20 op err(1, "pledge");
316 62e001b0 2021-03-20 op }
317 62e001b0 2021-03-20 op
318 62e001b0 2021-03-20 op #else
319 62e001b0 2021-03-20 op
320 62e001b0 2021-03-20 op #warning "No sandbox method known for this OS"
321 62e001b0 2021-03-20 op
322 62e001b0 2021-03-20 op void
323 62e001b0 2021-03-20 op sandbox_server_process(void)
324 62e001b0 2021-03-20 op {
325 62e001b0 2021-03-20 op return;
326 62e001b0 2021-03-20 op }
327 62e001b0 2021-03-20 op
328 62e001b0 2021-03-20 op void
329 62e001b0 2021-03-20 op sandbox_executor_process(void)
330 62e001b0 2021-03-20 op {
331 2a911637 2021-02-11 op log_notice(NULL, "no sandbox method known for this OS");
332 dafb57b8 2021-01-15 op }
333 dafb57b8 2021-01-15 op
334 62e001b0 2021-03-20 op void
335 62e001b0 2021-03-20 op sandbox_logger_process(void)
336 62e001b0 2021-03-20 op {
337 62e001b0 2021-03-20 op return;
338 62e001b0 2021-03-20 op }
339 62e001b0 2021-03-20 op
340 dafb57b8 2021-01-15 op #endif