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