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