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