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