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