File: | kern/kern_pledge.c |
Warning: | line 1268, column 15 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: kern_pledge.c,v 1.310 2023/12/12 17:43:10 deraadt Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> | |||
5 | * Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org> | |||
6 | * | |||
7 | * Permission to use, copy, modify, and distribute this software for any | |||
8 | * purpose with or without fee is hereby granted, provided that the above | |||
9 | * copyright notice and this permission notice appear in all copies. | |||
10 | * | |||
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
18 | */ | |||
19 | ||||
20 | #include <sys/param.h> | |||
21 | #include <sys/mount.h> | |||
22 | #include <sys/proc.h> | |||
23 | #include <sys/mutex.h> | |||
24 | #include <sys/fcntl.h> | |||
25 | #include <sys/file.h> | |||
26 | #include <sys/namei.h> | |||
27 | #include <sys/socketvar.h> | |||
28 | #include <sys/vnode.h> | |||
29 | #include <sys/mman.h> | |||
30 | #include <sys/sysctl.h> | |||
31 | #include <sys/syslog.h> | |||
32 | #include <sys/ktrace.h> | |||
33 | #include <sys/acct.h> | |||
34 | #include <sys/swap.h> | |||
35 | ||||
36 | #include <sys/ioctl.h> | |||
37 | #include <sys/termios.h> | |||
38 | #include <sys/tty.h> | |||
39 | #include <sys/device.h> | |||
40 | #include <sys/disklabel.h> | |||
41 | #include <sys/dkio.h> | |||
42 | #include <sys/mtio.h> | |||
43 | #include <sys/audioio.h> | |||
44 | #include <sys/videoio.h> | |||
45 | #include <net/bpf.h> | |||
46 | #include <net/route.h> | |||
47 | #include <net/if.h> | |||
48 | #include <net/if_var.h> | |||
49 | #include <netinet/in.h> | |||
50 | #include <netinet6/in6_var.h> | |||
51 | #include <netinet6/nd6.h> | |||
52 | #include <netinet/tcp.h> | |||
53 | #include <net/pfvar.h> | |||
54 | ||||
55 | #include <sys/conf.h> | |||
56 | #include <sys/specdev.h> | |||
57 | #include <sys/signal.h> | |||
58 | #include <sys/signalvar.h> | |||
59 | #include <sys/syscall.h> | |||
60 | #include <sys/syscallargs.h> | |||
61 | #include <sys/systm.h> | |||
62 | ||||
63 | #include <dev/biovar.h> | |||
64 | ||||
65 | #define PLEDGENAMES | |||
66 | #include <sys/pledge.h> | |||
67 | ||||
68 | #include "audio.h" | |||
69 | #include "bpfilter.h" | |||
70 | #include "pf.h" | |||
71 | #include "video.h" | |||
72 | #include "pty.h" | |||
73 | ||||
74 | #if defined(__amd64__1) | |||
75 | #include "vmm.h" | |||
76 | #if NVMM1 > 0 | |||
77 | #include <machine/conf.h> | |||
78 | #endif | |||
79 | #endif | |||
80 | ||||
81 | #include "drm.h" | |||
82 | ||||
83 | uint64_t pledgereq_flags(const char *req); | |||
84 | int parsepledges(struct proc *p, const char *kname, | |||
85 | const char *promises, u_int64_t *fp); | |||
86 | int canonpath(const char *input, char *buf, size_t bufsize); | |||
87 | void unveil_destroy(struct process *ps); | |||
88 | ||||
89 | /* #define DEBUG_PLEDGE */ | |||
90 | #ifdef DEBUG_PLEDGE | |||
91 | int debug_pledge = 1; | |||
92 | #define DPRINTF(x...) do { if (debug_pledge) printf(x); } while (0) | |||
93 | #define DNPRINTF(n,x...) do { if (debug_pledge >= (n)) printf(x); } while (0) | |||
94 | #else | |||
95 | #define DPRINTF(x...) | |||
96 | #define DNPRINTF(n,x...) | |||
97 | #endif | |||
98 | ||||
99 | /* | |||
100 | * Ordered in blocks starting with least risky and most required. | |||
101 | */ | |||
102 | const uint64_t pledge_syscalls[SYS_MAXSYSCALL331] = { | |||
103 | /* | |||
104 | * Minimum required | |||
105 | */ | |||
106 | [SYS_exit1] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
107 | [SYS_kbind86] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
108 | [SYS_msyscall37] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
109 | [SYS___get_tcb330] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
110 | [SYS___set_tcb329] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
111 | [SYS_pledge108] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
112 | [SYS_sendsyslog112] = PLEDGE_ALWAYS0xffffffffffffffffULL, /* stack protector reporting */ | |||
113 | [SYS_thrkill119] = PLEDGE_ALWAYS0xffffffffffffffffULL, /* raise, abort, stack pro */ | |||
114 | [SYS_utrace209] = PLEDGE_ALWAYS0xffffffffffffffffULL, /* ltrace(1) from ld.so */ | |||
115 | [SYS_pinsyscall146] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
116 | [SYS_pinsyscalls158] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
117 | ||||
118 | /* "getting" information about self is considered safe */ | |||
119 | [SYS_getuid24] = PLEDGE_STDIO0x0000000000000008ULL, | |||
120 | [SYS_geteuid25] = PLEDGE_STDIO0x0000000000000008ULL, | |||
121 | [SYS_getresuid281] = PLEDGE_STDIO0x0000000000000008ULL, | |||
122 | [SYS_getgid47] = PLEDGE_STDIO0x0000000000000008ULL, | |||
123 | [SYS_getegid43] = PLEDGE_STDIO0x0000000000000008ULL, | |||
124 | [SYS_getresgid283] = PLEDGE_STDIO0x0000000000000008ULL, | |||
125 | [SYS_getgroups79] = PLEDGE_STDIO0x0000000000000008ULL, | |||
126 | [SYS_getlogin_r141] = PLEDGE_STDIO0x0000000000000008ULL, | |||
127 | [SYS_getpgrp81] = PLEDGE_STDIO0x0000000000000008ULL, | |||
128 | [SYS_getpgid207] = PLEDGE_STDIO0x0000000000000008ULL, | |||
129 | [SYS_getppid39] = PLEDGE_STDIO0x0000000000000008ULL, | |||
130 | [SYS_getsid255] = PLEDGE_STDIO0x0000000000000008ULL, | |||
131 | [SYS_getthrid299] = PLEDGE_STDIO0x0000000000000008ULL, | |||
132 | [SYS_getrlimit194] = PLEDGE_STDIO0x0000000000000008ULL, | |||
133 | [SYS_getrtable311] = PLEDGE_STDIO0x0000000000000008ULL, | |||
134 | [SYS_gettimeofday67] = PLEDGE_STDIO0x0000000000000008ULL, | |||
135 | [SYS_getdtablecount18] = PLEDGE_STDIO0x0000000000000008ULL, | |||
136 | [SYS_getrusage19] = PLEDGE_STDIO0x0000000000000008ULL, | |||
137 | [SYS_issetugid253] = PLEDGE_STDIO0x0000000000000008ULL, | |||
138 | [SYS_clock_getres89] = PLEDGE_STDIO0x0000000000000008ULL, | |||
139 | [SYS_clock_gettime87] = PLEDGE_STDIO0x0000000000000008ULL, | |||
140 | [SYS_getpid20] = PLEDGE_STDIO0x0000000000000008ULL, | |||
141 | ||||
142 | /* | |||
143 | * Almost exclusively read-only, Very narrow subset. | |||
144 | * Use of "route", "inet", "dns", "ps", or "vminfo" | |||
145 | * expands access. | |||
146 | */ | |||
147 | [SYS_sysctl202] = PLEDGE_STDIO0x0000000000000008ULL, | |||
148 | ||||
149 | /* For moncontrol(3). Only allowed to disable profiling. */ | |||
150 | [SYS_profil44] = PLEDGE_STDIO0x0000000000000008ULL, | |||
151 | ||||
152 | /* Support for malloc(3) family of operations */ | |||
153 | [SYS_getentropy7] = PLEDGE_STDIO0x0000000000000008ULL, | |||
154 | [SYS_madvise75] = PLEDGE_STDIO0x0000000000000008ULL, | |||
155 | [SYS_minherit250] = PLEDGE_STDIO0x0000000000000008ULL, | |||
156 | [SYS_mmap49] = PLEDGE_STDIO0x0000000000000008ULL, | |||
157 | [SYS_mprotect74] = PLEDGE_STDIO0x0000000000000008ULL, | |||
158 | [SYS_mimmutable159] = PLEDGE_STDIO0x0000000000000008ULL, | |||
159 | [SYS_mquery78] = PLEDGE_STDIO0x0000000000000008ULL, | |||
160 | [SYS_munmap73] = PLEDGE_STDIO0x0000000000000008ULL, | |||
161 | [SYS_msync256] = PLEDGE_STDIO0x0000000000000008ULL, | |||
162 | [SYS_break17] = PLEDGE_STDIO0x0000000000000008ULL, | |||
163 | ||||
164 | [SYS_umask60] = PLEDGE_STDIO0x0000000000000008ULL, | |||
165 | ||||
166 | /* read/write operations */ | |||
167 | [SYS_read3] = PLEDGE_STDIO0x0000000000000008ULL, | |||
168 | [SYS_readv120] = PLEDGE_STDIO0x0000000000000008ULL, | |||
169 | [SYS_pread169] = PLEDGE_STDIO0x0000000000000008ULL, | |||
170 | [SYS_preadv171] = PLEDGE_STDIO0x0000000000000008ULL, | |||
171 | [SYS_write4] = PLEDGE_STDIO0x0000000000000008ULL, | |||
172 | [SYS_writev121] = PLEDGE_STDIO0x0000000000000008ULL, | |||
173 | [SYS_pwrite170] = PLEDGE_STDIO0x0000000000000008ULL, | |||
174 | [SYS_pwritev172] = PLEDGE_STDIO0x0000000000000008ULL, | |||
175 | [SYS_recvmsg27] = PLEDGE_STDIO0x0000000000000008ULL, | |||
176 | [SYS_recvmmsg116] = PLEDGE_STDIO0x0000000000000008ULL, | |||
177 | [SYS_recvfrom29] = PLEDGE_STDIO0x0000000000000008ULL, | |||
178 | [SYS_ftruncate168] = PLEDGE_STDIO0x0000000000000008ULL, | |||
179 | [SYS_lseek166] = PLEDGE_STDIO0x0000000000000008ULL, | |||
180 | [SYS_fpathconf192] = PLEDGE_STDIO0x0000000000000008ULL, | |||
181 | ||||
182 | /* | |||
183 | * Address selection required a network pledge ("inet", | |||
184 | * "unix", "dns". | |||
185 | */ | |||
186 | [SYS_sendto133] = PLEDGE_STDIO0x0000000000000008ULL, | |||
187 | ||||
188 | /* | |||
189 | * Address specification required a network pledge ("inet", | |||
190 | * "unix", "dns". SCM_RIGHTS requires "sendfd" or "recvfd". | |||
191 | */ | |||
192 | [SYS_sendmsg28] = PLEDGE_STDIO0x0000000000000008ULL, | |||
193 | [SYS_sendmmsg117] = PLEDGE_STDIO0x0000000000000008ULL, | |||
194 | ||||
195 | /* Common signal operations */ | |||
196 | [SYS_nanosleep91] = PLEDGE_STDIO0x0000000000000008ULL, | |||
197 | [SYS_sigaltstack288] = PLEDGE_STDIO0x0000000000000008ULL, | |||
198 | [SYS_sigprocmask48] = PLEDGE_STDIO0x0000000000000008ULL, | |||
199 | [SYS_sigsuspend111] = PLEDGE_STDIO0x0000000000000008ULL, | |||
200 | [SYS_sigaction46] = PLEDGE_STDIO0x0000000000000008ULL, | |||
201 | [SYS_sigreturn103] = PLEDGE_STDIO0x0000000000000008ULL, | |||
202 | [SYS_sigpending52] = PLEDGE_STDIO0x0000000000000008ULL, | |||
203 | [SYS_getitimer70] = PLEDGE_STDIO0x0000000000000008ULL, | |||
204 | [SYS_setitimer69] = PLEDGE_STDIO0x0000000000000008ULL, | |||
205 | ||||
206 | /* | |||
207 | * To support event driven programming. | |||
208 | */ | |||
209 | [SYS_poll252] = PLEDGE_STDIO0x0000000000000008ULL, | |||
210 | [SYS_ppoll109] = PLEDGE_STDIO0x0000000000000008ULL, | |||
211 | [SYS_kevent72] = PLEDGE_STDIO0x0000000000000008ULL, | |||
212 | [SYS_kqueue269] = PLEDGE_STDIO0x0000000000000008ULL, | |||
213 | [SYS_kqueue1270] = PLEDGE_STDIO0x0000000000000008ULL, | |||
214 | [SYS_select71] = PLEDGE_STDIO0x0000000000000008ULL, | |||
215 | [SYS_pselect110] = PLEDGE_STDIO0x0000000000000008ULL, | |||
216 | ||||
217 | [SYS_fstat53] = PLEDGE_STDIO0x0000000000000008ULL, | |||
218 | [SYS_fsync95] = PLEDGE_STDIO0x0000000000000008ULL, | |||
219 | ||||
220 | [SYS_setsockopt105] = PLEDGE_STDIO0x0000000000000008ULL, /* narrow whitelist */ | |||
221 | [SYS_getsockopt118] = PLEDGE_STDIO0x0000000000000008ULL, /* narrow whitelist */ | |||
222 | ||||
223 | /* F_SETOWN requires PLEDGE_PROC */ | |||
224 | [SYS_fcntl92] = PLEDGE_STDIO0x0000000000000008ULL, | |||
225 | ||||
226 | [SYS_close6] = PLEDGE_STDIO0x0000000000000008ULL, | |||
227 | [SYS_dup41] = PLEDGE_STDIO0x0000000000000008ULL, | |||
228 | [SYS_dup290] = PLEDGE_STDIO0x0000000000000008ULL, | |||
229 | [SYS_dup3102] = PLEDGE_STDIO0x0000000000000008ULL, | |||
230 | [SYS_closefrom287] = PLEDGE_STDIO0x0000000000000008ULL, | |||
231 | [SYS_shutdown134] = PLEDGE_STDIO0x0000000000000008ULL, | |||
232 | [SYS_fchdir13] = PLEDGE_STDIO0x0000000000000008ULL, /* XXX consider tightening */ | |||
233 | ||||
234 | [SYS_pipe263] = PLEDGE_STDIO0x0000000000000008ULL, | |||
235 | [SYS_pipe2101] = PLEDGE_STDIO0x0000000000000008ULL, | |||
236 | [SYS_socketpair135] = PLEDGE_STDIO0x0000000000000008ULL, | |||
237 | ||||
238 | [SYS_wait411] = PLEDGE_STDIO0x0000000000000008ULL, | |||
239 | [SYS_waitid160] = PLEDGE_STDIO0x0000000000000008ULL, | |||
240 | ||||
241 | /* | |||
242 | * Can kill self with "stdio". Killing another pid | |||
243 | * requires "proc" | |||
244 | */ | |||
245 | [SYS_kill122] = PLEDGE_STDIO0x0000000000000008ULL, | |||
246 | ||||
247 | /* | |||
248 | * FIONREAD/FIONBIO for "stdio" | |||
249 | * Other ioctl are selectively allowed based upon other pledges. | |||
250 | */ | |||
251 | [SYS_ioctl54] = PLEDGE_STDIO0x0000000000000008ULL, | |||
252 | ||||
253 | /* | |||
254 | * Path access/creation calls encounter many extensive | |||
255 | * checks done during pledge_namei() | |||
256 | */ | |||
257 | [SYS_open5] = PLEDGE_STDIO0x0000000000000008ULL, | |||
258 | [SYS_stat38] = PLEDGE_STDIO0x0000000000000008ULL, | |||
259 | [SYS_access33] = PLEDGE_STDIO0x0000000000000008ULL, | |||
260 | [SYS_readlink58] = PLEDGE_STDIO0x0000000000000008ULL, | |||
261 | [SYS___realpath115] = PLEDGE_STDIO0x0000000000000008ULL, | |||
262 | ||||
263 | [SYS_adjtime140] = PLEDGE_STDIO0x0000000000000008ULL, /* setting requires "settime" */ | |||
264 | [SYS_adjfreq305] = PLEDGE_SETTIME0x0000000000002000ULL, | |||
265 | [SYS_settimeofday68] = PLEDGE_SETTIME0x0000000000002000ULL, | |||
266 | ||||
267 | /* | |||
268 | * Needed by threaded programs | |||
269 | * XXX should we have a new "threads"? | |||
270 | */ | |||
271 | [SYS___tfork8] = PLEDGE_STDIO0x0000000000000008ULL, | |||
272 | [SYS_sched_yield298] = PLEDGE_STDIO0x0000000000000008ULL, | |||
273 | [SYS_futex83] = PLEDGE_STDIO0x0000000000000008ULL, | |||
274 | [SYS___thrsleep94] = PLEDGE_STDIO0x0000000000000008ULL, | |||
275 | [SYS___thrwakeup301] = PLEDGE_STDIO0x0000000000000008ULL, | |||
276 | [SYS___threxit302] = PLEDGE_STDIO0x0000000000000008ULL, | |||
277 | [SYS___thrsigdivert303] = PLEDGE_STDIO0x0000000000000008ULL, | |||
278 | [SYS_getthrname142] = PLEDGE_STDIO0x0000000000000008ULL, | |||
279 | [SYS_setthrname143] = PLEDGE_STDIO0x0000000000000008ULL, | |||
280 | ||||
281 | [SYS_fork2] = PLEDGE_PROC0x0000000000001000ULL, | |||
282 | [SYS_vfork66] = PLEDGE_PROC0x0000000000001000ULL, | |||
283 | [SYS_setpgid82] = PLEDGE_PROC0x0000000000001000ULL, | |||
284 | [SYS_setsid147] = PLEDGE_PROC0x0000000000001000ULL, | |||
285 | ||||
286 | [SYS_setrlimit195] = PLEDGE_PROC0x0000000000001000ULL | PLEDGE_ID0x0000000000000200ULL, | |||
287 | [SYS_getpriority100] = PLEDGE_PROC0x0000000000001000ULL | PLEDGE_ID0x0000000000000200ULL, | |||
288 | ||||
289 | [SYS_setpriority96] = PLEDGE_PROC0x0000000000001000ULL | PLEDGE_ID0x0000000000000200ULL, | |||
290 | ||||
291 | [SYS_setuid23] = PLEDGE_ID0x0000000000000200ULL, | |||
292 | [SYS_seteuid183] = PLEDGE_ID0x0000000000000200ULL, | |||
293 | [SYS_setreuid126] = PLEDGE_ID0x0000000000000200ULL, | |||
294 | [SYS_setresuid282] = PLEDGE_ID0x0000000000000200ULL, | |||
295 | [SYS_setgid181] = PLEDGE_ID0x0000000000000200ULL, | |||
296 | [SYS_setegid182] = PLEDGE_ID0x0000000000000200ULL, | |||
297 | [SYS_setregid127] = PLEDGE_ID0x0000000000000200ULL, | |||
298 | [SYS_setresgid284] = PLEDGE_ID0x0000000000000200ULL, | |||
299 | [SYS_setgroups80] = PLEDGE_ID0x0000000000000200ULL, | |||
300 | [SYS_setlogin50] = PLEDGE_ID0x0000000000000200ULL, | |||
301 | [SYS_setrtable310] = PLEDGE_ID0x0000000000000200ULL, | |||
302 | ||||
303 | [SYS_unveil114] = PLEDGE_UNVEIL0x0000001000000000ULL, | |||
304 | ||||
305 | [SYS_execve59] = PLEDGE_EXEC0x0000000000080000ULL, | |||
306 | ||||
307 | [SYS_chdir12] = PLEDGE_RPATH0x0000000000000001ULL, | |||
308 | [SYS_openat321] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
309 | [SYS_fstatat42] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
310 | [SYS_faccessat313] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
311 | [SYS_readlinkat322] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
312 | [SYS_lstat40] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL | PLEDGE_TMPPATH0x0000000000000010ULL, | |||
313 | [SYS_truncate167] = PLEDGE_WPATH0x0000000000000002ULL, | |||
314 | [SYS_rename128] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_CPATH0x0000000000000004ULL, | |||
315 | [SYS_rmdir137] = PLEDGE_CPATH0x0000000000000004ULL, | |||
316 | [SYS_renameat323] = PLEDGE_CPATH0x0000000000000004ULL, | |||
317 | [SYS_link9] = PLEDGE_CPATH0x0000000000000004ULL, | |||
318 | [SYS_linkat317] = PLEDGE_CPATH0x0000000000000004ULL, | |||
319 | [SYS_symlink57] = PLEDGE_CPATH0x0000000000000004ULL, | |||
320 | [SYS_symlinkat324] = PLEDGE_CPATH0x0000000000000004ULL, | |||
321 | [SYS_unlink10] = PLEDGE_CPATH0x0000000000000004ULL | PLEDGE_TMPPATH0x0000000000000010ULL, | |||
322 | [SYS_unlinkat325] = PLEDGE_CPATH0x0000000000000004ULL, | |||
323 | [SYS_mkdir136] = PLEDGE_CPATH0x0000000000000004ULL, | |||
324 | [SYS_mkdirat318] = PLEDGE_CPATH0x0000000000000004ULL, | |||
325 | ||||
326 | [SYS_mkfifo132] = PLEDGE_DPATH0x0000000010000000ULL, | |||
327 | [SYS_mkfifoat319] = PLEDGE_DPATH0x0000000010000000ULL, | |||
328 | [SYS_mknod14] = PLEDGE_DPATH0x0000000010000000ULL, | |||
329 | [SYS_mknodat320] = PLEDGE_DPATH0x0000000010000000ULL, | |||
330 | ||||
331 | [SYS_revoke56] = PLEDGE_TTY0x0000000000010000ULL, /* also requires PLEDGE_RPATH */ | |||
332 | ||||
333 | /* | |||
334 | * Classify as RPATH|WPATH, because of path information leakage. | |||
335 | * WPATH due to unknown use of mk*temp(3) on non-/tmp paths.. | |||
336 | */ | |||
337 | [SYS___getcwd304] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
338 | ||||
339 | /* Classify as RPATH, because these leak path information */ | |||
340 | [SYS_getdents99] = PLEDGE_RPATH0x0000000000000001ULL, | |||
341 | [SYS_getfsstat62] = PLEDGE_RPATH0x0000000000000001ULL, | |||
342 | [SYS_statfs63] = PLEDGE_RPATH0x0000000000000001ULL, | |||
343 | [SYS_fstatfs64] = PLEDGE_RPATH0x0000000000000001ULL, | |||
344 | [SYS_pathconf191] = PLEDGE_RPATH0x0000000000000001ULL, | |||
345 | ||||
346 | [SYS_utimes76] = PLEDGE_FATTR0x0000000000004000ULL, | |||
347 | [SYS_futimes77] = PLEDGE_FATTR0x0000000000004000ULL, | |||
348 | [SYS_utimensat84] = PLEDGE_FATTR0x0000000000004000ULL, | |||
349 | [SYS_futimens85] = PLEDGE_FATTR0x0000000000004000ULL, | |||
350 | [SYS_chmod15] = PLEDGE_FATTR0x0000000000004000ULL, | |||
351 | [SYS_fchmod124] = PLEDGE_FATTR0x0000000000004000ULL, | |||
352 | [SYS_fchmodat314] = PLEDGE_FATTR0x0000000000004000ULL, | |||
353 | [SYS_chflags34] = PLEDGE_FATTR0x0000000000004000ULL, | |||
354 | [SYS_chflagsat107] = PLEDGE_FATTR0x0000000000004000ULL, | |||
355 | [SYS_fchflags35] = PLEDGE_FATTR0x0000000000004000ULL, | |||
356 | ||||
357 | [SYS_chown16] = PLEDGE_CHOWN0x0000000080000000ULL, | |||
358 | [SYS_fchownat315] = PLEDGE_CHOWN0x0000000080000000ULL, | |||
359 | [SYS_lchown254] = PLEDGE_CHOWN0x0000000080000000ULL, | |||
360 | [SYS_fchown123] = PLEDGE_CHOWN0x0000000080000000ULL, | |||
361 | ||||
362 | [SYS_socket97] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL, | |||
363 | [SYS_connect98] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL, | |||
364 | [SYS_bind104] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL, | |||
365 | [SYS_getsockname32] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL, | |||
366 | ||||
367 | [SYS_listen106] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL, | |||
368 | [SYS_accept493] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL, | |||
369 | [SYS_accept30] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL, | |||
370 | [SYS_getpeername31] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL, | |||
371 | ||||
372 | [SYS_flock131] = PLEDGE_FLOCK0x0000000000000080ULL, | |||
373 | ||||
374 | [SYS_ypconnect150] = PLEDGE_GETPW0x0000000000000800ULL, | |||
375 | ||||
376 | [SYS_swapctl193] = PLEDGE_VMINFO0x0000000000400000ULL, | |||
377 | }; | |||
378 | ||||
379 | static const struct { | |||
380 | char *name; | |||
381 | uint64_t flags; | |||
382 | } pledgereq[] = { | |||
383 | { "audio", PLEDGE_AUDIO0x0000000008000000ULL }, | |||
384 | { "bpf", PLEDGE_BPF0x0000000200000000ULL }, | |||
385 | { "chown", PLEDGE_CHOWN0x0000000080000000ULL | PLEDGE_CHOWNUID0x0000000100000000ULL }, | |||
386 | { "cpath", PLEDGE_CPATH0x0000000000000004ULL }, | |||
387 | { "disklabel", PLEDGE_DISKLABEL0x0000000002000000ULL }, | |||
388 | { "dns", PLEDGE_DNS0x0000000000000020ULL }, | |||
389 | { "dpath", PLEDGE_DPATH0x0000000010000000ULL }, | |||
390 | { "drm", PLEDGE_DRM0x0000000020000000ULL }, | |||
391 | { "error", PLEDGE_ERROR0x0000000400000000ULL }, | |||
392 | { "exec", PLEDGE_EXEC0x0000000000080000ULL }, | |||
393 | { "fattr", PLEDGE_FATTR0x0000000000004000ULL | PLEDGE_CHOWN0x0000000080000000ULL }, | |||
394 | { "flock", PLEDGE_FLOCK0x0000000000000080ULL }, | |||
395 | { "getpw", PLEDGE_GETPW0x0000000000000800ULL }, | |||
396 | { "id", PLEDGE_ID0x0000000000000200ULL }, | |||
397 | { "inet", PLEDGE_INET0x0000000000000040ULL }, | |||
398 | { "mcast", PLEDGE_MCAST0x0000000000200000ULL }, | |||
399 | { "pf", PLEDGE_PF0x0000000004000000ULL }, | |||
400 | { "proc", PLEDGE_PROC0x0000000000001000ULL }, | |||
401 | { "prot_exec", PLEDGE_PROTEXEC0x0000000000008000ULL }, | |||
402 | { "ps", PLEDGE_PS0x0000000000800000ULL }, | |||
403 | { "recvfd", PLEDGE_RECVFD0x0000000000040000ULL }, | |||
404 | { "route", PLEDGE_ROUTE0x0000000000100000ULL }, | |||
405 | { "rpath", PLEDGE_RPATH0x0000000000000001ULL }, | |||
406 | { "sendfd", PLEDGE_SENDFD0x0000000000020000ULL }, | |||
407 | { "settime", PLEDGE_SETTIME0x0000000000002000ULL }, | |||
408 | { "stdio", PLEDGE_STDIO0x0000000000000008ULL }, | |||
409 | { "tape", PLEDGE_TAPE0x0000000000000400ULL }, | |||
410 | { "tmppath", PLEDGE_TMPPATH0x0000000000000010ULL }, | |||
411 | { "tty", PLEDGE_TTY0x0000000000010000ULL }, | |||
412 | { "unix", PLEDGE_UNIX0x0000000000000100ULL }, | |||
413 | { "unveil", PLEDGE_UNVEIL0x0000001000000000ULL }, | |||
414 | { "video", PLEDGE_VIDEO0x0000002000000000ULL }, | |||
415 | { "vminfo", PLEDGE_VMINFO0x0000000000400000ULL }, | |||
416 | { "vmm", PLEDGE_VMM0x0000000040000000ULL }, | |||
417 | { "wpath", PLEDGE_WPATH0x0000000000000002ULL }, | |||
418 | { "wroute", PLEDGE_WROUTE0x0000000800000000ULL }, | |||
419 | }; | |||
420 | ||||
421 | int | |||
422 | parsepledges(struct proc *p, const char *kname, const char *promises, u_int64_t *fp) | |||
423 | { | |||
424 | size_t rbuflen; | |||
425 | char *rbuf, *rp, *pn; | |||
426 | u_int64_t flags = 0, f; | |||
427 | int error; | |||
428 | ||||
429 | rbuf = malloc(MAXPATHLEN1024, M_TEMP127, M_WAITOK0x0001); | |||
430 | error = copyinstr(promises, rbuf, MAXPATHLEN1024, &rbuflen); | |||
431 | if (error) { | |||
432 | free(rbuf, M_TEMP127, MAXPATHLEN1024); | |||
433 | return (error); | |||
434 | } | |||
435 | #ifdef KTRACE1 | |||
436 | if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) && ((p)->p_flag & 0x00000001) == 0)) | |||
437 | ktrstruct(p, kname, rbuf, rbuflen-1); | |||
438 | #endif | |||
439 | ||||
440 | for (rp = rbuf; rp && *rp; rp = pn) { | |||
441 | pn = strchr(rp, ' '); /* find terminator */ | |||
442 | if (pn) { | |||
443 | while (*pn == ' ') | |||
444 | *pn++ = '\0'; | |||
445 | } | |||
446 | if ((f = pledgereq_flags(rp)) == 0) { | |||
447 | free(rbuf, M_TEMP127, MAXPATHLEN1024); | |||
448 | return (EINVAL22); | |||
449 | } | |||
450 | flags |= f; | |||
451 | } | |||
452 | free(rbuf, M_TEMP127, MAXPATHLEN1024); | |||
453 | *fp = flags; | |||
454 | return 0; | |||
455 | } | |||
456 | ||||
457 | int | |||
458 | sys_pledge(struct proc *p, void *v, register_t *retval) | |||
459 | { | |||
460 | struct sys_pledge_args /* { | |||
461 | syscallarg(const char *)promises; | |||
462 | syscallarg(const char *)execpromises; | |||
463 | } */ *uap = v; | |||
464 | struct process *pr = p->p_p; | |||
465 | uint64_t promises, execpromises; | |||
466 | int error; | |||
467 | int unveil_cleanup = 0; | |||
468 | ||||
469 | /* Check for any error in user input */ | |||
470 | if (SCARG(uap, promises)((uap)->promises.le.datum)) { | |||
471 | error = parsepledges(p, "pledgereq", | |||
472 | SCARG(uap, promises)((uap)->promises.le.datum), &promises); | |||
473 | if (error) | |||
474 | return (error); | |||
475 | } | |||
476 | if (SCARG(uap, execpromises)((uap)->execpromises.le.datum)) { | |||
477 | error = parsepledges(p, "pledgeexecreq", | |||
478 | SCARG(uap, execpromises)((uap)->execpromises.le.datum), &execpromises); | |||
479 | if (error) | |||
480 | return (error); | |||
481 | } | |||
482 | ||||
483 | mtx_enter(&pr->ps_mtx); | |||
484 | ||||
485 | /* Check for any error wrt current promises */ | |||
486 | if (SCARG(uap, promises)((uap)->promises.le.datum)) { | |||
487 | /* In "error" mode, ignore promise increase requests, | |||
488 | * but accept promise decrease requests */ | |||
489 | if (ISSET(pr->ps_flags, PS_PLEDGE)((pr->ps_flags) & (0x00100000)) && | |||
490 | (pr->ps_pledge & PLEDGE_ERROR0x0000000400000000ULL)) | |||
491 | promises &= (pr->ps_pledge & PLEDGE_USERSET0x0fffffffffffffffULL); | |||
492 | ||||
493 | /* Only permit reductions */ | |||
494 | if (ISSET(pr->ps_flags, PS_PLEDGE)((pr->ps_flags) & (0x00100000)) && | |||
495 | (((promises | pr->ps_pledge) != pr->ps_pledge))) { | |||
496 | mtx_leave(&pr->ps_mtx); | |||
497 | return (EPERM1); | |||
498 | } | |||
499 | } | |||
500 | if (SCARG(uap, execpromises)((uap)->execpromises.le.datum)) { | |||
501 | /* Only permit reductions */ | |||
502 | if (ISSET(pr->ps_flags, PS_EXECPLEDGE)((pr->ps_flags) & (0x00400000)) && | |||
503 | (((execpromises | pr->ps_execpledge) != pr->ps_execpledge))) { | |||
504 | mtx_leave(&pr->ps_mtx); | |||
505 | return (EPERM1); | |||
506 | } | |||
507 | } | |||
508 | ||||
509 | /* Set up promises */ | |||
510 | if (SCARG(uap, promises)((uap)->promises.le.datum)) { | |||
511 | pr->ps_pledge = promises; | |||
512 | atomic_setbits_intx86_atomic_setbits_u32(&pr->ps_flags, PS_PLEDGE0x00100000); | |||
513 | ||||
514 | if ((pr->ps_pledge & (PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL | | |||
515 | PLEDGE_CPATH0x0000000000000004ULL | PLEDGE_DPATH0x0000000010000000ULL | PLEDGE_TMPPATH0x0000000000000010ULL | PLEDGE_EXEC0x0000000000080000ULL | | |||
516 | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_UNVEIL0x0000001000000000ULL)) == 0) | |||
517 | unveil_cleanup = 1; | |||
518 | } | |||
519 | if (SCARG(uap, execpromises)((uap)->execpromises.le.datum)) { | |||
520 | pr->ps_execpledge = execpromises; | |||
521 | atomic_setbits_intx86_atomic_setbits_u32(&pr->ps_flags, PS_EXECPLEDGE0x00400000); | |||
522 | } | |||
523 | ||||
524 | mtx_leave(&pr->ps_mtx); | |||
525 | ||||
526 | if (unveil_cleanup) { | |||
527 | /* | |||
528 | * Kill off unveil and drop unveil vnode refs if we no | |||
529 | * longer are holding any path-accessing pledge | |||
530 | */ | |||
531 | KERNEL_LOCK()_kernel_lock(); | |||
532 | unveil_destroy(pr); | |||
533 | KERNEL_UNLOCK()_kernel_unlock(); | |||
534 | } | |||
535 | ||||
536 | return (0); | |||
537 | } | |||
538 | ||||
539 | int | |||
540 | pledge_syscall(struct proc *p, int code, uint64_t *tval) | |||
541 | { | |||
542 | p->p_pledge_syscall = code; | |||
543 | *tval = 0; | |||
544 | ||||
545 | if (code < 0 || code > SYS_MAXSYSCALL331 - 1) | |||
546 | return (EINVAL22); | |||
547 | ||||
548 | if (pledge_syscalls[code] == PLEDGE_ALWAYS0xffffffffffffffffULL) | |||
549 | return (0); | |||
550 | ||||
551 | if (p->p_p->ps_pledge & pledge_syscalls[code]) | |||
552 | return (0); | |||
553 | ||||
554 | *tval = pledge_syscalls[code]; | |||
555 | return (EPERM1); | |||
556 | } | |||
557 | ||||
558 | int | |||
559 | pledge_fail(struct proc *p, int error, uint64_t code) | |||
560 | { | |||
561 | const char *codes = ""; | |||
562 | int i; | |||
563 | ||||
564 | /* Print first matching pledge */ | |||
565 | for (i = 0; code && pledgenames[i].bits != 0; i++) | |||
566 | if (pledgenames[i].bits & code) { | |||
567 | codes = pledgenames[i].name; | |||
568 | break; | |||
569 | } | |||
570 | #ifdef KTRACE1 | |||
571 | if (KTRPOINT(p, KTR_PLEDGE)((p)->p_p->ps_traceflag & (1<<(12)) && ((p)->p_flag & 0x00000001) == 0)) | |||
572 | ktrpledge(p, error, code, p->p_pledge_syscall); | |||
573 | #endif | |||
574 | if (p->p_p->ps_pledge & PLEDGE_ERROR0x0000000400000000ULL) | |||
575 | return (ENOSYS78); | |||
576 | ||||
577 | KERNEL_LOCK()_kernel_lock(); | |||
578 | log(LOG_ERR3, "%s[%d]: pledge \"%s\", syscall %d\n", | |||
579 | p->p_p->ps_comm, p->p_p->ps_pid, codes, p->p_pledge_syscall); | |||
580 | p->p_p->ps_acflag |= APLEDGE0x00000020; | |||
581 | ||||
582 | /* Try to stop threads immediately, because this process is suspect */ | |||
583 | if (P_HASSIBLING(p)((p)->p_p->ps_threadcnt > 1)) | |||
584 | single_thread_set(p, SINGLE_UNWIND0x02 | SINGLE_DEEP0x10); | |||
585 | ||||
586 | /* Send uncatchable SIGABRT for coredump */ | |||
587 | sigabort(p); | |||
588 | ||||
589 | p->p_p->ps_pledge = 0; /* Disable all PLEDGE_ flags */ | |||
590 | KERNEL_UNLOCK()_kernel_unlock(); | |||
591 | return (error); | |||
592 | } | |||
593 | ||||
594 | /* | |||
595 | * Need to make it more obvious that one cannot get through here | |||
596 | * without the right flags set | |||
597 | */ | |||
598 | int | |||
599 | pledge_namei(struct proc *p, struct nameidata *ni, char *origpath) | |||
600 | { | |||
601 | char path[PATH_MAX1024]; | |||
602 | uint64_t pledge; | |||
603 | int error; | |||
604 | ||||
605 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0 || | |||
606 | (p->p_p->ps_flags & PS_COREDUMP0x00000800)) | |||
607 | return (0); | |||
608 | pledge = READ_ONCE(p->p_p->ps_pledge)({ typeof(p->p_p->ps_pledge) __tmp = *(volatile typeof( p->p_p->ps_pledge) *)&(p->p_p->ps_pledge); membar_datadep_consumer (); __tmp; }); | |||
609 | ||||
610 | if (ni->ni_pledge == 0) | |||
611 | panic("pledge_namei: ni_pledge"); | |||
612 | ||||
613 | /* | |||
614 | * We set the BYPASSUNVEIL flag to skip unveil checks | |||
615 | * as necessary | |||
616 | */ | |||
617 | ||||
618 | /* Doing a permitted execve() */ | |||
619 | if ((ni->ni_pledge & PLEDGE_EXEC0x0000000000080000ULL) && | |||
620 | (pledge & PLEDGE_EXEC0x0000000000080000ULL)) | |||
621 | return (0); | |||
622 | ||||
623 | error = canonpath(origpath, path, sizeof(path)); | |||
624 | if (error) | |||
625 | return (error); | |||
626 | ||||
627 | /* Detect what looks like a mkstemp(3) family operation */ | |||
628 | if ((pledge & PLEDGE_TMPPATH0x0000000000000010ULL) && | |||
629 | (p->p_pledge_syscall == SYS_open5) && | |||
630 | (ni->ni_pledge & PLEDGE_CPATH0x0000000000000004ULL) && | |||
631 | strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { | |||
632 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
633 | return (0); | |||
634 | } | |||
635 | ||||
636 | /* Allow unlinking of a mkstemp(3) file... | |||
637 | * Good opportunity for strict checks here. | |||
638 | */ | |||
639 | if ((pledge & PLEDGE_TMPPATH0x0000000000000010ULL) && | |||
640 | (p->p_pledge_syscall == SYS_unlink10) && | |||
641 | strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { | |||
642 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
643 | return (0); | |||
644 | } | |||
645 | ||||
646 | /* Whitelisted paths */ | |||
647 | switch (p->p_pledge_syscall) { | |||
648 | case SYS_access33: | |||
649 | /* tzset() needs this. */ | |||
650 | if (ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL && | |||
651 | strcmp(path, "/etc/localtime") == 0) { | |||
652 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
653 | return (0); | |||
654 | } | |||
655 | break; | |||
656 | case SYS_open5: | |||
657 | /* daemon(3) or other such functions */ | |||
658 | if ((ni->ni_pledge & ~(PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL)) == 0 && | |||
659 | strcmp(path, "/dev/null") == 0) { | |||
660 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
661 | return (0); | |||
662 | } | |||
663 | ||||
664 | /* readpassphrase(3), getpass(3) */ | |||
665 | if ((pledge & PLEDGE_TTY0x0000000000010000ULL) && | |||
666 | (ni->ni_pledge & ~(PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL)) == 0 && | |||
667 | strcmp(path, "/dev/tty") == 0) { | |||
668 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
669 | return (0); | |||
670 | } | |||
671 | ||||
672 | /* getpw* and friends need a few files */ | |||
673 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
674 | (pledge & PLEDGE_GETPW0x0000000000000800ULL)) { | |||
675 | if (strcmp(path, "/etc/spwd.db") == 0) | |||
676 | return (EPERM1); /* don't call pledge_fail */ | |||
677 | if (strcmp(path, "/etc/pwd.db") == 0) { | |||
678 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
679 | return (0); | |||
680 | } | |||
681 | if (strcmp(path, "/etc/group") == 0) { | |||
682 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
683 | return (0); | |||
684 | } | |||
685 | if (strcmp(path, "/etc/netid") == 0) { | |||
686 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
687 | return (0); | |||
688 | } | |||
689 | } | |||
690 | ||||
691 | /* DNS needs /etc/{resolv.conf,hosts,services,protocols}. */ | |||
692 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
693 | (pledge & PLEDGE_DNS0x0000000000000020ULL)) { | |||
694 | if (strcmp(path, "/etc/resolv.conf") == 0) { | |||
695 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
696 | return (0); | |||
697 | } | |||
698 | if (strcmp(path, "/etc/hosts") == 0) { | |||
699 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
700 | return (0); | |||
701 | } | |||
702 | if (strcmp(path, "/etc/services") == 0) { | |||
703 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
704 | return (0); | |||
705 | } | |||
706 | if (strcmp(path, "/etc/protocols") == 0) { | |||
707 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
708 | return (0); | |||
709 | } | |||
710 | } | |||
711 | ||||
712 | /* tzset() needs these. */ | |||
713 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
714 | strncmp(path, "/usr/share/zoneinfo/", | |||
715 | sizeof("/usr/share/zoneinfo/") - 1) == 0) { | |||
716 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
717 | return (0); | |||
718 | } | |||
719 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
720 | strcmp(path, "/etc/localtime") == 0) { | |||
721 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
722 | return (0); | |||
723 | } | |||
724 | ||||
725 | break; | |||
726 | case SYS_stat38: | |||
727 | /* DNS needs /etc/{resolv.conf,hosts}. */ | |||
728 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
729 | (pledge & PLEDGE_DNS0x0000000000000020ULL)) { | |||
730 | if (strcmp(path, "/etc/resolv.conf") == 0) { | |||
731 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
732 | return (0); | |||
733 | } | |||
734 | if (strcmp(path, "/etc/hosts") == 0) { | |||
735 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
736 | return (0); | |||
737 | } | |||
738 | } | |||
739 | break; | |||
740 | } | |||
741 | ||||
742 | /* | |||
743 | * Ensure each flag of ni_pledge has counterpart allowing it in | |||
744 | * ps_pledge. | |||
745 | */ | |||
746 | if (ni->ni_pledge & ~pledge) | |||
747 | return (pledge_fail(p, EPERM1, (ni->ni_pledge & ~pledge))); | |||
748 | ||||
749 | /* continue, and check unveil if present */ | |||
750 | return (0); | |||
751 | } | |||
752 | ||||
753 | /* | |||
754 | * Only allow reception of safe file descriptors. | |||
755 | */ | |||
756 | int | |||
757 | pledge_recvfd(struct proc *p, struct file *fp) | |||
758 | { | |||
759 | struct vnode *vp; | |||
760 | ||||
761 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
762 | return (0); | |||
763 | if ((p->p_p->ps_pledge & PLEDGE_RECVFD0x0000000000040000ULL) == 0) | |||
764 | return pledge_fail(p, EPERM1, PLEDGE_RECVFD0x0000000000040000ULL); | |||
765 | ||||
766 | switch (fp->f_type) { | |||
767 | case DTYPE_SOCKET2: | |||
768 | case DTYPE_PIPE3: | |||
769 | case DTYPE_DMABUF5: | |||
770 | case DTYPE_SYNC6: | |||
771 | return (0); | |||
772 | case DTYPE_VNODE1: | |||
773 | vp = fp->f_data; | |||
774 | ||||
775 | if (vp->v_type != VDIR) | |||
776 | return (0); | |||
777 | } | |||
778 | return pledge_fail(p, EINVAL22, PLEDGE_RECVFD0x0000000000040000ULL); | |||
779 | } | |||
780 | ||||
781 | /* | |||
782 | * Only allow sending of safe file descriptors. | |||
783 | */ | |||
784 | int | |||
785 | pledge_sendfd(struct proc *p, struct file *fp) | |||
786 | { | |||
787 | struct vnode *vp; | |||
788 | ||||
789 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
790 | return (0); | |||
791 | if ((p->p_p->ps_pledge & PLEDGE_SENDFD0x0000000000020000ULL) == 0) | |||
792 | return pledge_fail(p, EPERM1, PLEDGE_SENDFD0x0000000000020000ULL); | |||
793 | ||||
794 | switch (fp->f_type) { | |||
795 | case DTYPE_SOCKET2: | |||
796 | case DTYPE_PIPE3: | |||
797 | case DTYPE_DMABUF5: | |||
798 | case DTYPE_SYNC6: | |||
799 | return (0); | |||
800 | case DTYPE_VNODE1: | |||
801 | vp = fp->f_data; | |||
802 | ||||
803 | if (vp->v_type != VDIR) | |||
804 | return (0); | |||
805 | break; | |||
806 | } | |||
807 | return pledge_fail(p, EINVAL22, PLEDGE_SENDFD0x0000000000020000ULL); | |||
808 | } | |||
809 | ||||
810 | int | |||
811 | pledge_sysctl(struct proc *p, int miblen, int *mib, void *new) | |||
812 | { | |||
813 | char buf[80]; | |||
814 | uint64_t pledge; | |||
815 | int i; | |||
816 | ||||
817 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
818 | return (0); | |||
819 | pledge = READ_ONCE(p->p_p->ps_pledge)({ typeof(p->p_p->ps_pledge) __tmp = *(volatile typeof( p->p_p->ps_pledge) *)&(p->p_p->ps_pledge); membar_datadep_consumer (); __tmp; }); | |||
820 | ||||
821 | if (new) | |||
822 | return pledge_fail(p, EFAULT14, 0); | |||
823 | ||||
824 | /* routing table observation */ | |||
825 | if ((pledge & PLEDGE_ROUTE0x0000000000100000ULL)) { | |||
826 | if ((miblen == 6 || miblen == 7) && | |||
827 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
828 | mib[2] == 0 && | |||
829 | mib[4] == NET_RT_DUMP1) | |||
830 | return (0); | |||
831 | ||||
832 | if (miblen == 6 && | |||
833 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
834 | mib[2] == 0 && | |||
835 | (mib[3] == 0 || mib[3] == AF_INET624 || mib[3] == AF_INET2) && | |||
836 | (mib[4] == NET_RT_TABLE5 || mib[4] == NET_RT_SOURCE7)) | |||
837 | return (0); | |||
838 | ||||
839 | if (miblen == 7 && /* exposes MACs */ | |||
840 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
841 | mib[2] == 0 && | |||
842 | (mib[3] == 0 || mib[3] == AF_INET624 || mib[3] == AF_INET2) && | |||
843 | mib[4] == NET_RT_FLAGS2 && mib[5] == RTF_LLINFO0x400) | |||
844 | return (0); | |||
845 | } | |||
846 | ||||
847 | if ((pledge & PLEDGE_WROUTE0x0000000800000000ULL)) { | |||
848 | if (miblen == 4 && | |||
849 | mib[0] == CTL_NET4 && mib[1] == PF_INET624 && | |||
850 | mib[2] == IPPROTO_IPV641 && mib[3] == IPV6CTL_SOIIKEY54) | |||
851 | return (0); | |||
852 | } | |||
853 | ||||
854 | if (pledge & (PLEDGE_PS0x0000000000800000ULL | PLEDGE_VMINFO0x0000000000400000ULL)) { | |||
855 | if (miblen == 2 && /* kern.fscale */ | |||
856 | mib[0] == CTL_KERN1 && mib[1] == KERN_FSCALE46) | |||
857 | return (0); | |||
858 | if (miblen == 2 && /* kern.boottime */ | |||
859 | mib[0] == CTL_KERN1 && mib[1] == KERN_BOOTTIME21) | |||
860 | return (0); | |||
861 | if (miblen == 2 && /* kern.consdev */ | |||
862 | mib[0] == CTL_KERN1 && mib[1] == KERN_CONSDEV75) | |||
863 | return (0); | |||
864 | if (miblen == 2 && /* kern.cptime */ | |||
865 | mib[0] == CTL_KERN1 && mib[1] == KERN_CPTIME40) | |||
866 | return (0); | |||
867 | if (miblen == 3 && /* kern.cptime2 */ | |||
868 | mib[0] == CTL_KERN1 && mib[1] == KERN_CPTIME271) | |||
869 | return (0); | |||
870 | if (miblen == 3 && /* kern.cpustats */ | |||
871 | mib[0] == CTL_KERN1 && mib[1] == KERN_CPUSTATS85) | |||
872 | return (0); | |||
873 | } | |||
874 | ||||
875 | if ((pledge & PLEDGE_PS0x0000000000800000ULL)) { | |||
876 | if (miblen == 4 && /* kern.procargs.* */ | |||
877 | mib[0] == CTL_KERN1 && mib[1] == KERN_PROC_ARGS55 && | |||
878 | (mib[3] == KERN_PROC_ARGV1 || mib[3] == KERN_PROC_ENV3)) | |||
879 | return (0); | |||
880 | if (miblen == 6 && /* kern.proc.* */ | |||
881 | mib[0] == CTL_KERN1 && mib[1] == KERN_PROC66) | |||
882 | return (0); | |||
883 | if (miblen == 3 && /* kern.proc_cwd.* */ | |||
884 | mib[0] == CTL_KERN1 && mib[1] == KERN_PROC_CWD78) | |||
885 | return (0); | |||
886 | if (miblen == 2 && /* kern.ccpu */ | |||
887 | mib[0] == CTL_KERN1 && mib[1] == KERN_CCPU45) | |||
888 | return (0); | |||
889 | if (miblen == 2 && /* vm.maxslp */ | |||
890 | mib[0] == CTL_VM2 && mib[1] == VM_MAXSLP10) | |||
891 | return (0); | |||
892 | } | |||
893 | ||||
894 | if ((pledge & PLEDGE_VMINFO0x0000000000400000ULL)) { | |||
895 | if (miblen == 2 && /* vm.uvmexp */ | |||
896 | mib[0] == CTL_VM2 && mib[1] == VM_UVMEXP4) | |||
897 | return (0); | |||
898 | if (miblen == 3 && /* vfs.generic.bcachestat */ | |||
899 | mib[0] == CTL_VFS10 && mib[1] == VFS_GENERIC0 && | |||
900 | mib[2] == VFS_BCACHESTAT3) | |||
901 | return (0); | |||
902 | if (miblen == 3 && /* for sysconf(3) */ | |||
903 | mib[0] == CTL_NET4 && mib[1] == PF_INET624) | |||
904 | return (0); | |||
905 | } | |||
906 | ||||
907 | if ((pledge & (PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL))) { | |||
908 | if (miblen == 2 && /* kern.somaxconn */ | |||
909 | mib[0] == CTL_KERN1 && mib[1] == KERN_SOMAXCONN28) | |||
910 | return (0); | |||
911 | } | |||
912 | ||||
913 | if ((pledge & (PLEDGE_ROUTE0x0000000000100000ULL | PLEDGE_INET0x0000000000000040ULL | PLEDGE_DNS0x0000000000000020ULL))) { | |||
914 | if (miblen == 6 && /* getifaddrs() */ | |||
915 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
916 | mib[2] == 0 && | |||
917 | (mib[3] == 0 || mib[3] == AF_INET624 || mib[3] == AF_INET2) && | |||
918 | mib[4] == NET_RT_IFLIST3) | |||
919 | return (0); | |||
920 | } | |||
921 | ||||
922 | if ((pledge & PLEDGE_DISKLABEL0x0000000002000000ULL)) { | |||
923 | if (miblen == 2 && /* kern.rawpartition */ | |||
924 | mib[0] == CTL_KERN1 && | |||
925 | mib[1] == KERN_RAWPARTITION24) | |||
926 | return (0); | |||
927 | if (miblen == 2 && /* kern.maxpartitions */ | |||
928 | mib[0] == CTL_KERN1 && | |||
929 | mib[1] == KERN_MAXPARTITIONS23) | |||
930 | return (0); | |||
931 | #ifdef CPU_CHR2BLK4 | |||
932 | if (miblen == 3 && /* machdep.chr2blk */ | |||
933 | mib[0] == CTL_MACHDEP7 && | |||
934 | mib[1] == CPU_CHR2BLK4) | |||
935 | return (0); | |||
936 | #endif /* CPU_CHR2BLK */ | |||
937 | } | |||
938 | ||||
939 | if (miblen >= 3 && /* ntpd(8) to read sensors */ | |||
940 | mib[0] == CTL_HW6 && mib[1] == HW_SENSORS11) | |||
941 | return (0); | |||
942 | ||||
943 | if (miblen == 6 && /* if_nameindex() */ | |||
944 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
945 | mib[2] == 0 && mib[3] == 0 && mib[4] == NET_RT_IFNAMES6) | |||
946 | return (0); | |||
947 | ||||
948 | if (miblen == 2) { | |||
949 | switch (mib[0]) { | |||
950 | case CTL_KERN1: | |||
951 | switch (mib[1]) { | |||
952 | case KERN_DOMAINNAME22: /* getdomainname() */ | |||
953 | case KERN_HOSTNAME10: /* gethostname() */ | |||
954 | case KERN_OSTYPE1: /* uname() */ | |||
955 | case KERN_OSRELEASE2: /* uname() */ | |||
956 | case KERN_OSVERSION27: /* uname() */ | |||
957 | case KERN_VERSION4: /* uname() */ | |||
958 | case KERN_CLOCKRATE12: /* kern.clockrate */ | |||
959 | case KERN_ARGMAX8: /* kern.argmax */ | |||
960 | case KERN_NGROUPS18: /* kern.ngroups */ | |||
961 | case KERN_SYSVSHM36: /* kern.sysvshm */ | |||
962 | case KERN_POSIX117: /* kern.posix1version */ | |||
963 | case KERN_AUTOCONF_SERIAL91: /* kern.autoconf_serial */ | |||
964 | return (0); | |||
965 | } | |||
966 | break; | |||
967 | case CTL_HW6: | |||
968 | switch (mib[1]) { | |||
969 | case HW_MACHINE1: /* uname() */ | |||
970 | case HW_PAGESIZE7: /* getpagesize() */ | |||
971 | case HW_PHYSMEM6419: /* hw.physmem */ | |||
972 | case HW_NCPU3: /* hw.ncpu */ | |||
973 | case HW_NCPUONLINE25: /* hw.ncpuonline */ | |||
974 | case HW_USERMEM6420: /* hw.usermem */ | |||
975 | return (0); | |||
976 | } | |||
977 | break; | |||
978 | case CTL_VM2: | |||
979 | switch (mib[1]) { | |||
980 | case VM_PSSTRINGS3: /* setproctitle() */ | |||
981 | case VM_LOADAVG2: /* vm.loadavg / getloadavg(3) */ | |||
982 | case VM_MALLOC_CONF12: /* vm.malloc_conf */ | |||
983 | return (0); | |||
984 | } | |||
985 | break; | |||
986 | default: | |||
987 | break; | |||
988 | } | |||
989 | } | |||
990 | ||||
991 | #ifdef CPU_SSE | |||
992 | if (miblen == 2 && /* i386 libm tests for SSE */ | |||
993 | mib[0] == CTL_MACHDEP7 && mib[1] == CPU_SSE) | |||
994 | return (0); | |||
995 | #endif /* CPU_SSE */ | |||
996 | ||||
997 | #ifdef CPU_ID_AA64ISAR0 | |||
998 | if (miblen == 2 && /* arm64 libcrypto inspects CPU features */ | |||
999 | mib[0] == CTL_MACHDEP7 && mib[1] == CPU_ID_AA64ISAR0) | |||
1000 | return (0); | |||
1001 | #endif /* CPU_ID_AA64ISAR0 */ | |||
1002 | ||||
1003 | snprintf(buf, sizeof(buf), "%s(%d): pledge sysctl %d:", | |||
1004 | p->p_p->ps_comm, p->p_p->ps_pid, miblen); | |||
1005 | for (i = 0; i < miblen; i++) { | |||
1006 | char *p = buf + strlen(buf); | |||
1007 | snprintf(p, sizeof(buf) - (p - buf), " %d", mib[i]); | |||
1008 | } | |||
1009 | log(LOG_ERR3, "%s\n", buf); | |||
1010 | ||||
1011 | return pledge_fail(p, EINVAL22, 0); | |||
1012 | } | |||
1013 | ||||
1014 | int | |||
1015 | pledge_chown(struct proc *p, uid_t uid, gid_t gid) | |||
1016 | { | |||
1017 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1018 | return (0); | |||
1019 | ||||
1020 | if (p->p_p->ps_pledge & PLEDGE_CHOWNUID0x0000000100000000ULL) | |||
1021 | return (0); | |||
1022 | ||||
1023 | if (uid != -1 && uid != p->p_ucred->cr_uid) | |||
1024 | return (EPERM1); | |||
1025 | if (gid != -1 && !groupmember(gid, p->p_ucred)) | |||
1026 | return (EPERM1); | |||
1027 | return (0); | |||
1028 | } | |||
1029 | ||||
1030 | int | |||
1031 | pledge_adjtime(struct proc *p, const void *v) | |||
1032 | { | |||
1033 | const struct timeval *delta = v; | |||
1034 | ||||
1035 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1036 | return (0); | |||
1037 | ||||
1038 | if ((p->p_p->ps_pledge & PLEDGE_SETTIME0x0000000000002000ULL)) | |||
1039 | return (0); | |||
1040 | if (delta) | |||
1041 | return (EPERM1); | |||
1042 | return (0); | |||
1043 | } | |||
1044 | ||||
1045 | int | |||
1046 | pledge_sendit(struct proc *p, const void *to) | |||
1047 | { | |||
1048 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1049 | return (0); | |||
1050 | ||||
1051 | if ((p->p_p->ps_pledge & (PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL))) | |||
1052 | return (0); /* may use address */ | |||
1053 | if (to == NULL((void *)0)) | |||
1054 | return (0); /* behaves just like write */ | |||
1055 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
1056 | } | |||
1057 | ||||
1058 | int | |||
1059 | pledge_ioctl(struct proc *p, long com, struct file *fp) | |||
1060 | { | |||
1061 | struct vnode *vp = NULL((void *)0); | |||
| ||||
1062 | int error = EPERM1; | |||
1063 | uint64_t pledge; | |||
1064 | ||||
1065 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1066 | return (0); | |||
1067 | pledge = READ_ONCE(p->p_p->ps_pledge)({ typeof(p->p_p->ps_pledge) __tmp = *(volatile typeof( p->p_p->ps_pledge) *)&(p->p_p->ps_pledge); membar_datadep_consumer (); __tmp; }); | |||
1068 | ||||
1069 | /* | |||
1070 | * The ioctl's which are always allowed. | |||
1071 | */ | |||
1072 | switch (com) { | |||
1073 | case FIONREAD((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('f')) << 8) | ((127))): | |||
1074 | case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('f')) << 8) | ((126))): | |||
1075 | case FIOCLEX((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('f')) << 8) | ((1))): | |||
1076 | case FIONCLEX((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('f')) << 8) | ((2))): | |||
1077 | return (0); | |||
1078 | } | |||
1079 | ||||
1080 | /* fp != NULL was already checked */ | |||
1081 | if (fp->f_type == DTYPE_VNODE1) { | |||
1082 | vp = fp->f_data; | |||
1083 | if (vp->v_type == VBAD) | |||
1084 | return (ENOTTY25); | |||
1085 | } | |||
1086 | ||||
1087 | if ((pledge & PLEDGE_INET0x0000000000000040ULL)) { | |||
1088 | switch (com) { | |||
1089 | case SIOCATMARK((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('s')) << 8) | ((7))): | |||
1090 | case SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((136))): | |||
1091 | if (fp->f_type == DTYPE_SOCKET2) | |||
1092 | return (0); | |||
1093 | break; | |||
1094 | } | |||
1095 | } | |||
1096 | ||||
1097 | #if NBPFILTER1 > 0 | |||
1098 | if ((pledge & PLEDGE_BPF0x0000000200000000ULL)) { | |||
1099 | switch (com) { | |||
1100 | case BIOCGSTATS((unsigned long)0x40000000 | ((sizeof(struct bpf_stat) & 0x1fff ) << 16) | ((('B')) << 8) | ((111))): /* bpf: tcpdump privsep on ^C */ | |||
1101 | if (fp->f_type == DTYPE_VNODE1 && | |||
1102 | fp->f_ops->fo_ioctl == vn_ioctl && | |||
1103 | vp->v_type == VCHR && | |||
1104 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == bpfopen) | |||
1105 | return (0); | |||
1106 | break; | |||
1107 | } | |||
1108 | } | |||
1109 | #endif /* NBPFILTER > 0 */ | |||
1110 | ||||
1111 | if ((pledge & PLEDGE_TAPE0x0000000000000400ULL)) { | |||
1112 | switch (com) { | |||
1113 | case MTIOCGET((unsigned long)0x40000000 | ((sizeof(struct mtget) & 0x1fff ) << 16) | ((('m')) << 8) | ((2))): | |||
1114 | case MTIOCTOP((unsigned long)0x80000000 | ((sizeof(struct mtop) & 0x1fff ) << 16) | ((('m')) << 8) | ((1))): | |||
1115 | /* for pax(1) and such, checking tapes... */ | |||
1116 | if (fp->f_type == DTYPE_VNODE1 && | |||
1117 | vp->v_type == VCHR) { | |||
1118 | if (vp->v_flag & VISTTY0x0008) | |||
1119 | return (ENOTTY25); | |||
1120 | else | |||
1121 | return (0); | |||
1122 | } | |||
1123 | break; | |||
1124 | } | |||
1125 | } | |||
1126 | ||||
1127 | #if NDRM1 > 0 | |||
1128 | if ((pledge & PLEDGE_DRM0x0000000020000000ULL)) { | |||
1129 | if ((fp->f_type == DTYPE_VNODE1) && | |||
1130 | (vp->v_type == VCHR) && | |||
1131 | (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == drmopen)) { | |||
1132 | error = pledge_ioctl_drm(p, com, vp->v_rdevv_un.vu_specinfo->si_rdev); | |||
1133 | if (error == 0) | |||
1134 | return 0; | |||
1135 | } | |||
1136 | } | |||
1137 | #endif /* NDRM > 0 */ | |||
1138 | ||||
1139 | #if NAUDIO1 > 0 | |||
1140 | if ((pledge & PLEDGE_AUDIO0x0000000008000000ULL)) { | |||
1141 | switch (com) { | |||
1142 | case AUDIO_GETPOS((unsigned long)0x40000000 | ((sizeof(struct audio_pos) & 0x1fff) << 16) | ((('A')) << 8) | ((35))): | |||
1143 | case AUDIO_GETPAR((unsigned long)0x40000000 | ((sizeof(struct audio_swpar) & 0x1fff) << 16) | ((('A')) << 8) | ((36))): | |||
1144 | case AUDIO_SETPAR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct audio_swpar) & 0x1fff) << 16) | ((('A')) << 8) | ((37))): | |||
1145 | case AUDIO_START((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('A')) << 8) | ((38))): | |||
1146 | case AUDIO_STOP((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('A')) << 8) | ((39))): | |||
1147 | case AUDIO_MIXER_DEVINFO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (mixer_devinfo_t) & 0x1fff) << 16) | ((('M')) << 8) | ((2))): | |||
1148 | case AUDIO_MIXER_READ(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (mixer_ctrl_t) & 0x1fff) << 16) | ((('M')) << 8) | ((0))): | |||
1149 | case AUDIO_MIXER_WRITE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (mixer_ctrl_t) & 0x1fff) << 16) | ((('M')) << 8) | ((1))): | |||
1150 | if (fp->f_type == DTYPE_VNODE1 && | |||
1151 | vp->v_type == VCHR && | |||
1152 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == audioopen) | |||
1153 | return (0); | |||
1154 | } | |||
1155 | } | |||
1156 | #endif /* NAUDIO > 0 */ | |||
1157 | ||||
1158 | if ((pledge & PLEDGE_DISKLABEL0x0000000002000000ULL)) { | |||
1159 | switch (com) { | |||
1160 | case DIOCGDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((101))): | |||
1161 | case DIOCGPDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((114))): | |||
1162 | case DIOCRLDINFO((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('d')) << 8) | ((115))): | |||
1163 | case DIOCWDINFO((unsigned long)0x80000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((103))): | |||
1164 | case BIOCDISK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bioc_disk) & 0x1fff) << 16) | ((('B')) << 8) | ((33))): | |||
1165 | case BIOCINQ(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bioc_inq) & 0x1fff) << 16) | ((('B')) << 8) | ((32))): | |||
1166 | case BIOCINSTALLBOOT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bioc_installboot) & 0x1fff) << 16) | ((('B' )) << 8) | ((41))): | |||
1167 | case BIOCVOL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bioc_vol) & 0x1fff) << 16) | ((('B')) << 8) | ((34))): | |||
1168 | if (fp->f_type == DTYPE_VNODE1 && | |||
1169 | ((vp->v_type == VCHR && | |||
1170 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_type == D_DISK1) || | |||
1171 | (vp->v_type == VBLK && | |||
1172 | bdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_type == D_DISK1))) | |||
1173 | return (0); | |||
1174 | break; | |||
1175 | case DIOCMAP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct dk_diskmap) & 0x1fff) << 16) | ((('d')) << 8) | ((119))): | |||
1176 | if (fp->f_type == DTYPE_VNODE1 && | |||
1177 | vp->v_type == VCHR && | |||
1178 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_ioctl == diskmapioctl) | |||
1179 | return (0); | |||
1180 | break; | |||
1181 | } | |||
1182 | } | |||
1183 | ||||
1184 | #if NVIDEO1 > 0 | |||
1185 | if ((pledge & PLEDGE_VIDEO0x0000002000000000ULL)) { | |||
1186 | switch (com) { | |||
1187 | case VIDIOC_QUERYCAP((unsigned long)0x40000000 | ((sizeof(struct v4l2_capability) & 0x1fff) << 16) | ((('V')) << 8) | ((0))): | |||
1188 | case VIDIOC_TRY_FMT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_format) & 0x1fff) << 16) | ((('V')) << 8) | ((64))): | |||
1189 | case VIDIOC_ENUM_FMT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_fmtdesc) & 0x1fff) << 16) | ((('V')) << 8) | ((2))): | |||
1190 | case VIDIOC_S_FMT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_format) & 0x1fff) << 16) | ((('V')) << 8) | ((5))): | |||
1191 | case VIDIOC_QUERYCTRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_queryctrl) & 0x1fff) << 16) | ((('V')) << 8) | ((36))): | |||
1192 | case VIDIOC_G_CTRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_control) & 0x1fff) << 16) | ((('V')) << 8) | ((27))): | |||
1193 | case VIDIOC_S_CTRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_control) & 0x1fff) << 16) | ((('V')) << 8) | ((28))): | |||
1194 | case VIDIOC_G_PARM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_streamparm) & 0x1fff) << 16) | ((('V') ) << 8) | ((21))): | |||
1195 | case VIDIOC_S_PARM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_streamparm) & 0x1fff) << 16) | ((('V') ) << 8) | ((22))): | |||
1196 | case VIDIOC_REQBUFS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_requestbuffers) & 0x1fff) << 16) | ((( 'V')) << 8) | ((8))): | |||
1197 | case VIDIOC_QBUF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_buffer) & 0x1fff) << 16) | ((('V')) << 8) | ((15))): | |||
1198 | case VIDIOC_DQBUF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_buffer) & 0x1fff) << 16) | ((('V')) << 8) | ((17))): | |||
1199 | case VIDIOC_QUERYBUF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_buffer) & 0x1fff) << 16) | ((('V')) << 8) | ((9))): | |||
1200 | case VIDIOC_STREAMON((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('V')) << 8) | ((18))): | |||
1201 | case VIDIOC_STREAMOFF((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('V')) << 8) | ((19))): | |||
1202 | case VIDIOC_ENUM_FRAMESIZES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_frmsizeenum) & 0x1fff) << 16) | ((('V' )) << 8) | ((74))): | |||
1203 | case VIDIOC_ENUM_FRAMEINTERVALS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_frmivalenum) & 0x1fff) << 16) | ((('V' )) << 8) | ((75))): | |||
1204 | case VIDIOC_DQEVENT((unsigned long)0x40000000 | ((sizeof(struct v4l2_event) & 0x1fff) << 16) | ((('V')) << 8) | ((89))): | |||
1205 | case VIDIOC_ENCODER_CMD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_encoder_cmd) & 0x1fff) << 16) | ((('V' )) << 8) | ((77))): | |||
1206 | case VIDIOC_EXPBUF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_exportbuffer) & 0x1fff) << 16) | ((('V' )) << 8) | ((16))): | |||
1207 | case VIDIOC_G_CROP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_crop) & 0x1fff) << 16) | ((('V')) << 8) | ((59))): | |||
1208 | case VIDIOC_G_EXT_CTRLS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_ext_controls) & 0x1fff) << 16) | ((('V' )) << 8) | ((71))): | |||
1209 | case VIDIOC_G_FMT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_format) & 0x1fff) << 16) | ((('V')) << 8) | ((4))): | |||
1210 | case VIDIOC_G_SELECTION(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_selection) & 0x1fff) << 16) | ((('V')) << 8) | ((94))): | |||
1211 | case VIDIOC_QUERYMENU(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_querymenu) & 0x1fff) << 16) | ((('V')) << 8) | ((37))): | |||
1212 | case VIDIOC_SUBSCRIBE_EVENT((unsigned long)0x80000000 | ((sizeof(struct v4l2_event_subscription ) & 0x1fff) << 16) | ((('V')) << 8) | ((90))): | |||
1213 | case VIDIOC_S_EXT_CTRLS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_ext_controls) & 0x1fff) << 16) | ((('V' )) << 8) | ((72))): | |||
1214 | case VIDIOC_S_SELECTION(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_selection) & 0x1fff) << 16) | ((('V')) << 8) | ((95))): | |||
1215 | case VIDIOC_TRY_DECODER_CMD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_decoder_cmd) & 0x1fff) << 16) | ((('V' )) << 8) | ((97))): | |||
1216 | case VIDIOC_TRY_ENCODER_CMD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_encoder_cmd) & 0x1fff) << 16) | ((('V' )) << 8) | ((78))): | |||
1217 | if (fp->f_type == DTYPE_VNODE1 && | |||
1218 | vp->v_type == VCHR && | |||
1219 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == videoopen) | |||
1220 | return (0); | |||
1221 | break; | |||
1222 | } | |||
1223 | } | |||
1224 | #endif | |||
1225 | ||||
1226 | #if NPF1 > 0 | |||
1227 | if ((pledge & PLEDGE_PF0x0000000004000000ULL)) { | |||
1228 | switch (com) { | |||
1229 | case DIOCADDRULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_rule) & 0x1fff) << 16) | ((('D')) << 8) | ((4))): | |||
1230 | case DIOCGETSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pf_status) & 0x1fff) << 16) | ((('D')) << 8) | ((21))): | |||
1231 | case DIOCNATLOOK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_natlook) & 0x1fff) << 16) | ((('D')) << 8) | ((23))): | |||
1232 | case DIOCRADDTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((61))): | |||
1233 | case DIOCRCLRADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((66))): | |||
1234 | case DIOCRCLRTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((60))): | |||
1235 | case DIOCRCLRTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((65))): | |||
1236 | case DIOCRGETTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((64))): | |||
1237 | case DIOCRSETADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((69))): | |||
1238 | case DIOCXBEGIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_trans) & 0x1fff) << 16) | ((('D')) << 8) | ((81))): | |||
1239 | case DIOCXCOMMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_trans) & 0x1fff) << 16) | ((('D')) << 8) | ((82))): | |||
1240 | case DIOCKILLSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_src_node_kill) & 0x1fff) << 16) | ((( 'D')) << 8) | ((91))): | |||
1241 | if ((fp->f_type == DTYPE_VNODE1) && | |||
1242 | (vp->v_type == VCHR) && | |||
1243 | (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == pfopen)) | |||
1244 | return (0); | |||
1245 | break; | |||
1246 | } | |||
1247 | } | |||
1248 | #endif | |||
1249 | ||||
1250 | if ((pledge & PLEDGE_TTY0x0000000000010000ULL)) { | |||
1251 | switch (com) { | |||
1252 | #if NPTY16 > 0 | |||
1253 | case PTMGET((unsigned long)0x40000000 | ((sizeof(struct ptmget) & 0x1fff ) << 16) | ((('t')) << 8) | ((1))): | |||
1254 | if ((pledge & PLEDGE_RPATH0x0000000000000001ULL) == 0) | |||
1255 | break; | |||
1256 | if ((pledge & PLEDGE_WPATH0x0000000000000002ULL) == 0) | |||
1257 | break; | |||
1258 | if (fp->f_type != DTYPE_VNODE1 || vp->v_type != VCHR) | |||
1259 | break; | |||
1260 | if (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open != ptmopen) | |||
1261 | break; | |||
1262 | return (0); | |||
1263 | case TIOCUCNTL((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((102))): /* vmd */ | |||
1264 | if ((pledge & PLEDGE_RPATH0x0000000000000001ULL) == 0) | |||
1265 | break; | |||
1266 | if ((pledge & PLEDGE_WPATH0x0000000000000002ULL) == 0) | |||
1267 | break; | |||
1268 | if (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open != ptcopen) | |||
| ||||
1269 | break; | |||
1270 | return (0); | |||
1271 | #endif /* NPTY > 0 */ | |||
1272 | case TIOCSPGRP((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((118))): | |||
1273 | if ((pledge & PLEDGE_PROC0x0000000000001000ULL) == 0) | |||
1274 | break; | |||
1275 | /* FALLTHROUGH */ | |||
1276 | case TIOCFLUSH((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((16))): /* getty, telnet */ | |||
1277 | case TIOCSTART((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((110))): /* emacs, etc */ | |||
1278 | case TIOCGPGRP((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((119))): | |||
1279 | case TIOCGETA((unsigned long)0x40000000 | ((sizeof(struct termios) & 0x1fff ) << 16) | ((('t')) << 8) | ((19))): | |||
1280 | case TIOCGWINSZ((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff ) << 16) | ((('t')) << 8) | ((104))): /* ENOTTY return for non-tty */ | |||
1281 | case TIOCSTAT((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((101))): /* csh */ | |||
1282 | if (fp->f_type == DTYPE_VNODE1 && (vp->v_flag & VISTTY0x0008)) | |||
1283 | return (0); | |||
1284 | return (ENOTTY25); | |||
1285 | case TIOCSWINSZ((unsigned long)0x80000000 | ((sizeof(struct winsize) & 0x1fff ) << 16) | ((('t')) << 8) | ((103))): | |||
1286 | case TIOCEXT((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((96))): /* mail, libedit .. */ | |||
1287 | case TIOCCBRK((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((122))): /* cu */ | |||
1288 | case TIOCSBRK((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((123))): /* cu */ | |||
1289 | case TIOCCDTR((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((120))): /* cu */ | |||
1290 | case TIOCSDTR((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((121))): /* cu */ | |||
1291 | case TIOCEXCL((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((13))): /* cu */ | |||
1292 | case TIOCSETA((unsigned long)0x80000000 | ((sizeof(struct termios) & 0x1fff ) << 16) | ((('t')) << 8) | ((20))): /* cu, ... */ | |||
1293 | case TIOCSETAW((unsigned long)0x80000000 | ((sizeof(struct termios) & 0x1fff ) << 16) | ((('t')) << 8) | ((21))): /* cu, ... */ | |||
1294 | case TIOCSETAF((unsigned long)0x80000000 | ((sizeof(struct termios) & 0x1fff ) << 16) | ((('t')) << 8) | ((22))): /* tcsetattr TCSAFLUSH, script */ | |||
1295 | case TIOCSCTTY((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((97))): /* forkpty(3), login_tty(3), ... */ | |||
1296 | if (fp->f_type == DTYPE_VNODE1 && (vp->v_flag & VISTTY0x0008)) | |||
1297 | return (0); | |||
1298 | break; | |||
1299 | } | |||
1300 | } | |||
1301 | ||||
1302 | if ((pledge & PLEDGE_ROUTE0x0000000000100000ULL)) { | |||
1303 | switch (com) { | |||
1304 | case SIOCGIFADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((33))): | |||
1305 | case SIOCGIFAFLAG_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((73))): | |||
1306 | case SIOCGIFALIFETIME_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((81))): | |||
1307 | case SIOCGIFDESCR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((129))): | |||
1308 | case SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((17))): | |||
1309 | case SIOCGIFMETRIC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((23))): | |||
1310 | case SIOCGIFGMEMB(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((138))): | |||
1311 | case SIOCGIFRDOMAIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((160))): | |||
1312 | case SIOCGIFDSTADDR_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((34))): | |||
1313 | case SIOCGIFNETMASK_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((37))): | |||
1314 | case SIOCGIFXFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((158))): | |||
1315 | case SIOCGNBRINFO_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_nbrinfo) & 0x1fff) << 16) | ((('i')) << 8) | ((78))): | |||
1316 | case SIOCGIFINFO_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ndireq) & 0x1fff) << 16) | ((('i')) << 8) | ((108))): | |||
1317 | case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifmediareq) & 0x1fff) << 16) | ((('i')) << 8) | ((56))): | |||
1318 | if (fp->f_type == DTYPE_SOCKET2) | |||
1319 | return (0); | |||
1320 | break; | |||
1321 | } | |||
1322 | } | |||
1323 | ||||
1324 | if ((pledge & PLEDGE_WROUTE0x0000000800000000ULL)) { | |||
1325 | switch (com) { | |||
1326 | case SIOCAIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifaliasreq) & 0x1fff) << 16) | ((('i')) << 8) | ((26))): | |||
1327 | case SIOCDIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((25))): | |||
1328 | case SIOCAIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_aliasreq) & 0x1fff) << 16) | ((('i')) << 8) | ((26))): | |||
1329 | case SIOCDIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((25))): | |||
1330 | if (fp->f_type == DTYPE_SOCKET2) | |||
1331 | return (0); | |||
1332 | break; | |||
1333 | case SIOCSIFMTU((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((127))): | |||
1334 | if (fp->f_type == DTYPE_SOCKET2) | |||
1335 | return (0); | |||
1336 | break; | |||
1337 | } | |||
1338 | } | |||
1339 | ||||
1340 | #if NVMM1 > 0 | |||
1341 | if ((pledge & PLEDGE_VMM0x0000000040000000ULL)) { | |||
1342 | if ((fp->f_type == DTYPE_VNODE1) && | |||
1343 | (vp->v_type == VCHR) && | |||
1344 | (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == vmmopen)) { | |||
1345 | error = pledge_ioctl_vmm(p, com); | |||
1346 | if (error == 0) | |||
1347 | return 0; | |||
1348 | } | |||
1349 | } | |||
1350 | #endif | |||
1351 | ||||
1352 | return pledge_fail(p, error, PLEDGE_TTY0x0000000000010000ULL); | |||
1353 | } | |||
1354 | ||||
1355 | int | |||
1356 | pledge_sockopt(struct proc *p, int set, int level, int optname) | |||
1357 | { | |||
1358 | uint64_t pledge; | |||
1359 | ||||
1360 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1361 | return (0); | |||
1362 | pledge = READ_ONCE(p->p_p->ps_pledge)({ typeof(p->p_p->ps_pledge) __tmp = *(volatile typeof( p->p_p->ps_pledge) *)&(p->p_p->ps_pledge); membar_datadep_consumer (); __tmp; }); | |||
1363 | ||||
1364 | /* Always allow these, which are too common to reject */ | |||
1365 | switch (level) { | |||
1366 | case SOL_SOCKET0xffff: | |||
1367 | switch (optname) { | |||
1368 | case SO_RCVBUF0x1002: | |||
1369 | case SO_ERROR0x1007: | |||
1370 | return (0); | |||
1371 | } | |||
1372 | break; | |||
1373 | case IPPROTO_TCP6: | |||
1374 | switch (optname) { | |||
1375 | case TCP_NODELAY0x01: | |||
1376 | return (0); | |||
1377 | } | |||
1378 | break; | |||
1379 | } | |||
1380 | ||||
1381 | if ((pledge & PLEDGE_WROUTE0x0000000800000000ULL)) { | |||
1382 | switch (level) { | |||
1383 | case SOL_SOCKET0xffff: | |||
1384 | switch (optname) { | |||
1385 | case SO_RTABLE0x1021: | |||
1386 | return (0); | |||
1387 | } | |||
1388 | } | |||
1389 | } | |||
1390 | ||||
1391 | if ((pledge & (PLEDGE_INET0x0000000000000040ULL|PLEDGE_UNIX0x0000000000000100ULL|PLEDGE_DNS0x0000000000000020ULL)) == 0) | |||
1392 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
1393 | /* In use by some service libraries */ | |||
1394 | switch (level) { | |||
1395 | case SOL_SOCKET0xffff: | |||
1396 | switch (optname) { | |||
1397 | case SO_TIMESTAMP0x0800: | |||
1398 | return (0); | |||
1399 | } | |||
1400 | break; | |||
1401 | } | |||
1402 | ||||
1403 | /* DNS resolver may do these requests */ | |||
1404 | if ((pledge & PLEDGE_DNS0x0000000000000020ULL)) { | |||
1405 | switch (level) { | |||
1406 | case IPPROTO_IPV641: | |||
1407 | switch (optname) { | |||
1408 | case IPV6_RECVPKTINFO36: | |||
1409 | case IPV6_USE_MIN_MTU42: | |||
1410 | return (0); | |||
1411 | } | |||
1412 | } | |||
1413 | } | |||
1414 | ||||
1415 | if ((pledge & (PLEDGE_INET0x0000000000000040ULL|PLEDGE_UNIX0x0000000000000100ULL)) == 0) | |||
1416 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
1417 | switch (level) { | |||
1418 | case SOL_SOCKET0xffff: | |||
1419 | switch (optname) { | |||
1420 | case SO_RTABLE0x1021: | |||
1421 | return pledge_fail(p, EINVAL22, PLEDGE_WROUTE0x0000000800000000ULL); | |||
1422 | } | |||
1423 | return (0); | |||
1424 | } | |||
1425 | ||||
1426 | if ((pledge & PLEDGE_INET0x0000000000000040ULL) == 0) | |||
1427 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
1428 | switch (level) { | |||
1429 | case IPPROTO_TCP6: | |||
1430 | switch (optname) { | |||
1431 | case TCP_MD5SIG0x04: | |||
1432 | case TCP_SACK_ENABLE0x08: | |||
1433 | case TCP_MAXSEG0x02: | |||
1434 | case TCP_NOPUSH0x10: | |||
1435 | case TCP_INFO0x09: | |||
1436 | return (0); | |||
1437 | } | |||
1438 | break; | |||
1439 | case IPPROTO_IP0: | |||
1440 | switch (optname) { | |||
1441 | case IP_OPTIONS1: | |||
1442 | if (!set) | |||
1443 | return (0); | |||
1444 | break; | |||
1445 | case IP_TOS3: | |||
1446 | case IP_TTL4: | |||
1447 | case IP_MINTTL32: | |||
1448 | case IP_IPDEFTTL37: | |||
1449 | case IP_PORTRANGE19: | |||
1450 | case IP_RECVDSTADDR7: | |||
1451 | case IP_RECVDSTPORT33: | |||
1452 | return (0); | |||
1453 | case IP_MULTICAST_IF9: | |||
1454 | case IP_MULTICAST_TTL10: | |||
1455 | case IP_MULTICAST_LOOP11: | |||
1456 | case IP_ADD_MEMBERSHIP12: | |||
1457 | case IP_DROP_MEMBERSHIP13: | |||
1458 | if (pledge & PLEDGE_MCAST0x0000000000200000ULL) | |||
1459 | return (0); | |||
1460 | break; | |||
1461 | } | |||
1462 | break; | |||
1463 | case IPPROTO_ICMP1: | |||
1464 | break; | |||
1465 | case IPPROTO_IPV641: | |||
1466 | switch (optname) { | |||
1467 | case IPV6_TCLASS61: | |||
1468 | case IPV6_UNICAST_HOPS4: | |||
1469 | case IPV6_MINHOPCOUNT65: | |||
1470 | case IPV6_RECVHOPLIMIT37: | |||
1471 | case IPV6_PORTRANGE14: | |||
1472 | case IPV6_RECVPKTINFO36: | |||
1473 | case IPV6_RECVDSTPORT64: | |||
1474 | case IPV6_V6ONLY27: | |||
1475 | return (0); | |||
1476 | case IPV6_MULTICAST_IF9: | |||
1477 | case IPV6_MULTICAST_HOPS10: | |||
1478 | case IPV6_MULTICAST_LOOP11: | |||
1479 | case IPV6_JOIN_GROUP12: | |||
1480 | case IPV6_LEAVE_GROUP13: | |||
1481 | if (pledge & PLEDGE_MCAST0x0000000000200000ULL) | |||
1482 | return (0); | |||
1483 | break; | |||
1484 | } | |||
1485 | break; | |||
1486 | case IPPROTO_ICMPV658: | |||
1487 | break; | |||
1488 | } | |||
1489 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
1490 | } | |||
1491 | ||||
1492 | int | |||
1493 | pledge_socket(struct proc *p, int domain, unsigned int state) | |||
1494 | { | |||
1495 | uint64_t pledge; | |||
1496 | ||||
1497 | if (!ISSET(p->p_p->ps_flags, PS_PLEDGE)((p->p_p->ps_flags) & (0x00100000))) | |||
1498 | return 0; | |||
1499 | pledge = READ_ONCE(p->p_p->ps_pledge)({ typeof(p->p_p->ps_pledge) __tmp = *(volatile typeof( p->p_p->ps_pledge) *)&(p->p_p->ps_pledge); membar_datadep_consumer (); __tmp; }); | |||
1500 | ||||
1501 | if (ISSET(state, SS_DNS)((state) & (0x4000))) { | |||
1502 | if (ISSET(pledge, PLEDGE_DNS)((pledge) & (0x0000000000000020ULL))) | |||
1503 | return 0; | |||
1504 | return pledge_fail(p, EPERM1, PLEDGE_DNS0x0000000000000020ULL); | |||
1505 | } | |||
1506 | ||||
1507 | switch (domain) { | |||
1508 | case -1: /* accept on any domain */ | |||
1509 | return (0); | |||
1510 | case AF_INET2: | |||
1511 | case AF_INET624: | |||
1512 | if (ISSET(pledge, PLEDGE_INET)((pledge) & (0x0000000000000040ULL))) | |||
1513 | return 0; | |||
1514 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
1515 | ||||
1516 | case AF_UNIX1: | |||
1517 | if (ISSET(pledge, PLEDGE_UNIX)((pledge) & (0x0000000000000100ULL))) | |||
1518 | return 0; | |||
1519 | return pledge_fail(p, EPERM1, PLEDGE_UNIX0x0000000000000100ULL); | |||
1520 | } | |||
1521 | ||||
1522 | return pledge_fail(p, EINVAL22, PLEDGE_INET0x0000000000000040ULL); | |||
1523 | } | |||
1524 | ||||
1525 | int | |||
1526 | pledge_flock(struct proc *p) | |||
1527 | { | |||
1528 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1529 | return (0); | |||
1530 | ||||
1531 | if ((p->p_p->ps_pledge & PLEDGE_FLOCK0x0000000000000080ULL)) | |||
1532 | return (0); | |||
1533 | return (pledge_fail(p, EPERM1, PLEDGE_FLOCK0x0000000000000080ULL)); | |||
1534 | } | |||
1535 | ||||
1536 | int | |||
1537 | pledge_swapctl(struct proc *p, int cmd) | |||
1538 | { | |||
1539 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1540 | return (0); | |||
1541 | ||||
1542 | if (p->p_p->ps_pledge & PLEDGE_VMINFO0x0000000000400000ULL) { | |||
1543 | switch (cmd) { | |||
1544 | case SWAP_NSWAP3: | |||
1545 | case SWAP_STATS4: | |||
1546 | return (0); | |||
1547 | } | |||
1548 | } | |||
1549 | ||||
1550 | return pledge_fail(p, EPERM1, PLEDGE_VMINFO0x0000000000400000ULL); | |||
1551 | } | |||
1552 | ||||
1553 | /* bsearch over pledgereq. return flags value if found, 0 else */ | |||
1554 | uint64_t | |||
1555 | pledgereq_flags(const char *req_name) | |||
1556 | { | |||
1557 | int base = 0, cmp, i, lim; | |||
1558 | ||||
1559 | for (lim = nitems(pledgereq)(sizeof((pledgereq)) / sizeof((pledgereq)[0])); lim != 0; lim >>= 1) { | |||
1560 | i = base + (lim >> 1); | |||
1561 | cmp = strcmp(req_name, pledgereq[i].name); | |||
1562 | if (cmp == 0) | |||
1563 | return (pledgereq[i].flags); | |||
1564 | if (cmp > 0) { /* not found before, move right */ | |||
1565 | base = i + 1; | |||
1566 | lim--; | |||
1567 | } /* else move left */ | |||
1568 | } | |||
1569 | return (0); | |||
1570 | } | |||
1571 | ||||
1572 | int | |||
1573 | pledge_fcntl(struct proc *p, int cmd) | |||
1574 | { | |||
1575 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1576 | return (0); | |||
1577 | if ((p->p_p->ps_pledge & PLEDGE_PROC0x0000000000001000ULL) == 0 && cmd == F_SETOWN6) | |||
1578 | return pledge_fail(p, EPERM1, PLEDGE_PROC0x0000000000001000ULL); | |||
1579 | return (0); | |||
1580 | } | |||
1581 | ||||
1582 | int | |||
1583 | pledge_kill(struct proc *p, pid_t pid) | |||
1584 | { | |||
1585 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1586 | return 0; | |||
1587 | if (p->p_p->ps_pledge & PLEDGE_PROC0x0000000000001000ULL) | |||
1588 | return 0; | |||
1589 | if (pid == 0 || pid == p->p_p->ps_pid) | |||
1590 | return 0; | |||
1591 | return pledge_fail(p, EPERM1, PLEDGE_PROC0x0000000000001000ULL); | |||
1592 | } | |||
1593 | ||||
1594 | int | |||
1595 | pledge_profil(struct proc *p, u_int scale) | |||
1596 | { | |||
1597 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1598 | return 0; | |||
1599 | if (scale != 0) | |||
1600 | return pledge_fail(p, EPERM1, PLEDGE_STDIO0x0000000000000008ULL); | |||
1601 | return 0; | |||
1602 | } | |||
1603 | ||||
1604 | int | |||
1605 | pledge_protexec(struct proc *p, int prot) | |||
1606 | { | |||
1607 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
1608 | return 0; | |||
1609 | /* Before kbind(2) call, ld.so and crt may create EXEC mappings */ | |||
1610 | if (p->p_p->ps_kbind_addr == 0 && p->p_p->ps_kbind_cookie == 0) | |||
1611 | return 0; | |||
1612 | if (!(p->p_p->ps_pledge & PLEDGE_PROTEXEC0x0000000000008000ULL) && (prot & PROT_EXEC0x04)) | |||
1613 | return pledge_fail(p, EPERM1, PLEDGE_PROTEXEC0x0000000000008000ULL); | |||
1614 | return 0; | |||
1615 | } | |||
1616 | ||||
1617 | int | |||
1618 | canonpath(const char *input, char *buf, size_t bufsize) | |||
1619 | { | |||
1620 | const char *p; | |||
1621 | char *q; | |||
1622 | ||||
1623 | /* can't canon relative paths, don't bother */ | |||
1624 | if (input[0] != '/') { | |||
1625 | if (strlcpy(buf, input, bufsize) >= bufsize) | |||
1626 | return ENAMETOOLONG63; | |||
1627 | return 0; | |||
1628 | } | |||
1629 | ||||
1630 | p = input; | |||
1631 | q = buf; | |||
1632 | while (*p && (q - buf < bufsize)) { | |||
1633 | if (p[0] == '/' && (p[1] == '/' || p[1] == '\0')) { | |||
1634 | p += 1; | |||
1635 | ||||
1636 | } else if (p[0] == '/' && p[1] == '.' && | |||
1637 | (p[2] == '/' || p[2] == '\0')) { | |||
1638 | p += 2; | |||
1639 | ||||
1640 | } else if (p[0] == '/' && p[1] == '.' && p[2] == '.' && | |||
1641 | (p[3] == '/' || p[3] == '\0')) { | |||
1642 | p += 3; | |||
1643 | if (q != buf) /* "/../" at start of buf */ | |||
1644 | while (*--q != '/') | |||
1645 | continue; | |||
1646 | ||||
1647 | } else { | |||
1648 | *q++ = *p++; | |||
1649 | } | |||
1650 | } | |||
1651 | if ((*p == '\0') && (q - buf < bufsize)) { | |||
1652 | *q = 0; | |||
1653 | return 0; | |||
1654 | } else | |||
1655 | return ENAMETOOLONG63; | |||
1656 | } |