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