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