xref: /openbsd-src/sys/kern/kern_pledge.c (revision 25c4e8bd056e974b28f4a0ffd39d76c190a56013)
1 /*	$OpenBSD: kern_pledge.c,v 1.290 2022/07/18 18:02:27 jca 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/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 #include <sys/swap.h>
38 
39 #include <sys/ioctl.h>
40 #include <sys/termios.h>
41 #include <sys/tty.h>
42 #include <sys/device.h>
43 #include <sys/disklabel.h>
44 #include <sys/dkio.h>
45 #include <sys/mtio.h>
46 #include <sys/audioio.h>
47 #include <sys/videoio.h>
48 #include <net/bpf.h>
49 #include <net/route.h>
50 #include <net/if.h>
51 #include <net/if_var.h>
52 #include <netinet/in.h>
53 #include <netinet6/in6_var.h>
54 #include <netinet6/nd6.h>
55 #include <netinet/tcp.h>
56 #include <net/pfvar.h>
57 
58 #include <sys/conf.h>
59 #include <sys/specdev.h>
60 #include <sys/signal.h>
61 #include <sys/signalvar.h>
62 #include <sys/syscall.h>
63 #include <sys/syscallargs.h>
64 #include <sys/systm.h>
65 
66 #include <dev/biovar.h>
67 
68 #define PLEDGENAMES
69 #include <sys/pledge.h>
70 
71 #include "audio.h"
72 #include "bpfilter.h"
73 #include "pf.h"
74 #include "video.h"
75 #include "pty.h"
76 
77 #if defined(__amd64__)
78 #include "vmm.h"
79 #if NVMM > 0
80 #include <machine/conf.h>
81 #endif
82 #endif
83 
84 #include "drm.h"
85 
86 uint64_t pledgereq_flags(const char *req);
87 int	 parsepledges(struct proc *p, const char *kname,
88 	    const char *promises, u_int64_t *fp);
89 int	 canonpath(const char *input, char *buf, size_t bufsize);
90 void	 unveil_destroy(struct process *ps);
91 
92 /* #define DEBUG_PLEDGE */
93 #ifdef DEBUG_PLEDGE
94 int debug_pledge = 1;
95 #define DPRINTF(x...)    do { if (debug_pledge) printf(x); } while (0)
96 #define DNPRINTF(n,x...) do { if (debug_pledge >= (n)) printf(x); } while (0)
97 #else
98 #define DPRINTF(x...)
99 #define DNPRINTF(n,x...)
100 #endif
101 
102 /*
103  * Ordered in blocks starting with least risky and most required.
104  */
105 const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = {
106 	/*
107 	 * Minimum required
108 	 */
109 	[SYS_exit] = PLEDGE_ALWAYS,
110 	[SYS_kbind] = PLEDGE_ALWAYS,
111 	[SYS_msyscall] = PLEDGE_ALWAYS,
112 	[SYS___get_tcb] = PLEDGE_ALWAYS,
113 	[SYS___set_tcb] = PLEDGE_ALWAYS,
114 	[SYS_pledge] = PLEDGE_ALWAYS,
115 	[SYS_sendsyslog] = PLEDGE_ALWAYS,	/* stack protector reporting */
116 	[SYS_thrkill] = PLEDGE_ALWAYS,		/* raise, abort, stack pro */
117 	[SYS_utrace] = PLEDGE_ALWAYS,		/* ltrace(1) from ld.so */
118 
119 	/* "getting" information about self is considered safe */
120 	[SYS_getuid] = PLEDGE_STDIO,
121 	[SYS_geteuid] = PLEDGE_STDIO,
122 	[SYS_getresuid] = PLEDGE_STDIO,
123 	[SYS_getgid] = PLEDGE_STDIO,
124 	[SYS_getegid] = PLEDGE_STDIO,
125 	[SYS_getresgid] = PLEDGE_STDIO,
126 	[SYS_getgroups] = PLEDGE_STDIO,
127 	[SYS_getlogin_r] = PLEDGE_STDIO,
128 	[SYS_getpgrp] = PLEDGE_STDIO,
129 	[SYS_getpgid] = PLEDGE_STDIO,
130 	[SYS_getppid] = PLEDGE_STDIO,
131 	[SYS_getsid] = PLEDGE_STDIO,
132 	[SYS_getthrid] = PLEDGE_STDIO,
133 	[SYS_getrlimit] = PLEDGE_STDIO,
134 	[SYS_getrtable] = PLEDGE_STDIO,
135 	[SYS_gettimeofday] = PLEDGE_STDIO,
136 	[SYS_getdtablecount] = PLEDGE_STDIO,
137 	[SYS_getrusage] = PLEDGE_STDIO,
138 	[SYS_issetugid] = PLEDGE_STDIO,
139 	[SYS_clock_getres] = PLEDGE_STDIO,
140 	[SYS_clock_gettime] = PLEDGE_STDIO,
141 	[SYS_getpid] = PLEDGE_STDIO,
142 
143 	/*
144 	 * Almost exclusively read-only, Very narrow subset.
145 	 * Use of "route", "inet", "dns", "ps", or "vminfo"
146 	 * expands access.
147 	 */
148 	[SYS_sysctl] = PLEDGE_STDIO,
149 
150 	/* Support for malloc(3) family of operations */
151 	[SYS_getentropy] = PLEDGE_STDIO,
152 	[SYS_madvise] = PLEDGE_STDIO,
153 	[SYS_minherit] = PLEDGE_STDIO,
154 	[SYS_mmap] = PLEDGE_STDIO,
155 	[SYS_mprotect] = PLEDGE_STDIO,
156 	[SYS_mquery] = PLEDGE_STDIO,
157 	[SYS_munmap] = PLEDGE_STDIO,
158 	[SYS_msync] = PLEDGE_STDIO,
159 	[SYS_break] = PLEDGE_STDIO,
160 
161 	[SYS_umask] = PLEDGE_STDIO,
162 
163 	/* read/write operations */
164 	[SYS_read] = PLEDGE_STDIO,
165 	[SYS_readv] = PLEDGE_STDIO,
166 	[SYS_pread] = PLEDGE_STDIO,
167 	[SYS_preadv] = PLEDGE_STDIO,
168 	[SYS_write] = PLEDGE_STDIO,
169 	[SYS_writev] = PLEDGE_STDIO,
170 	[SYS_pwrite] = PLEDGE_STDIO,
171 	[SYS_pwritev] = PLEDGE_STDIO,
172 	[SYS_recvmsg] = PLEDGE_STDIO,
173 	[SYS_recvfrom] = PLEDGE_STDIO,
174 	[SYS_ftruncate] = PLEDGE_STDIO,
175 	[SYS_lseek] = PLEDGE_STDIO,
176 	[SYS_fpathconf] = PLEDGE_STDIO,
177 
178 	/*
179 	 * Address selection required a network pledge ("inet",
180 	 * "unix", "dns".
181 	 */
182 	[SYS_sendto] = PLEDGE_STDIO,
183 
184 	/*
185 	 * Address specification required a network pledge ("inet",
186 	 * "unix", "dns".  SCM_RIGHTS requires "sendfd" or "recvfd".
187 	 */
188 	[SYS_sendmsg] = PLEDGE_STDIO,
189 
190 	/* Common signal operations */
191 	[SYS_nanosleep] = PLEDGE_STDIO,
192 	[SYS_sigaltstack] = PLEDGE_STDIO,
193 	[SYS_sigprocmask] = PLEDGE_STDIO,
194 	[SYS_sigsuspend] = PLEDGE_STDIO,
195 	[SYS_sigaction] = PLEDGE_STDIO,
196 	[SYS_sigreturn] = PLEDGE_STDIO,
197 	[SYS_sigpending] = PLEDGE_STDIO,
198 	[SYS_getitimer] = PLEDGE_STDIO,
199 	[SYS_setitimer] = PLEDGE_STDIO,
200 
201 	/*
202 	 * To support event driven programming.
203 	 */
204 	[SYS_poll] = PLEDGE_STDIO,
205 	[SYS_ppoll] = PLEDGE_STDIO,
206 	[SYS_kevent] = PLEDGE_STDIO,
207 	[SYS_kqueue] = PLEDGE_STDIO,
208 	[SYS_select] = PLEDGE_STDIO,
209 	[SYS_pselect] = PLEDGE_STDIO,
210 
211 	[SYS_fstat] = PLEDGE_STDIO,
212 	[SYS_fsync] = PLEDGE_STDIO,
213 
214 	[SYS_setsockopt] = PLEDGE_STDIO,	/* narrow whitelist */
215 	[SYS_getsockopt] = PLEDGE_STDIO,	/* narrow whitelist */
216 
217 	/* F_SETOWN requires PLEDGE_PROC */
218 	[SYS_fcntl] = PLEDGE_STDIO,
219 
220 	[SYS_close] = PLEDGE_STDIO,
221 	[SYS_dup] = PLEDGE_STDIO,
222 	[SYS_dup2] = PLEDGE_STDIO,
223 	[SYS_dup3] = PLEDGE_STDIO,
224 	[SYS_closefrom] = PLEDGE_STDIO,
225 	[SYS_shutdown] = PLEDGE_STDIO,
226 	[SYS_fchdir] = PLEDGE_STDIO,	/* XXX consider tightening */
227 
228 	[SYS_pipe] = PLEDGE_STDIO,
229 	[SYS_pipe2] = PLEDGE_STDIO,
230 	[SYS_socketpair] = PLEDGE_STDIO,
231 
232 	[SYS_wait4] = PLEDGE_STDIO,
233 
234 	/*
235 	 * Can kill self with "stdio".  Killing another pid
236 	 * requires "proc"
237 	 */
238 	[SYS_kill] = PLEDGE_STDIO,
239 
240 	/*
241 	 * FIONREAD/FIONBIO for "stdio"
242 	 * Other ioctl are selectively allowed based upon other pledges.
243 	 */
244 	[SYS_ioctl] = PLEDGE_STDIO,
245 
246 	/*
247 	 * Path access/creation calls encounter many extensive
248 	 * checks done during pledge_namei()
249 	 */
250 	[SYS_open] = PLEDGE_STDIO,
251 	[SYS_stat] = PLEDGE_STDIO,
252 	[SYS_access] = PLEDGE_STDIO,
253 	[SYS_readlink] = PLEDGE_STDIO,
254 	[SYS___realpath] = PLEDGE_STDIO,
255 
256 	[SYS_adjtime] = PLEDGE_STDIO,   /* setting requires "settime" */
257 	[SYS_adjfreq] = PLEDGE_SETTIME,
258 	[SYS_settimeofday] = PLEDGE_SETTIME,
259 
260 	/*
261 	 * Needed by threaded programs
262 	 * XXX should we have a new "threads"?
263 	 */
264 	[SYS___tfork] = PLEDGE_STDIO,
265 	[SYS_sched_yield] = PLEDGE_STDIO,
266 	[SYS_futex] = PLEDGE_STDIO,
267 	[SYS___thrsleep] = PLEDGE_STDIO,
268 	[SYS___thrwakeup] = PLEDGE_STDIO,
269 	[SYS___threxit] = PLEDGE_STDIO,
270 	[SYS___thrsigdivert] = PLEDGE_STDIO,
271 
272 	[SYS_fork] = PLEDGE_PROC,
273 	[SYS_vfork] = PLEDGE_PROC,
274 	[SYS_setpgid] = PLEDGE_PROC,
275 	[SYS_setsid] = PLEDGE_PROC,
276 
277 	[SYS_setrlimit] = PLEDGE_PROC | PLEDGE_ID,
278 	[SYS_getpriority] = PLEDGE_PROC | PLEDGE_ID,
279 
280 	[SYS_setpriority] = PLEDGE_PROC | PLEDGE_ID,
281 
282 	[SYS_setuid] = PLEDGE_ID,
283 	[SYS_seteuid] = PLEDGE_ID,
284 	[SYS_setreuid] = PLEDGE_ID,
285 	[SYS_setresuid] = PLEDGE_ID,
286 	[SYS_setgid] = PLEDGE_ID,
287 	[SYS_setegid] = PLEDGE_ID,
288 	[SYS_setregid] = PLEDGE_ID,
289 	[SYS_setresgid] = PLEDGE_ID,
290 	[SYS_setgroups] = PLEDGE_ID,
291 	[SYS_setlogin] = PLEDGE_ID,
292 	[SYS_setrtable] = PLEDGE_ID,
293 
294 	[SYS_unveil] = PLEDGE_UNVEIL,
295 
296 	[SYS_execve] = PLEDGE_EXEC,
297 
298 	[SYS_chdir] = PLEDGE_RPATH,
299 	[SYS_openat] = PLEDGE_RPATH | PLEDGE_WPATH,
300 	[SYS_fstatat] = PLEDGE_RPATH | PLEDGE_WPATH,
301 	[SYS_faccessat] = PLEDGE_RPATH | PLEDGE_WPATH,
302 	[SYS_readlinkat] = PLEDGE_RPATH | PLEDGE_WPATH,
303 	[SYS_lstat] = PLEDGE_RPATH | PLEDGE_WPATH | PLEDGE_TMPPATH,
304 	[SYS_truncate] = PLEDGE_WPATH,
305 	[SYS_rename] = PLEDGE_RPATH | PLEDGE_CPATH,
306 	[SYS_rmdir] = PLEDGE_CPATH,
307 	[SYS_renameat] = PLEDGE_CPATH,
308 	[SYS_link] = PLEDGE_CPATH,
309 	[SYS_linkat] = PLEDGE_CPATH,
310 	[SYS_symlink] = PLEDGE_CPATH,
311 	[SYS_symlinkat] = PLEDGE_CPATH,
312 	[SYS_unlink] = PLEDGE_CPATH | PLEDGE_TMPPATH,
313 	[SYS_unlinkat] = PLEDGE_CPATH,
314 	[SYS_mkdir] = PLEDGE_CPATH,
315 	[SYS_mkdirat] = PLEDGE_CPATH,
316 
317 	[SYS_mkfifo] = PLEDGE_DPATH,
318 	[SYS_mkfifoat] = PLEDGE_DPATH,
319 	[SYS_mknod] = PLEDGE_DPATH,
320 	[SYS_mknodat] = PLEDGE_DPATH,
321 
322 	[SYS_revoke] = PLEDGE_TTY,	/* also requires PLEDGE_RPATH */
323 
324 	/*
325 	 * Classify as RPATH|WPATH, because of path information leakage.
326 	 * WPATH due to unknown use of mk*temp(3) on non-/tmp paths..
327 	 */
328 	[SYS___getcwd] = PLEDGE_RPATH | PLEDGE_WPATH,
329 
330 	/* Classify as RPATH, because these leak path information */
331 	[SYS_getdents] = PLEDGE_RPATH,
332 	[SYS_getfsstat] = PLEDGE_RPATH,
333 	[SYS_statfs] = PLEDGE_RPATH,
334 	[SYS_fstatfs] = PLEDGE_RPATH,
335 	[SYS_pathconf] = PLEDGE_RPATH,
336 
337 	[SYS_utimes] = PLEDGE_FATTR,
338 	[SYS_futimes] = PLEDGE_FATTR,
339 	[SYS_utimensat] = PLEDGE_FATTR,
340 	[SYS_futimens] = PLEDGE_FATTR,
341 	[SYS_chmod] = PLEDGE_FATTR,
342 	[SYS_fchmod] = PLEDGE_FATTR,
343 	[SYS_fchmodat] = PLEDGE_FATTR,
344 	[SYS_chflags] = PLEDGE_FATTR,
345 	[SYS_chflagsat] = PLEDGE_FATTR,
346 	[SYS_fchflags] = PLEDGE_FATTR,
347 
348 	[SYS_chown] = PLEDGE_CHOWN,
349 	[SYS_fchownat] = PLEDGE_CHOWN,
350 	[SYS_lchown] = PLEDGE_CHOWN,
351 	[SYS_fchown] = PLEDGE_CHOWN,
352 
353 	[SYS_socket] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS,
354 	[SYS_connect] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS,
355 	[SYS_bind] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS,
356 	[SYS_getsockname] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS,
357 
358 	[SYS_listen] = PLEDGE_INET | PLEDGE_UNIX,
359 	[SYS_accept4] = PLEDGE_INET | PLEDGE_UNIX,
360 	[SYS_accept] = PLEDGE_INET | PLEDGE_UNIX,
361 	[SYS_getpeername] = PLEDGE_INET | PLEDGE_UNIX,
362 
363 	[SYS_flock] = PLEDGE_FLOCK,
364 
365 	[SYS_ypconnect] = PLEDGE_GETPW,
366 
367 	[SYS_swapctl] = PLEDGE_VMINFO,
368 };
369 
370 static const struct {
371 	char *name;
372 	uint64_t flags;
373 } pledgereq[] = {
374 	{ "audio",		PLEDGE_AUDIO },
375 	{ "bpf",		PLEDGE_BPF },
376 	{ "chown",		PLEDGE_CHOWN | PLEDGE_CHOWNUID },
377 	{ "cpath",		PLEDGE_CPATH },
378 	{ "disklabel",		PLEDGE_DISKLABEL },
379 	{ "dns",		PLEDGE_DNS },
380 	{ "dpath",		PLEDGE_DPATH },
381 	{ "drm",		PLEDGE_DRM },
382 	{ "error",		PLEDGE_ERROR },
383 	{ "exec",		PLEDGE_EXEC },
384 	{ "fattr",		PLEDGE_FATTR | PLEDGE_CHOWN },
385 	{ "flock",		PLEDGE_FLOCK },
386 	{ "getpw",		PLEDGE_GETPW },
387 	{ "id",			PLEDGE_ID },
388 	{ "inet",		PLEDGE_INET },
389 	{ "mcast",		PLEDGE_MCAST },
390 	{ "pf",			PLEDGE_PF },
391 	{ "proc",		PLEDGE_PROC },
392 	{ "prot_exec",		PLEDGE_PROTEXEC },
393 	{ "ps",			PLEDGE_PS },
394 	{ "recvfd",		PLEDGE_RECVFD },
395 	{ "route",		PLEDGE_ROUTE },
396 	{ "rpath",		PLEDGE_RPATH },
397 	{ "sendfd",		PLEDGE_SENDFD },
398 	{ "settime",		PLEDGE_SETTIME },
399 	{ "stdio",		PLEDGE_STDIO },
400 	{ "tape",		PLEDGE_TAPE },
401 	{ "tmppath",		PLEDGE_TMPPATH },
402 	{ "tty",		PLEDGE_TTY },
403 	{ "unix",		PLEDGE_UNIX },
404 	{ "unveil",		PLEDGE_UNVEIL },
405 	{ "video",		PLEDGE_VIDEO },
406 	{ "vminfo",		PLEDGE_VMINFO },
407 	{ "vmm",		PLEDGE_VMM },
408 	{ "wpath",		PLEDGE_WPATH },
409 	{ "wroute",		PLEDGE_WROUTE },
410 };
411 
412 int
413 parsepledges(struct proc *p, const char *kname, const char *promises, u_int64_t *fp)
414 {
415 	size_t rbuflen;
416 	char *rbuf, *rp, *pn;
417 	u_int64_t flags = 0, f;
418 	int error;
419 
420 	rbuf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
421 	error = copyinstr(promises, rbuf, MAXPATHLEN,
422 	    &rbuflen);
423 	if (error) {
424 		free(rbuf, M_TEMP, MAXPATHLEN);
425 		return (error);
426 	}
427 #ifdef KTRACE
428 	if (KTRPOINT(p, KTR_STRUCT))
429 		ktrstruct(p, kname, rbuf, rbuflen-1);
430 #endif
431 
432 	for (rp = rbuf; rp && *rp; rp = pn) {
433 		pn = strchr(rp, ' ');	/* find terminator */
434 		if (pn) {
435 			while (*pn == ' ')
436 				*pn++ = '\0';
437 		}
438 		if ((f = pledgereq_flags(rp)) == 0) {
439 			free(rbuf, M_TEMP, MAXPATHLEN);
440 			return (EINVAL);
441 		}
442 		flags |= f;
443 	}
444 	free(rbuf, M_TEMP, MAXPATHLEN);
445 	*fp = flags;
446 	return 0;
447 }
448 
449 int
450 sys_pledge(struct proc *p, void *v, register_t *retval)
451 {
452 	struct sys_pledge_args /* {
453 		syscallarg(const char *)promises;
454 		syscallarg(const char *)execpromises;
455 	} */	*uap = v;
456 	struct process *pr = p->p_p;
457 	uint64_t promises, execpromises;
458 	int error;
459 	int unveil_cleanup = 0;
460 
461 	/* Check for any error in user input */
462 	if (SCARG(uap, promises)) {
463 		error = parsepledges(p, "pledgereq",
464 		    SCARG(uap, promises), &promises);
465 		if (error)
466 			return (error);
467 	}
468 	if (SCARG(uap, execpromises)) {
469 		error = parsepledges(p, "pledgeexecreq",
470 		    SCARG(uap, execpromises), &execpromises);
471 		if (error)
472 			return (error);
473 	}
474 
475 	mtx_enter(&pr->ps_mtx);
476 
477 	/* Check for any error wrt current promises */
478 	if (SCARG(uap, promises)) {
479 		/* In "error" mode, ignore promise increase requests,
480 		 * but accept promise decrease requests */
481 		if (ISSET(pr->ps_flags, PS_PLEDGE) &&
482 		    (pr->ps_pledge & PLEDGE_ERROR))
483 			promises &= (pr->ps_pledge & PLEDGE_USERSET);
484 
485 		/* Only permit reductions */
486 		if (ISSET(pr->ps_flags, PS_PLEDGE) &&
487 		    (((promises | pr->ps_pledge) != pr->ps_pledge))) {
488 			mtx_leave(&pr->ps_mtx);
489 			return (EPERM);
490 		}
491 	}
492 	if (SCARG(uap, execpromises)) {
493 		/* Only permit reductions */
494 		if (ISSET(pr->ps_flags, PS_EXECPLEDGE) &&
495 		    (((execpromises | pr->ps_execpledge) != pr->ps_execpledge))) {
496 			mtx_leave(&pr->ps_mtx);
497 			return (EPERM);
498 		}
499 	}
500 
501 	/* Set up promises */
502 	if (SCARG(uap, promises)) {
503 		pr->ps_pledge = promises;
504 		atomic_setbits_int(&pr->ps_flags, PS_PLEDGE);
505 
506 		if ((pr->ps_pledge & (PLEDGE_RPATH | PLEDGE_WPATH |
507 		    PLEDGE_CPATH | PLEDGE_DPATH | PLEDGE_TMPPATH | PLEDGE_EXEC |
508 		    PLEDGE_UNIX | PLEDGE_UNVEIL)) == 0)
509 			unveil_cleanup = 1;
510 	}
511 	if (SCARG(uap, execpromises)) {
512 		pr->ps_execpledge = execpromises;
513 		atomic_setbits_int(&pr->ps_flags, PS_EXECPLEDGE);
514 	}
515 
516 	mtx_leave(&pr->ps_mtx);
517 
518 	if (unveil_cleanup) {
519 		/*
520 		 * Kill off unveil and drop unveil vnode refs if we no
521 		 * longer are holding any path-accessing pledge
522 		 */
523 		KERNEL_LOCK();
524 		unveil_destroy(pr);
525 		KERNEL_UNLOCK();
526 	}
527 
528 	return (0);
529 }
530 
531 int
532 pledge_syscall(struct proc *p, int code, uint64_t *tval)
533 {
534 	p->p_pledge_syscall = code;
535 	*tval = 0;
536 
537 	if (code < 0 || code > SYS_MAXSYSCALL - 1)
538 		return (EINVAL);
539 
540 	if (pledge_syscalls[code] == PLEDGE_ALWAYS)
541 		return (0);
542 
543 	if (p->p_p->ps_pledge & pledge_syscalls[code])
544 		return (0);
545 
546 	*tval = pledge_syscalls[code];
547 	return (EPERM);
548 }
549 
550 int
551 pledge_fail(struct proc *p, int error, uint64_t code)
552 {
553 	const char *codes = "";
554 	int i;
555 
556 	/* Print first matching pledge */
557 	for (i = 0; code && pledgenames[i].bits != 0; i++)
558 		if (pledgenames[i].bits & code) {
559 			codes = pledgenames[i].name;
560 			break;
561 		}
562 #ifdef KTRACE
563 	if (KTRPOINT(p, KTR_PLEDGE))
564 		ktrpledge(p, error, code, p->p_pledge_syscall);
565 #endif
566 	if (p->p_p->ps_pledge & PLEDGE_ERROR)
567 		return (ENOSYS);
568 
569 	KERNEL_LOCK();
570 	log(LOG_ERR, "%s[%d]: pledge \"%s\", syscall %d\n",
571 	    p->p_p->ps_comm, p->p_p->ps_pid, codes, p->p_pledge_syscall);
572 	p->p_p->ps_acflag |= APLEDGE;
573 
574 	/* Stop threads immediately, because this process is suspect */
575 	if (P_HASSIBLING(p))
576 		single_thread_set(p, SINGLE_SUSPEND, 1);
577 
578 	/* Send uncatchable SIGABRT for coredump */
579 	sigabort(p);
580 
581 	p->p_p->ps_pledge = 0;		/* Disable all PLEDGE_ flags */
582 	KERNEL_UNLOCK();
583 	return (error);
584 }
585 
586 /*
587  * Need to make it more obvious that one cannot get through here
588  * without the right flags set
589  */
590 int
591 pledge_namei(struct proc *p, struct nameidata *ni, char *origpath)
592 {
593 	char path[PATH_MAX];
594 	uint64_t pledge;
595 	int error;
596 
597 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0 ||
598 	    (p->p_p->ps_flags & PS_COREDUMP))
599 		return (0);
600 	pledge = READ_ONCE(p->p_p->ps_pledge);
601 
602 	if (ni->ni_pledge == 0)
603 		panic("pledge_namei: ni_pledge");
604 
605 	/*
606 	 * We set the BYPASSUNVEIL flag to skip unveil checks
607 	 * as necessary
608 	 */
609 
610 	/* Doing a permitted execve() */
611 	if ((ni->ni_pledge & PLEDGE_EXEC) &&
612 	    (pledge & PLEDGE_EXEC))
613 		return (0);
614 
615 	error = canonpath(origpath, path, sizeof(path));
616 	if (error)
617 		return (error);
618 
619 	/* Detect what looks like a mkstemp(3) family operation */
620 	if ((pledge & PLEDGE_TMPPATH) &&
621 	    (p->p_pledge_syscall == SYS_open) &&
622 	    (ni->ni_pledge & PLEDGE_CPATH) &&
623 	    strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) {
624 		ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
625 		return (0);
626 	}
627 
628 	/* Allow unlinking of a mkstemp(3) file...
629 	 * Good opportunity for strict checks here.
630 	 */
631 	if ((pledge & PLEDGE_TMPPATH) &&
632 	    (p->p_pledge_syscall == SYS_unlink) &&
633 	    strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) {
634 		ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
635 		return (0);
636 	}
637 
638 	/* Whitelisted paths */
639 	switch (p->p_pledge_syscall) {
640 	case SYS_access:
641 		/* tzset() needs this. */
642 		if (ni->ni_pledge == PLEDGE_RPATH &&
643 		    strcmp(path, "/etc/localtime") == 0) {
644 			ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
645 			return (0);
646 		}
647 		/*
648 		 * XXX delete before 7.2.
649 		 * Old static binaries may try this file in getpwent and friends
650 		 */
651 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
652 		    (pledge & PLEDGE_GETPW) &&
653 		    strcmp(path, "/var/run/ypbind.lock") == 0) {
654 			ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
655 			return (0);
656 		}
657 		break;
658 	case SYS_open:
659 		/* daemon(3) or other such functions */
660 		if ((ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 &&
661 		    strcmp(path, "/dev/null") == 0) {
662 			ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
663 			return (0);
664 		}
665 
666 		/* readpassphrase(3), getpass(3) */
667 		if ((pledge & PLEDGE_TTY) &&
668 		    (ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 &&
669 		    strcmp(path, "/dev/tty") == 0) {
670 			ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
671 			return (0);
672 		}
673 
674 		/* getpw* and friends need a few files */
675 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
676 		    (pledge & PLEDGE_GETPW)) {
677 			if (strcmp(path, "/etc/spwd.db") == 0)
678 				return (EPERM); /* don't call pledge_fail */
679 			if (strcmp(path, "/etc/pwd.db") == 0) {
680 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
681 				return (0);
682 			}
683 			if (strcmp(path, "/etc/group") == 0) {
684 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
685 				return (0);
686 			}
687 			if (strcmp(path, "/etc/netid") == 0) {
688 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
689 				return (0);
690 			}
691 		}
692 
693 		/* DNS needs /etc/{resolv.conf,hosts,services,protocols}. */
694 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
695 		    (pledge & PLEDGE_DNS)) {
696 			if (strcmp(path, "/etc/resolv.conf") == 0) {
697 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
698 				return (0);
699 			}
700 			if (strcmp(path, "/etc/hosts") == 0) {
701 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
702 				return (0);
703 			}
704 			if (strcmp(path, "/etc/services") == 0) {
705 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
706 				return (0);
707 			}
708 			if (strcmp(path, "/etc/protocols") == 0) {
709 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
710 				return (0);
711 			}
712 		}
713 
714 		/*
715 		 * XXX delete before 7.2.
716 		 * Old static binaries may try this file in getpwent and friends
717 		 */
718 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
719 		    (pledge & PLEDGE_GETPW) &&
720 		    strcmp(path, "/var/run/ypbind.lock") == 0) {
721 			ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
722 			return (0);
723 		}
724 
725 		/* tzset() needs these. */
726 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
727 		    strncmp(path, "/usr/share/zoneinfo/",
728 		    sizeof("/usr/share/zoneinfo/") - 1) == 0)  {
729 			ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
730 			return (0);
731 		}
732 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
733 		    strcmp(path, "/etc/localtime") == 0) {
734 			ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
735 			return (0);
736 		}
737 
738 		break;
739 	case SYS_stat:
740 		/* DNS needs /etc/{resolv.conf,hosts}. */
741 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
742 		    (pledge & PLEDGE_DNS)) {
743 			if (strcmp(path, "/etc/resolv.conf") == 0) {
744 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
745 				return (0);
746 			}
747 			if (strcmp(path, "/etc/hosts") == 0) {
748 				ni->ni_cnd.cn_flags |= BYPASSUNVEIL;
749 				return (0);
750 			}
751 		}
752 		break;
753 	}
754 
755 	/*
756 	 * Ensure each flag of ni_pledge has counterpart allowing it in
757 	 * ps_pledge.
758 	 */
759 	if (ni->ni_pledge & ~pledge)
760 		return (pledge_fail(p, EPERM, (ni->ni_pledge & ~pledge)));
761 
762 	/* continue, and check unveil if present */
763 	return (0);
764 }
765 
766 /*
767  * Only allow reception of safe file descriptors.
768  */
769 int
770 pledge_recvfd(struct proc *p, struct file *fp)
771 {
772 	struct vnode *vp;
773 
774 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
775 		return (0);
776 	if ((p->p_p->ps_pledge & PLEDGE_RECVFD) == 0)
777 		return pledge_fail(p, EPERM, PLEDGE_RECVFD);
778 
779 	switch (fp->f_type) {
780 	case DTYPE_SOCKET:
781 	case DTYPE_PIPE:
782 	case DTYPE_DMABUF:
783 	case DTYPE_SYNC:
784 		return (0);
785 	case DTYPE_VNODE:
786 		vp = fp->f_data;
787 
788 		if (vp->v_type != VDIR)
789 			return (0);
790 	}
791 	return pledge_fail(p, EINVAL, PLEDGE_RECVFD);
792 }
793 
794 /*
795  * Only allow sending of safe file descriptors.
796  */
797 int
798 pledge_sendfd(struct proc *p, struct file *fp)
799 {
800 	struct vnode *vp;
801 
802 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
803 		return (0);
804 	if ((p->p_p->ps_pledge & PLEDGE_SENDFD) == 0)
805 		return pledge_fail(p, EPERM, PLEDGE_SENDFD);
806 
807 	switch (fp->f_type) {
808 	case DTYPE_SOCKET:
809 	case DTYPE_PIPE:
810 	case DTYPE_DMABUF:
811 	case DTYPE_SYNC:
812 		return (0);
813 	case DTYPE_VNODE:
814 		vp = fp->f_data;
815 
816 		if (vp->v_type != VDIR)
817 			return (0);
818 		break;
819 	}
820 	return pledge_fail(p, EINVAL, PLEDGE_SENDFD);
821 }
822 
823 int
824 pledge_sysctl(struct proc *p, int miblen, int *mib, void *new)
825 {
826 	char	buf[80];
827 	uint64_t pledge;
828 	int	i;
829 
830 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
831 		return (0);
832 	pledge = READ_ONCE(p->p_p->ps_pledge);
833 
834 	if (new)
835 		return pledge_fail(p, EFAULT, 0);
836 
837 	/* routing table observation */
838 	if ((pledge & PLEDGE_ROUTE)) {
839 		if ((miblen == 6 || miblen == 7) &&
840 		    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
841 		    mib[2] == 0 &&
842 		    mib[4] == NET_RT_DUMP)
843 			return (0);
844 
845 		if (miblen == 6 &&
846 		    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
847 		    mib[2] == 0 &&
848 		    (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) &&
849 		    (mib[4] == NET_RT_TABLE || mib[4] == NET_RT_SOURCE))
850 			return (0);
851 
852 		if (miblen == 7 &&		/* exposes MACs */
853 		    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
854 		    mib[2] == 0 &&
855 		    (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) &&
856 		    mib[4] == NET_RT_FLAGS && mib[5] == RTF_LLINFO)
857 			return (0);
858 	}
859 
860 	if ((pledge & PLEDGE_WROUTE)) {
861 		if (miblen == 4 &&
862 		    mib[0] == CTL_NET && mib[1] == PF_INET6 &&
863 		    mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_SOIIKEY)
864 			return (0);
865 	}
866 
867 	if (pledge & (PLEDGE_PS | PLEDGE_VMINFO)) {
868 		if (miblen == 2 &&		/* kern.fscale */
869 		    mib[0] == CTL_KERN && mib[1] == KERN_FSCALE)
870 			return (0);
871 		if (miblen == 2 &&		/* kern.boottime */
872 		    mib[0] == CTL_KERN && mib[1] == KERN_BOOTTIME)
873 			return (0);
874 		if (miblen == 2 &&		/* kern.consdev */
875 		    mib[0] == CTL_KERN && mib[1] == KERN_CONSDEV)
876 			return (0);
877 		if (miblen == 2 &&			/* kern.cptime */
878 		    mib[0] == CTL_KERN && mib[1] == KERN_CPTIME)
879 			return (0);
880 		if (miblen == 3 &&			/* kern.cptime2 */
881 		    mib[0] == CTL_KERN && mib[1] == KERN_CPTIME2)
882 			return (0);
883 		if (miblen == 3 &&			/* kern.cpustats */
884 		    mib[0] == CTL_KERN && mib[1] == KERN_CPUSTATS)
885 			return (0);
886 	}
887 
888 	if ((pledge & PLEDGE_PS)) {
889 		if (miblen == 4 &&		/* kern.procargs.* */
890 		    mib[0] == CTL_KERN && mib[1] == KERN_PROC_ARGS &&
891 		    (mib[3] == KERN_PROC_ARGV || mib[3] == KERN_PROC_ENV))
892 			return (0);
893 		if (miblen == 6 &&		/* kern.proc.* */
894 		    mib[0] == CTL_KERN && mib[1] == KERN_PROC)
895 			return (0);
896 		if (miblen == 3 &&		/* kern.proc_cwd.* */
897 		    mib[0] == CTL_KERN && mib[1] == KERN_PROC_CWD)
898 			return (0);
899 		if (miblen == 2 &&		/* kern.ccpu */
900 		    mib[0] == CTL_KERN && mib[1] == KERN_CCPU)
901 			return (0);
902 		if (miblen == 2 &&		/* vm.maxslp */
903 		    mib[0] == CTL_VM && mib[1] == VM_MAXSLP)
904 			return (0);
905 	}
906 
907 	if ((pledge & PLEDGE_VMINFO)) {
908 		if (miblen == 2 &&		/* vm.uvmexp */
909 		    mib[0] == CTL_VM && mib[1] == VM_UVMEXP)
910 			return (0);
911 		if (miblen == 3 &&		/* vfs.generic.bcachestat */
912 		    mib[0] == CTL_VFS && mib[1] == VFS_GENERIC &&
913 		    mib[2] == VFS_BCACHESTAT)
914 			return (0);
915 		if (miblen == 3 &&		/* for sysconf(3) */
916 		    mib[0] == CTL_NET && mib[1] == PF_INET6)
917 			return (0);
918 	}
919 
920 	if ((pledge & (PLEDGE_INET | PLEDGE_UNIX))) {
921 		if (miblen == 2 &&		/* kern.somaxconn */
922 		    mib[0] == CTL_KERN && mib[1] == KERN_SOMAXCONN)
923 			return (0);
924 	}
925 
926 	if ((pledge & (PLEDGE_ROUTE | PLEDGE_INET | PLEDGE_DNS))) {
927 		if (miblen == 6 &&		/* getifaddrs() */
928 		    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
929 		    mib[2] == 0 &&
930 		    (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) &&
931 		    mib[4] == NET_RT_IFLIST)
932 			return (0);
933 	}
934 
935 	if ((pledge & PLEDGE_DISKLABEL)) {
936 		if (miblen == 2 &&		/* kern.rawpartition */
937 		    mib[0] == CTL_KERN &&
938 		    mib[1] == KERN_RAWPARTITION)
939 			return (0);
940 		if (miblen == 2 &&		/* kern.maxpartitions */
941 		    mib[0] == CTL_KERN &&
942 		    mib[1] == KERN_MAXPARTITIONS)
943 			return (0);
944 #ifdef CPU_CHR2BLK
945 		if (miblen == 3 &&		/* machdep.chr2blk */
946 		    mib[0] == CTL_MACHDEP &&
947 		    mib[1] == CPU_CHR2BLK)
948 			return (0);
949 #endif /* CPU_CHR2BLK */
950 	}
951 
952 	if (miblen >= 3 &&			/* ntpd(8) to read sensors */
953 	    mib[0] == CTL_HW && mib[1] == HW_SENSORS)
954 		return (0);
955 
956 	if (miblen == 6 &&		/* if_nameindex() */
957 	    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
958 	    mib[2] == 0 && mib[3] == 0 && mib[4] == NET_RT_IFNAMES)
959 		return (0);
960 
961 	if (miblen == 2) {
962 		switch (mib[0]) {
963 		case CTL_KERN:
964 			switch (mib[1]) {
965 			case KERN_DOMAINNAME:	/* getdomainname() */
966 			case KERN_HOSTNAME:	/* gethostname() */
967 			case KERN_OSTYPE:	/* uname() */
968 			case KERN_OSRELEASE:	/* uname() */
969 			case KERN_OSVERSION:	/* uname() */
970 			case KERN_VERSION:	/* uname() */
971 			case KERN_CLOCKRATE:	/* kern.clockrate */
972 			case KERN_ARGMAX:	/* kern.argmax */
973 			case KERN_NGROUPS:	/* kern.ngroups */
974 			case KERN_SYSVSHM:	/* kern.sysvshm */
975 			case KERN_POSIX1:	/* kern.posix1version */
976 				return (0);
977 			}
978 			break;
979 		case CTL_HW:
980 			switch (mib[1]) {
981 			case HW_MACHINE: 	/* uname() */
982 			case HW_PAGESIZE: 	/* getpagesize() */
983 			case HW_PHYSMEM64:	/* hw.physmem */
984 			case HW_NCPU:		/* hw.ncpu */
985 			case HW_NCPUONLINE:	/* hw.ncpuonline */
986 			case HW_USERMEM64:	/* hw.usermem */
987 				return (0);
988 			}
989 			break;
990 		case CTL_VM:
991 			switch (mib[1]) {
992 			case VM_PSSTRINGS:	/* setproctitle() */
993 			case VM_LOADAVG:	/* vm.loadavg / getloadavg(3) */
994 			case VM_MALLOC_CONF:	/* vm.malloc_conf */
995 				return (0);
996 			}
997 			break;
998 		default:
999 			break;
1000 		}
1001 	}
1002 
1003 #ifdef CPU_SSE
1004 	if (miblen == 2 &&		/* i386 libm tests for SSE */
1005 	    mib[0] == CTL_MACHDEP && mib[1] == CPU_SSE)
1006 		return (0);
1007 #endif /* CPU_SSE */
1008 
1009 #ifdef CPU_ID_AA64ISAR0
1010 	if (miblen == 2 &&		/* arm64 libcrypto inspects CPU features */
1011 	    mib[0] == CTL_MACHDEP && mib[1] == CPU_ID_AA64ISAR0)
1012 		return (0);
1013 #endif /* CPU_ID_AA64ISAR0 */
1014 
1015 	snprintf(buf, sizeof(buf), "%s(%d): pledge sysctl %d:",
1016 	    p->p_p->ps_comm, p->p_p->ps_pid, miblen);
1017 	for (i = 0; i < miblen; i++) {
1018 		char *p = buf + strlen(buf);
1019 		snprintf(p, sizeof(buf) - (p - buf), " %d", mib[i]);
1020 	}
1021 	log(LOG_ERR, "%s\n", buf);
1022 
1023 	return pledge_fail(p, EINVAL, 0);
1024 }
1025 
1026 int
1027 pledge_chown(struct proc *p, uid_t uid, gid_t gid)
1028 {
1029 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1030 		return (0);
1031 
1032 	if (p->p_p->ps_pledge & PLEDGE_CHOWNUID)
1033 		return (0);
1034 
1035 	if (uid != -1 && uid != p->p_ucred->cr_uid)
1036 		return (EPERM);
1037 	if (gid != -1 && !groupmember(gid, p->p_ucred))
1038 		return (EPERM);
1039 	return (0);
1040 }
1041 
1042 int
1043 pledge_adjtime(struct proc *p, const void *v)
1044 {
1045 	const struct timeval *delta = v;
1046 
1047 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1048 		return (0);
1049 
1050 	if ((p->p_p->ps_pledge & PLEDGE_SETTIME))
1051 		return (0);
1052 	if (delta)
1053 		return (EPERM);
1054 	return (0);
1055 }
1056 
1057 int
1058 pledge_sendit(struct proc *p, const void *to)
1059 {
1060 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1061 		return (0);
1062 
1063 	if ((p->p_p->ps_pledge & (PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS)))
1064 		return (0);		/* may use address */
1065 	if (to == NULL)
1066 		return (0);		/* behaves just like write */
1067 	return pledge_fail(p, EPERM, PLEDGE_INET);
1068 }
1069 
1070 int
1071 pledge_ioctl(struct proc *p, long com, struct file *fp)
1072 {
1073 	struct vnode *vp = NULL;
1074 	int error = EPERM;
1075 	uint64_t pledge;
1076 
1077 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1078 		return (0);
1079 	pledge = READ_ONCE(p->p_p->ps_pledge);
1080 
1081 	/*
1082 	 * The ioctl's which are always allowed.
1083 	 */
1084 	switch (com) {
1085 	case FIONREAD:
1086 	case FIONBIO:
1087 	case FIOCLEX:
1088 	case FIONCLEX:
1089 		return (0);
1090 	}
1091 
1092 	/* fp != NULL was already checked */
1093 	if (fp->f_type == DTYPE_VNODE) {
1094 		vp = fp->f_data;
1095 		if (vp->v_type == VBAD)
1096 			return (ENOTTY);
1097 	}
1098 
1099 	if ((pledge & PLEDGE_INET)) {
1100 		switch (com) {
1101 		case SIOCATMARK:
1102 		case SIOCGIFGROUP:
1103 			if (fp->f_type == DTYPE_SOCKET)
1104 				return (0);
1105 			break;
1106 		}
1107 	}
1108 
1109 #if NBPFILTER > 0
1110 	if ((pledge & PLEDGE_BPF)) {
1111 		switch (com) {
1112 		case BIOCGSTATS:	/* bpf: tcpdump privsep on ^C */
1113 			if (fp->f_type == DTYPE_VNODE &&
1114 			    fp->f_ops->fo_ioctl == vn_ioctl &&
1115 			    vp->v_type == VCHR &&
1116 			    cdevsw[major(vp->v_rdev)].d_open == bpfopen)
1117 				return (0);
1118 			break;
1119 		}
1120 	}
1121 #endif /* NBPFILTER > 0 */
1122 
1123 	if ((pledge & PLEDGE_TAPE)) {
1124 		switch (com) {
1125 		case MTIOCGET:
1126 		case MTIOCTOP:
1127 			/* for pax(1) and such, checking tapes... */
1128 			if (fp->f_type == DTYPE_VNODE &&
1129 			    vp->v_type == VCHR) {
1130 				if (vp->v_flag & VISTTY)
1131 					return (ENOTTY);
1132 				else
1133 					return (0);
1134 			}
1135 			break;
1136 		}
1137 	}
1138 
1139 #if NDRM > 0
1140 	if ((pledge & PLEDGE_DRM)) {
1141 		if ((fp->f_type == DTYPE_VNODE) &&
1142 		    (vp->v_type == VCHR) &&
1143 		    (cdevsw[major(vp->v_rdev)].d_open == drmopen)) {
1144 			error = pledge_ioctl_drm(p, com, vp->v_rdev);
1145 			if (error == 0)
1146 				return 0;
1147 		}
1148 	}
1149 #endif /* NDRM > 0 */
1150 
1151 #if NAUDIO > 0
1152 	if ((pledge & PLEDGE_AUDIO)) {
1153 		switch (com) {
1154 		case AUDIO_GETPOS:
1155 		case AUDIO_GETPAR:
1156 		case AUDIO_SETPAR:
1157 		case AUDIO_START:
1158 		case AUDIO_STOP:
1159 		case AUDIO_MIXER_DEVINFO:
1160 		case AUDIO_MIXER_READ:
1161 		case AUDIO_MIXER_WRITE:
1162 			if (fp->f_type == DTYPE_VNODE &&
1163 			    vp->v_type == VCHR &&
1164 			    cdevsw[major(vp->v_rdev)].d_open == audioopen)
1165 				return (0);
1166 		}
1167 	}
1168 #endif /* NAUDIO > 0 */
1169 
1170 	if ((pledge & PLEDGE_DISKLABEL)) {
1171 		switch (com) {
1172 		case DIOCGDINFO:
1173 		case DIOCGPDINFO:
1174 		case DIOCRLDINFO:
1175 		case DIOCWDINFO:
1176 		case BIOCDISK:
1177 		case BIOCINQ:
1178 		case BIOCINSTALLBOOT:
1179 		case BIOCVOL:
1180 			if (fp->f_type == DTYPE_VNODE &&
1181 			    ((vp->v_type == VCHR &&
1182 			    cdevsw[major(vp->v_rdev)].d_type == D_DISK) ||
1183 			    (vp->v_type == VBLK &&
1184 			    bdevsw[major(vp->v_rdev)].d_type == D_DISK)))
1185 				return (0);
1186 			break;
1187 		case DIOCMAP:
1188 			if (fp->f_type == DTYPE_VNODE &&
1189 			    vp->v_type == VCHR &&
1190 			    cdevsw[major(vp->v_rdev)].d_ioctl == diskmapioctl)
1191 				return (0);
1192 			break;
1193 		}
1194 	}
1195 
1196 #if NVIDEO > 0
1197 	if ((pledge & PLEDGE_VIDEO)) {
1198 		switch (com) {
1199 		case VIDIOC_QUERYCAP:
1200 		case VIDIOC_TRY_FMT:
1201 		case VIDIOC_ENUM_FMT:
1202 		case VIDIOC_S_FMT:
1203 		case VIDIOC_QUERYCTRL:
1204 		case VIDIOC_G_CTRL:
1205 		case VIDIOC_S_CTRL:
1206 		case VIDIOC_G_PARM:
1207 		case VIDIOC_S_PARM:
1208 		case VIDIOC_REQBUFS:
1209 		case VIDIOC_QBUF:
1210 		case VIDIOC_DQBUF:
1211 		case VIDIOC_QUERYBUF:
1212 		case VIDIOC_STREAMON:
1213 		case VIDIOC_STREAMOFF:
1214 		case VIDIOC_ENUM_FRAMESIZES:
1215 		case VIDIOC_ENUM_FRAMEINTERVALS:
1216 		case VIDIOC_DQEVENT:
1217 		case VIDIOC_ENCODER_CMD:
1218 		case VIDIOC_EXPBUF:
1219 		case VIDIOC_G_CROP:
1220 		case VIDIOC_G_EXT_CTRLS:
1221 		case VIDIOC_G_FMT:
1222 		case VIDIOC_G_SELECTION:
1223 		case VIDIOC_QUERYMENU:
1224 		case VIDIOC_SUBSCRIBE_EVENT:
1225 		case VIDIOC_S_EXT_CTRLS:
1226 		case VIDIOC_S_SELECTION:
1227 		case VIDIOC_TRY_DECODER_CMD:
1228 		case VIDIOC_TRY_ENCODER_CMD:
1229 			if (fp->f_type == DTYPE_VNODE &&
1230 			    vp->v_type == VCHR &&
1231 			    cdevsw[major(vp->v_rdev)].d_open == videoopen)
1232 				return (0);
1233 			break;
1234 		}
1235 	}
1236 #endif
1237 
1238 #if NPF > 0
1239 	if ((pledge & PLEDGE_PF)) {
1240 		switch (com) {
1241 		case DIOCADDRULE:
1242 		case DIOCGETSTATUS:
1243 		case DIOCNATLOOK:
1244 		case DIOCRADDTABLES:
1245 		case DIOCRCLRADDRS:
1246 		case DIOCRCLRTABLES:
1247 		case DIOCRCLRTSTATS:
1248 		case DIOCRGETTSTATS:
1249 		case DIOCRSETADDRS:
1250 		case DIOCXBEGIN:
1251 		case DIOCXCOMMIT:
1252 		case DIOCKILLSRCNODES:
1253 			if ((fp->f_type == DTYPE_VNODE) &&
1254 			    (vp->v_type == VCHR) &&
1255 			    (cdevsw[major(vp->v_rdev)].d_open == pfopen))
1256 				return (0);
1257 			break;
1258 		}
1259 	}
1260 #endif
1261 
1262 	if ((pledge & PLEDGE_TTY)) {
1263 		switch (com) {
1264 #if NPTY > 0
1265 		case PTMGET:
1266 			if ((pledge & PLEDGE_RPATH) == 0)
1267 				break;
1268 			if ((pledge & PLEDGE_WPATH) == 0)
1269 				break;
1270 			if (fp->f_type != DTYPE_VNODE || vp->v_type != VCHR)
1271 				break;
1272 			if (cdevsw[major(vp->v_rdev)].d_open != ptmopen)
1273 				break;
1274 			return (0);
1275 		case TIOCUCNTL:		/* vmd */
1276 			if ((pledge & PLEDGE_RPATH) == 0)
1277 				break;
1278 			if ((pledge & PLEDGE_WPATH) == 0)
1279 				break;
1280 			if (cdevsw[major(vp->v_rdev)].d_open != ptcopen)
1281 				break;
1282 			return (0);
1283 #endif /* NPTY > 0 */
1284 		case TIOCSPGRP:
1285 			if ((pledge & PLEDGE_PROC) == 0)
1286 				break;
1287 			/* FALLTHROUGH */
1288 		case TIOCFLUSH:		/* getty, telnet */
1289 		case TIOCSTART:		/* emacs, etc */
1290 		case TIOCGPGRP:
1291 		case TIOCGETA:
1292 		case TIOCGWINSZ:	/* ENOTTY return for non-tty */
1293 		case TIOCSTAT:		/* csh */
1294 			if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
1295 				return (0);
1296 			return (ENOTTY);
1297 		case TIOCSWINSZ:
1298 		case TIOCEXT:		/* mail, libedit .. */
1299 		case TIOCCBRK:		/* cu */
1300 		case TIOCSBRK:		/* cu */
1301 		case TIOCCDTR:		/* cu */
1302 		case TIOCSDTR:		/* cu */
1303 		case TIOCEXCL:		/* cu */
1304 		case TIOCSETA:		/* cu, ... */
1305 		case TIOCSETAW:		/* cu, ... */
1306 		case TIOCSETAF:		/* tcsetattr TCSAFLUSH, script */
1307 		case TIOCSCTTY:		/* forkpty(3), login_tty(3), ... */
1308 			if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
1309 				return (0);
1310 			break;
1311 		}
1312 	}
1313 
1314 	if ((pledge & PLEDGE_ROUTE)) {
1315 		switch (com) {
1316 		case SIOCGIFADDR:
1317 		case SIOCGIFAFLAG_IN6:
1318 		case SIOCGIFALIFETIME_IN6:
1319 		case SIOCGIFDESCR:
1320 		case SIOCGIFFLAGS:
1321 		case SIOCGIFMETRIC:
1322 		case SIOCGIFGMEMB:
1323 		case SIOCGIFRDOMAIN:
1324 		case SIOCGIFDSTADDR_IN6:
1325 		case SIOCGIFNETMASK_IN6:
1326 		case SIOCGIFXFLAGS:
1327 		case SIOCGNBRINFO_IN6:
1328 		case SIOCGIFINFO_IN6:
1329 		case SIOCGIFMEDIA:
1330 			if (fp->f_type == DTYPE_SOCKET)
1331 				return (0);
1332 			break;
1333 		}
1334 	}
1335 
1336 	if ((pledge & PLEDGE_WROUTE)) {
1337 		switch (com) {
1338 		case SIOCAIFADDR:
1339 		case SIOCDIFADDR:
1340 		case SIOCAIFADDR_IN6:
1341 		case SIOCDIFADDR_IN6:
1342 			if (fp->f_type == DTYPE_SOCKET)
1343 				return (0);
1344 			break;
1345 		case SIOCSIFMTU:
1346 			if (fp->f_type == DTYPE_SOCKET)
1347 				return (0);
1348 			break;
1349 		}
1350 	}
1351 
1352 #if NVMM > 0
1353 	if ((pledge & PLEDGE_VMM)) {
1354 		if ((fp->f_type == DTYPE_VNODE) &&
1355 		    (vp->v_type == VCHR) &&
1356 		    (cdevsw[major(vp->v_rdev)].d_open == vmmopen)) {
1357 			error = pledge_ioctl_vmm(p, com);
1358 			if (error == 0)
1359 				return 0;
1360 		}
1361 	}
1362 #endif
1363 
1364 	return pledge_fail(p, error, PLEDGE_TTY);
1365 }
1366 
1367 int
1368 pledge_sockopt(struct proc *p, int set, int level, int optname)
1369 {
1370 	uint64_t pledge;
1371 
1372 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1373 		return (0);
1374 	pledge = READ_ONCE(p->p_p->ps_pledge);
1375 
1376 	/* Always allow these, which are too common to reject */
1377 	switch (level) {
1378 	case SOL_SOCKET:
1379 		switch (optname) {
1380 		case SO_RCVBUF:
1381 		case SO_ERROR:
1382 			return 0;
1383 		}
1384 		break;
1385 	}
1386 
1387 	if ((pledge & PLEDGE_WROUTE)) {
1388 		switch (level) {
1389 		case SOL_SOCKET:
1390 			switch (optname) {
1391 			case SO_RTABLE:
1392 				return (0);
1393 			}
1394 		}
1395 	}
1396 
1397 	if ((pledge & (PLEDGE_INET|PLEDGE_UNIX|PLEDGE_DNS)) == 0)
1398 		return pledge_fail(p, EPERM, PLEDGE_INET);
1399 	/* In use by some service libraries */
1400 	switch (level) {
1401 	case SOL_SOCKET:
1402 		switch (optname) {
1403 		case SO_TIMESTAMP:
1404 			return 0;
1405 		}
1406 		break;
1407 	}
1408 
1409 	/* DNS resolver may do these requests */
1410 	if ((pledge & PLEDGE_DNS)) {
1411 		switch (level) {
1412 		case IPPROTO_IPV6:
1413 			switch (optname) {
1414 			case IPV6_RECVPKTINFO:
1415 			case IPV6_USE_MIN_MTU:
1416 				return (0);
1417 			}
1418 		}
1419 	}
1420 
1421 	if ((pledge & (PLEDGE_INET|PLEDGE_UNIX)) == 0)
1422 		return pledge_fail(p, EPERM, PLEDGE_INET);
1423 	switch (level) {
1424 	case SOL_SOCKET:
1425 		switch (optname) {
1426 		case SO_RTABLE:
1427 			return pledge_fail(p, EINVAL, PLEDGE_WROUTE);
1428 		}
1429 		return (0);
1430 	}
1431 
1432 	if ((pledge & PLEDGE_INET) == 0)
1433 		return pledge_fail(p, EPERM, PLEDGE_INET);
1434 	switch (level) {
1435 	case IPPROTO_TCP:
1436 		switch (optname) {
1437 		case TCP_NODELAY:
1438 		case TCP_MD5SIG:
1439 		case TCP_SACK_ENABLE:
1440 		case TCP_MAXSEG:
1441 		case TCP_NOPUSH:
1442 			return (0);
1443 		}
1444 		break;
1445 	case IPPROTO_IP:
1446 		switch (optname) {
1447 		case IP_OPTIONS:
1448 			if (!set)
1449 				return (0);
1450 			break;
1451 		case IP_TOS:
1452 		case IP_TTL:
1453 		case IP_MINTTL:
1454 		case IP_IPDEFTTL:
1455 		case IP_PORTRANGE:
1456 		case IP_RECVDSTADDR:
1457 		case IP_RECVDSTPORT:
1458 			return (0);
1459 		case IP_MULTICAST_IF:
1460 		case IP_MULTICAST_TTL:
1461 		case IP_MULTICAST_LOOP:
1462 		case IP_ADD_MEMBERSHIP:
1463 		case IP_DROP_MEMBERSHIP:
1464 			if (pledge & PLEDGE_MCAST)
1465 				return (0);
1466 			break;
1467 		}
1468 		break;
1469 	case IPPROTO_ICMP:
1470 		break;
1471 	case IPPROTO_IPV6:
1472 		switch (optname) {
1473 		case IPV6_TCLASS:
1474 		case IPV6_UNICAST_HOPS:
1475 		case IPV6_MINHOPCOUNT:
1476 		case IPV6_RECVHOPLIMIT:
1477 		case IPV6_PORTRANGE:
1478 		case IPV6_RECVPKTINFO:
1479 		case IPV6_RECVDSTPORT:
1480 		case IPV6_V6ONLY:
1481 			return (0);
1482 		case IPV6_MULTICAST_IF:
1483 		case IPV6_MULTICAST_HOPS:
1484 		case IPV6_MULTICAST_LOOP:
1485 		case IPV6_JOIN_GROUP:
1486 		case IPV6_LEAVE_GROUP:
1487 			if (pledge & PLEDGE_MCAST)
1488 				return (0);
1489 			break;
1490 		}
1491 		break;
1492 	case IPPROTO_ICMPV6:
1493 		break;
1494 	}
1495 	return pledge_fail(p, EPERM, PLEDGE_INET);
1496 }
1497 
1498 int
1499 pledge_socket(struct proc *p, int domain, unsigned int state)
1500 {
1501 	uint64_t pledge;
1502 
1503 	if (!ISSET(p->p_p->ps_flags, PS_PLEDGE))
1504 		return 0;
1505 	pledge = READ_ONCE(p->p_p->ps_pledge);
1506 
1507 	if (ISSET(state, SS_DNS)) {
1508 		if (ISSET(pledge, PLEDGE_DNS))
1509 			return 0;
1510 		return pledge_fail(p, EPERM, PLEDGE_DNS);
1511 	}
1512 
1513 	switch (domain) {
1514 	case -1:		/* accept on any domain */
1515 		return (0);
1516 	case AF_INET:
1517 	case AF_INET6:
1518 		if (ISSET(pledge, PLEDGE_INET))
1519 			return 0;
1520 		return pledge_fail(p, EPERM, PLEDGE_INET);
1521 
1522 	case AF_UNIX:
1523 		if (ISSET(pledge, PLEDGE_UNIX))
1524 			return 0;
1525 		return pledge_fail(p, EPERM, PLEDGE_UNIX);
1526 	}
1527 
1528 	return pledge_fail(p, EINVAL, PLEDGE_INET);
1529 }
1530 
1531 int
1532 pledge_flock(struct proc *p)
1533 {
1534 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1535 		return (0);
1536 
1537 	if ((p->p_p->ps_pledge & PLEDGE_FLOCK))
1538 		return (0);
1539 	return (pledge_fail(p, EPERM, PLEDGE_FLOCK));
1540 }
1541 
1542 int
1543 pledge_swapctl(struct proc *p, int cmd)
1544 {
1545 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1546 		return (0);
1547 
1548 	if (p->p_p->ps_pledge & PLEDGE_VMINFO) {
1549 		switch (cmd) {
1550 		case SWAP_NSWAP:
1551 		case SWAP_STATS:
1552 			return (0);
1553 		}
1554 	}
1555 
1556 	return pledge_fail(p, EPERM, PLEDGE_VMINFO);
1557 }
1558 
1559 /* bsearch over pledgereq. return flags value if found, 0 else */
1560 uint64_t
1561 pledgereq_flags(const char *req_name)
1562 {
1563 	int base = 0, cmp, i, lim;
1564 
1565 	for (lim = nitems(pledgereq); lim != 0; lim >>= 1) {
1566 		i = base + (lim >> 1);
1567 		cmp = strcmp(req_name, pledgereq[i].name);
1568 		if (cmp == 0)
1569 			return (pledgereq[i].flags);
1570 		if (cmp > 0) { /* not found before, move right */
1571 			base = i + 1;
1572 			lim--;
1573 		} /* else move left */
1574 	}
1575 	return (0);
1576 }
1577 
1578 int
1579 pledge_fcntl(struct proc *p, int cmd)
1580 {
1581 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1582 		return (0);
1583 	if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0 && cmd == F_SETOWN)
1584 		return pledge_fail(p, EPERM, PLEDGE_PROC);
1585 	return (0);
1586 }
1587 
1588 int
1589 pledge_kill(struct proc *p, pid_t pid)
1590 {
1591 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1592 		return 0;
1593 	if (p->p_p->ps_pledge & PLEDGE_PROC)
1594 		return 0;
1595 	if (pid == 0 || pid == p->p_p->ps_pid)
1596 		return 0;
1597 	return pledge_fail(p, EPERM, PLEDGE_PROC);
1598 }
1599 
1600 int
1601 pledge_protexec(struct proc *p, int prot)
1602 {
1603 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1604 		return 0;
1605 	/* Before kbind(2) call, ld.so and crt may create EXEC mappings */
1606 	if (p->p_p->ps_kbind_addr == 0 && p->p_p->ps_kbind_cookie == 0)
1607 		return 0;
1608 	if (!(p->p_p->ps_pledge & PLEDGE_PROTEXEC) && (prot & PROT_EXEC))
1609 		return pledge_fail(p, EPERM, PLEDGE_PROTEXEC);
1610 	return 0;
1611 }
1612 
1613 int
1614 canonpath(const char *input, char *buf, size_t bufsize)
1615 {
1616 	const char *p;
1617 	char *q;
1618 
1619 	/* can't canon relative paths, don't bother */
1620 	if (input[0] != '/') {
1621 		if (strlcpy(buf, input, bufsize) >= bufsize)
1622 			return ENAMETOOLONG;
1623 		return 0;
1624 	}
1625 
1626 	p = input;
1627 	q = buf;
1628 	while (*p && (q - buf < bufsize)) {
1629 		if (p[0] == '/' && (p[1] == '/' || p[1] == '\0')) {
1630 			p += 1;
1631 
1632 		} else if (p[0] == '/' && p[1] == '.' &&
1633 		    (p[2] == '/' || p[2] == '\0')) {
1634 			p += 2;
1635 
1636 		} else if (p[0] == '/' && p[1] == '.' && p[2] == '.' &&
1637 		    (p[3] == '/' || p[3] == '\0')) {
1638 			p += 3;
1639 			if (q != buf)	/* "/../" at start of buf */
1640 				while (*--q != '/')
1641 					continue;
1642 
1643 		} else {
1644 			*q++ = *p++;
1645 		}
1646 	}
1647 	if ((*p == '\0') && (q - buf < bufsize)) {
1648 		*q = 0;
1649 		return 0;
1650 	} else
1651 		return ENAMETOOLONG;
1652 }
1653