xref: /openbsd-src/sys/kern/kern_pledge.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /*	$OpenBSD: kern_pledge.c,v 1.228 2018/01/09 15:14:23 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 	/* Send uncatchable SIGABRT for coredump */
530 	memset(&sa, 0, sizeof sa);
531 	sa.sa_handler = SIG_DFL;
532 	setsigvec(p, SIGABRT, &sa);
533 	psignal(p, SIGABRT);
534 
535 	p->p_p->ps_pledge = 0;		/* Disable all PLEDGE_ flags */
536 	return (error);
537 }
538 
539 /*
540  * Need to make it more obvious that one cannot get through here
541  * without the right flags set
542  */
543 int
544 pledge_namei(struct proc *p, struct nameidata *ni, char *origpath)
545 {
546 	char path[PATH_MAX];
547 	int error;
548 
549 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0 ||
550 	    (p->p_p->ps_flags & PS_COREDUMP))
551 		return (0);
552 
553 	if (!ni || (ni->ni_pledge == 0))
554 		panic("ni_pledge");
555 
556 	/* Doing a permitted execve() */
557 	if ((ni->ni_pledge & PLEDGE_EXEC) &&
558 	    (p->p_p->ps_pledge & PLEDGE_EXEC))
559 		return (0);
560 
561 	error = canonpath(origpath, path, sizeof(path));
562 	if (error)
563 		return (error);
564 
565 	/* Detect what looks like a mkstemp(3) family operation */
566 	if ((p->p_p->ps_pledge & PLEDGE_TMPPATH) &&
567 	    (p->p_pledge_syscall == SYS_open) &&
568 	    (ni->ni_pledge & PLEDGE_CPATH) &&
569 	    strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) {
570 		return (0);
571 	}
572 
573 	/* Allow unlinking of a mkstemp(3) file...
574 	 * Good opportunity for strict checks here.
575 	 */
576 	if ((p->p_p->ps_pledge & PLEDGE_TMPPATH) &&
577 	    (p->p_pledge_syscall == SYS_unlink) &&
578 	    strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) {
579 		return (0);
580 	}
581 
582 	/* Whitelisted paths */
583 	switch (p->p_pledge_syscall) {
584 	case SYS_access:
585 		/* tzset() needs this. */
586 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
587 		    strcmp(path, "/etc/localtime") == 0)
588 			return (0);
589 
590 		/* when avoiding YP mode, getpw* functions touch this */
591 		if (ni->ni_pledge == PLEDGE_RPATH &&
592 		    strcmp(path, "/var/run/ypbind.lock") == 0) {
593 			if (p->p_p->ps_pledge & PLEDGE_GETPW)
594 				return (0);
595 			else
596 				return (pledge_fail(p, error, PLEDGE_GETPW));
597 		}
598 		break;
599 	case SYS_open:
600 		/* daemon(3) or other such functions */
601 		if ((ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 &&
602 		    strcmp(path, "/dev/null") == 0) {
603 			return (0);
604 		}
605 
606 		/* readpassphrase(3), getpass(3) */
607 		if ((p->p_p->ps_pledge & PLEDGE_TTY) &&
608 		    (ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 &&
609 		    strcmp(path, "/dev/tty") == 0) {
610 			return (0);
611 		}
612 
613 		/* getpw* and friends need a few files */
614 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
615 		    (p->p_p->ps_pledge & PLEDGE_GETPW)) {
616 			if (strcmp(path, "/etc/spwd.db") == 0)
617 				return (EPERM); /* don't call pledge_fail */
618 			if (strcmp(path, "/etc/pwd.db") == 0)
619 				return (0);
620 			if (strcmp(path, "/etc/group") == 0)
621 				return (0);
622 			if (strcmp(path, "/etc/netid") == 0)
623 				return (0);
624 		}
625 
626 		/* DNS needs /etc/{resolv.conf,hosts,services}. */
627 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
628 		    (p->p_p->ps_pledge & PLEDGE_DNS)) {
629 			if (strcmp(path, "/etc/resolv.conf") == 0)
630 				return (0);
631 			if (strcmp(path, "/etc/hosts") == 0)
632 				return (0);
633 			if (strcmp(path, "/etc/services") == 0)
634 				return (0);
635 		}
636 
637 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
638 		    (p->p_p->ps_pledge & PLEDGE_GETPW)) {
639 			if (strcmp(path, "/var/run/ypbind.lock") == 0) {
640 				/*
641 				 * XXX
642 				 * The current hack for YP support in "getpw"
643 				 * is to enable some "inet" features until
644 				 * next pledge call.  This is not considered
645 				 * worse than pre-pledge, but is a work in
646 				 * progress, needing a clever design.
647 				 */
648 				p->p_p->ps_pledge |= PLEDGE_YPACTIVE;
649 				return (0);
650 			}
651 			if (strncmp(path, "/var/yp/binding/",
652 			    sizeof("/var/yp/binding/") - 1) == 0)
653 				return (0);
654 		}
655 
656 		/* tzset() needs these. */
657 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
658 		    strncmp(path, "/usr/share/zoneinfo/",
659 		    sizeof("/usr/share/zoneinfo/") - 1) == 0)
660 			return (0);
661 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
662 		    strcmp(path, "/etc/localtime") == 0)
663 			return (0);
664 
665 		break;
666 	case SYS_readlink:
667 		/* Allow /etc/malloc.conf for malloc(3). */
668 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
669 		    strcmp(path, "/etc/malloc.conf") == 0)
670 			return (0);
671 		break;
672 	case SYS_stat:
673 		/* DNS needs /etc/resolv.conf. */
674 		if ((ni->ni_pledge == PLEDGE_RPATH) &&
675 		    (p->p_p->ps_pledge & PLEDGE_DNS) &&
676 		    strcmp(path, "/etc/resolv.conf") == 0)
677 			return (0);
678 		break;
679 	}
680 
681 	/*
682 	 * Ensure each flag of p_pledgenote has counterpart allowing it in
683 	 * ps_pledge
684 	 */
685 	if (ni->ni_pledge & ~p->p_p->ps_pledge)
686 		return (pledge_fail(p, EPERM, (ni->ni_pledge & ~p->p_p->ps_pledge)));
687 
688 	return (0);
689 }
690 
691 /*
692  * Only allow reception of safe file descriptors.
693  */
694 int
695 pledge_recvfd(struct proc *p, struct file *fp)
696 {
697 	struct vnode *vp;
698 
699 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
700 		return (0);
701 	if ((p->p_p->ps_pledge & PLEDGE_RECVFD) == 0)
702 		return pledge_fail(p, EPERM, PLEDGE_RECVFD);
703 
704 	switch (fp->f_type) {
705 	case DTYPE_SOCKET:
706 	case DTYPE_PIPE:
707 		return (0);
708 	case DTYPE_VNODE:
709 		vp = fp->f_data;
710 
711 		if (vp->v_type != VDIR)
712 			return (0);
713 		break;
714 	}
715 	return pledge_fail(p, EINVAL, PLEDGE_RECVFD);
716 }
717 
718 /*
719  * Only allow sending of safe file descriptors.
720  */
721 int
722 pledge_sendfd(struct proc *p, struct file *fp)
723 {
724 	struct vnode *vp;
725 
726 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
727 		return (0);
728 	if ((p->p_p->ps_pledge & PLEDGE_SENDFD) == 0)
729 		return pledge_fail(p, EPERM, PLEDGE_SENDFD);
730 
731 	switch (fp->f_type) {
732 	case DTYPE_SOCKET:
733 	case DTYPE_PIPE:
734 		return (0);
735 	case DTYPE_VNODE:
736 		vp = fp->f_data;
737 
738 		if (vp->v_type != VDIR)
739 			return (0);
740 		break;
741 	}
742 	return pledge_fail(p, EINVAL, PLEDGE_SENDFD);
743 }
744 
745 int
746 pledge_sysctl(struct proc *p, int miblen, int *mib, void *new)
747 {
748 	char	buf[80];
749 	int	i;
750 
751 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
752 		return (0);
753 
754 	if (new)
755 		return pledge_fail(p, EFAULT, 0);
756 
757 	/* routing table observation */
758 	if ((p->p_p->ps_pledge & PLEDGE_ROUTE)) {
759 		if ((miblen == 6 || miblen == 7) &&
760 		    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
761 		    mib[2] == 0 &&
762 		    mib[4] == NET_RT_DUMP)
763 			return (0);
764 
765 		if (miblen == 6 &&
766 		    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
767 		    mib[2] == 0 &&
768 		    (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) &&
769 		    mib[4] == NET_RT_TABLE)
770 			return (0);
771 
772 		if (miblen == 7 &&		/* exposes MACs */
773 		    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
774 		    mib[2] == 0 &&
775 		    (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) &&
776 		    mib[4] == NET_RT_FLAGS && mib[5] == RTF_LLINFO)
777 			return (0);
778 	}
779 
780 	if (p->p_p->ps_pledge & (PLEDGE_PS | PLEDGE_VMINFO)) {
781 		if (miblen == 2 &&		/* kern.fscale */
782 		    mib[0] == CTL_KERN && mib[1] == KERN_FSCALE)
783 			return (0);
784 		if (miblen == 2 &&		/* kern.boottime */
785 		    mib[0] == CTL_KERN && mib[1] == KERN_BOOTTIME)
786 			return (0);
787 		if (miblen == 2 &&		/* kern.consdev */
788 		    mib[0] == CTL_KERN && mib[1] == KERN_CONSDEV)
789 			return (0);
790 		if (miblen == 2 &&			/* kern.cptime */
791 		    mib[0] == CTL_KERN && mib[1] == KERN_CPTIME)
792 			return (0);
793 		if (miblen == 3 &&			/* kern.cptime2 */
794 		    mib[0] == CTL_KERN && mib[1] == KERN_CPTIME2)
795 			return (0);
796 	}
797 
798 	if ((p->p_p->ps_pledge & PLEDGE_PS)) {
799 		if (miblen == 4 &&		/* kern.procargs.* */
800 		    mib[0] == CTL_KERN && mib[1] == KERN_PROC_ARGS &&
801 		    (mib[3] == KERN_PROC_ARGV || mib[3] == KERN_PROC_ENV))
802 			return (0);
803 		if (miblen == 6 &&		/* kern.proc.* */
804 		    mib[0] == CTL_KERN && mib[1] == KERN_PROC)
805 			return (0);
806 		if (miblen == 3 &&		/* kern.proc_cwd.* */
807 		    mib[0] == CTL_KERN && mib[1] == KERN_PROC_CWD)
808 			return (0);
809 		if (miblen == 2 &&		/* hw.physmem */
810 		    mib[0] == CTL_HW && mib[1] == HW_PHYSMEM64)
811 			return (0);
812 		if (miblen == 2 &&		/* kern.ccpu */
813 		    mib[0] == CTL_KERN && mib[1] == KERN_CCPU)
814 			return (0);
815 		if (miblen == 2 &&		/* vm.maxslp */
816 		    mib[0] == CTL_VM && mib[1] == VM_MAXSLP)
817 			return (0);
818 	}
819 
820 	if ((p->p_p->ps_pledge & PLEDGE_VMINFO)) {
821 		if (miblen == 2 &&		/* vm.uvmexp */
822 		    mib[0] == CTL_VM && mib[1] == VM_UVMEXP)
823 			return (0);
824 		if (miblen == 3 &&		/* vfs.generic.bcachestat */
825 		    mib[0] == CTL_VFS && mib[1] == VFS_GENERIC &&
826 		    mib[2] == VFS_BCACHESTAT)
827 			return (0);
828 	}
829 
830 	if ((p->p_p->ps_pledge & (PLEDGE_ROUTE | PLEDGE_INET | PLEDGE_DNS))) {
831 		if (miblen == 6 &&		/* getifaddrs() */
832 		    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
833 		    mib[2] == 0 &&
834 		    (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) &&
835 		    mib[4] == NET_RT_IFLIST)
836 			return (0);
837 	}
838 
839 	if ((p->p_p->ps_pledge & PLEDGE_DISKLABEL)) {
840 		if (miblen == 2 &&		/* kern.rawpartition */
841 		    mib[0] == CTL_KERN &&
842 		    mib[1] == KERN_RAWPARTITION)
843 			return (0);
844 		if (miblen == 2 &&		/* kern.maxpartitions */
845 		    mib[0] == CTL_KERN &&
846 		    mib[1] == KERN_MAXPARTITIONS)
847 			return (0);
848 #ifdef CPU_CHR2BLK
849 		if (miblen == 3 &&		/* machdep.chr2blk */
850 		    mib[0] == CTL_MACHDEP &&
851 		    mib[1] == CPU_CHR2BLK)
852 			return (0);
853 #endif /* CPU_CHR2BLK */
854 	}
855 
856 	if (miblen >= 3 &&			/* ntpd(8) to read sensors */
857 	    mib[0] == CTL_HW && mib[1] == HW_SENSORS)
858 		return (0);
859 
860 	if (miblen == 2 &&		/* getdomainname() */
861 	    mib[0] == CTL_KERN && mib[1] == KERN_DOMAINNAME)
862 		return (0);
863 	if (miblen == 2 &&		/* gethostname() */
864 	    mib[0] == CTL_KERN && mib[1] == KERN_HOSTNAME)
865 		return (0);
866 	if (miblen == 6 &&		/* if_nameindex() */
867 	    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
868 	    mib[2] == 0 && mib[3] == 0 && mib[4] == NET_RT_IFNAMES)
869 		return (0);
870 	if (miblen == 2 &&		/* uname() */
871 	    mib[0] == CTL_KERN && mib[1] == KERN_OSTYPE)
872 		return (0);
873 	if (miblen == 2 &&		/* uname() */
874 	    mib[0] == CTL_KERN && mib[1] == KERN_OSRELEASE)
875 		return (0);
876 	if (miblen == 2 &&		/* uname() */
877 	    mib[0] == CTL_KERN && mib[1] == KERN_OSVERSION)
878 		return (0);
879 	if (miblen == 2 &&		/* uname() */
880 	    mib[0] == CTL_KERN && mib[1] == KERN_VERSION)
881 		return (0);
882 	if (miblen == 2 &&		/* kern.clockrate */
883 	    mib[0] == CTL_KERN && mib[1] == KERN_CLOCKRATE)
884 		return (0);
885 	if (miblen == 2 &&		/* kern.argmax */
886 	    mib[0] == CTL_KERN && mib[1] == KERN_ARGMAX)
887 		return (0);
888 	if (miblen == 2 &&		/* kern.ngroups */
889 	    mib[0] == CTL_KERN && mib[1] == KERN_NGROUPS)
890 		return (0);
891 	if (miblen == 2 &&		/* kern.sysvshm */
892 	    mib[0] == CTL_KERN && mib[1] == KERN_SYSVSHM)
893 		return (0);
894 	if (miblen == 2 &&		/* kern.posix1version */
895 	    mib[0] == CTL_KERN && mib[1] == KERN_POSIX1)
896 		return (0);
897 	if (miblen == 2 &&		/* uname() */
898 	    mib[0] == CTL_HW && mib[1] == HW_MACHINE)
899 		return (0);
900 	if (miblen == 2 &&		/* getpagesize() */
901 	    mib[0] == CTL_HW && mib[1] == HW_PAGESIZE)
902 		return (0);
903 	if (miblen == 2 &&		/* setproctitle() */
904 	    mib[0] == CTL_VM && mib[1] == VM_PSSTRINGS)
905 		return (0);
906 	if (miblen == 2 &&		/* hw.ncpu */
907 	    mib[0] == CTL_HW && mib[1] == HW_NCPU)
908 		return (0);
909 	if (miblen == 2 &&		/* vm.loadavg / getloadavg(3) */
910 	    mib[0] == CTL_VM && mib[1] == VM_LOADAVG)
911 		return (0);
912 
913 	snprintf(buf, sizeof(buf), "%s(%d): pledge sysctl %d:",
914 	    p->p_p->ps_comm, p->p_p->ps_pid, miblen);
915 	for (i = 0; i < miblen; i++) {
916 		char *p = buf + strlen(buf);
917 		snprintf(p, sizeof(buf) - (p - buf), " %d", mib[i]);
918 	}
919 	log(LOG_ERR, "%s\n", buf);
920 
921 	return pledge_fail(p, EINVAL, 0);
922 }
923 
924 int
925 pledge_chown(struct proc *p, uid_t uid, gid_t gid)
926 {
927 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
928 		return (0);
929 
930 	if (p->p_p->ps_pledge & PLEDGE_CHOWNUID)
931 		return (0);
932 
933 	if (uid != -1 && uid != p->p_ucred->cr_uid)
934 		return (EPERM);
935 	if (gid != -1 && !groupmember(gid, p->p_ucred))
936 		return (EPERM);
937 	return (0);
938 }
939 
940 int
941 pledge_adjtime(struct proc *p, const void *v)
942 {
943 	const struct timeval *delta = v;
944 
945 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
946 		return (0);
947 
948 	if ((p->p_p->ps_pledge & PLEDGE_SETTIME))
949 		return (0);
950 	if (delta)
951 		return (EPERM);
952 	return (0);
953 }
954 
955 int
956 pledge_sendit(struct proc *p, const void *to)
957 {
958 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
959 		return (0);
960 
961 	if ((p->p_p->ps_pledge & (PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS | PLEDGE_YPACTIVE)))
962 		return (0);		/* may use address */
963 	if (to == NULL)
964 		return (0);		/* behaves just like write */
965 	return pledge_fail(p, EPERM, PLEDGE_INET);
966 }
967 
968 int
969 pledge_ioctl(struct proc *p, long com, struct file *fp)
970 {
971 	struct vnode *vp = NULL;
972 	int error = EPERM;
973 
974 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
975 		return (0);
976 
977 	/*
978 	 * The ioctl's which are always allowed.
979 	 */
980 	switch (com) {
981 	case FIONREAD:
982 	case FIONBIO:
983 	case FIOCLEX:
984 	case FIONCLEX:
985 		return (0);
986 	}
987 
988 	/* fp != NULL was already checked */
989 	if (fp->f_type == DTYPE_VNODE) {
990 		vp = fp->f_data;
991 		if (vp->v_type == VBAD)
992 			return (ENOTTY);
993 	}
994 
995 	if ((p->p_p->ps_pledge & PLEDGE_INET)) {
996 		switch (com) {
997 		case SIOCATMARK:
998 		case SIOCGIFGROUP:
999 			if (fp->f_type == DTYPE_SOCKET)
1000 				return (0);
1001 			break;
1002 		}
1003 	}
1004 
1005 #if NBPFILTER > 0
1006 	if ((p->p_p->ps_pledge & PLEDGE_BPF)) {
1007 		switch (com) {
1008 		case BIOCGSTATS:	/* bpf: tcpdump privsep on ^C */
1009 			if (fp->f_type == DTYPE_VNODE &&
1010 			    fp->f_ops->fo_ioctl == vn_ioctl &&
1011 			    vp->v_type == VCHR &&
1012 			    cdevsw[major(vp->v_rdev)].d_open == bpfopen)
1013 				return (0);
1014 			break;
1015 		}
1016 	}
1017 #endif /* NBPFILTER > 0 */
1018 
1019 	if ((p->p_p->ps_pledge & PLEDGE_TAPE)) {
1020 		switch (com) {
1021 		case MTIOCGET:
1022 		case MTIOCTOP:
1023 			/* for pax(1) and such, checking tapes... */
1024 			if (fp->f_type == DTYPE_VNODE &&
1025 			    vp->v_type == VCHR) {
1026 				if (vp->v_flag & VISTTY)
1027 					return (ENOTTY);
1028 				else
1029 					return (0);
1030 			}
1031 			break;
1032 		}
1033 	}
1034 
1035 #if NDRM > 0
1036 	if ((p->p_p->ps_pledge & PLEDGE_DRM)) {
1037 		if ((fp->f_type == DTYPE_VNODE) &&
1038 		    (vp->v_type == VCHR) &&
1039 		    (cdevsw[major(vp->v_rdev)].d_open == drmopen)) {
1040 			error = pledge_ioctl_drm(p, com, vp->v_rdev);
1041 			if (error == 0)
1042 				return 0;
1043 		}
1044 	}
1045 #endif /* NDRM > 0 */
1046 
1047 #if NAUDIO > 0
1048 	if ((p->p_p->ps_pledge & PLEDGE_AUDIO)) {
1049 		switch (com) {
1050 		case AUDIO_GETPOS:
1051 		case AUDIO_GETPAR:
1052 		case AUDIO_SETPAR:
1053 		case AUDIO_START:
1054 		case AUDIO_STOP:
1055 			if (fp->f_type == DTYPE_VNODE &&
1056 			    vp->v_type == VCHR &&
1057 			    cdevsw[major(vp->v_rdev)].d_open == audioopen)
1058 				return (0);
1059 		}
1060 	}
1061 #endif /* NAUDIO > 0 */
1062 
1063 	if ((p->p_p->ps_pledge & PLEDGE_DISKLABEL)) {
1064 		switch (com) {
1065 		case DIOCGDINFO:
1066 		case DIOCGPDINFO:
1067 		case DIOCRLDINFO:
1068 		case DIOCWDINFO:
1069 		case BIOCDISK:
1070 		case BIOCINQ:
1071 		case BIOCINSTALLBOOT:
1072 		case BIOCVOL:
1073 			if (fp->f_type == DTYPE_VNODE &&
1074 			    ((vp->v_type == VCHR &&
1075 			    cdevsw[major(vp->v_rdev)].d_type == D_DISK) ||
1076 			    (vp->v_type == VBLK &&
1077 			    bdevsw[major(vp->v_rdev)].d_type == D_DISK)))
1078 				return (0);
1079 			break;
1080 		case DIOCMAP:
1081 			if (fp->f_type == DTYPE_VNODE &&
1082 			    vp->v_type == VCHR &&
1083 			    cdevsw[major(vp->v_rdev)].d_ioctl == diskmapioctl)
1084 				return (0);
1085 			break;
1086 		}
1087 	}
1088 
1089 #if NPF > 0
1090 	if ((p->p_p->ps_pledge & PLEDGE_PF)) {
1091 		switch (com) {
1092 		case DIOCADDRULE:
1093 		case DIOCGETSTATUS:
1094 		case DIOCNATLOOK:
1095 		case DIOCRADDTABLES:
1096 		case DIOCRCLRADDRS:
1097 		case DIOCRCLRTABLES:
1098 		case DIOCRCLRTSTATS:
1099 		case DIOCRGETTSTATS:
1100 		case DIOCRSETADDRS:
1101 		case DIOCXBEGIN:
1102 		case DIOCXCOMMIT:
1103 		case DIOCKILLSRCNODES:
1104 			if ((fp->f_type == DTYPE_VNODE) &&
1105 			    (vp->v_type == VCHR) &&
1106 			    (cdevsw[major(vp->v_rdev)].d_open == pfopen))
1107 				return (0);
1108 			break;
1109 		}
1110 	}
1111 #endif
1112 
1113 	if ((p->p_p->ps_pledge & PLEDGE_TTY)) {
1114 		switch (com) {
1115 #if NPTY > 0
1116 		case PTMGET:
1117 			if ((p->p_p->ps_pledge & PLEDGE_RPATH) == 0)
1118 				break;
1119 			if ((p->p_p->ps_pledge & PLEDGE_WPATH) == 0)
1120 				break;
1121 			if (fp->f_type != DTYPE_VNODE || vp->v_type != VCHR)
1122 				break;
1123 			if (cdevsw[major(vp->v_rdev)].d_open != ptmopen)
1124 				break;
1125 			return (0);
1126 		case TIOCUCNTL:		/* vmd */
1127 			if ((p->p_p->ps_pledge & PLEDGE_RPATH) == 0)
1128 				break;
1129 			if ((p->p_p->ps_pledge & PLEDGE_WPATH) == 0)
1130 				break;
1131 			if (cdevsw[major(vp->v_rdev)].d_open != ptcopen)
1132 				break;
1133 			return (0);
1134 #endif /* NPTY > 0 */
1135 		case TIOCSPGRP:
1136 			if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0)
1137 				break;
1138 			/* FALLTHROUGH */
1139 		case TIOCFLUSH:		/* getty, telnet */
1140 		case TIOCSTART:		/* emacs, etc */
1141 		case TIOCGPGRP:
1142 		case TIOCGETA:
1143 		case TIOCGWINSZ:	/* ENOTTY return for non-tty */
1144 		case TIOCSTAT:		/* csh */
1145 			if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
1146 				return (0);
1147 			return (ENOTTY);
1148 		case TIOCSWINSZ:
1149 		case TIOCEXT:		/* mail, libedit .. */
1150 		case TIOCCBRK:		/* cu */
1151 		case TIOCSBRK:		/* cu */
1152 		case TIOCCDTR:		/* cu */
1153 		case TIOCSDTR:		/* cu */
1154 		case TIOCEXCL:		/* cu */
1155 		case TIOCSETA:		/* cu, ... */
1156 		case TIOCSETAW:		/* cu, ... */
1157 		case TIOCSETAF:		/* tcsetattr TCSAFLUSH, script */
1158 		case TIOCSCTTY:		/* forkpty(3), login_tty(3), ... */
1159 			if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
1160 				return (0);
1161 			break;
1162 		}
1163 	}
1164 
1165 	if ((p->p_p->ps_pledge & PLEDGE_ROUTE)) {
1166 		switch (com) {
1167 		case SIOCGIFADDR:
1168 		case SIOCGIFAFLAG_IN6:
1169 		case SIOCGIFALIFETIME_IN6:
1170 		case SIOCGIFDESCR:
1171 		case SIOCGIFFLAGS:
1172 		case SIOCGIFMETRIC:
1173 		case SIOCGIFGMEMB:
1174 		case SIOCGIFRDOMAIN:
1175 		case SIOCGIFDSTADDR_IN6:
1176 		case SIOCGIFNETMASK_IN6:
1177 		case SIOCGIFXFLAGS:
1178 		case SIOCGNBRINFO_IN6:
1179 		case SIOCGIFINFO_IN6:
1180 		case SIOCGIFMEDIA:
1181 			if (fp->f_type == DTYPE_SOCKET)
1182 				return (0);
1183 			break;
1184 		}
1185 	}
1186 
1187 #if NVMM > 0
1188 	if ((p->p_p->ps_pledge & PLEDGE_VMM)) {
1189 		if ((fp->f_type == DTYPE_VNODE) &&
1190 		    (vp->v_type == VCHR) &&
1191 		    (cdevsw[major(vp->v_rdev)].d_open == vmmopen)) {
1192 			error = pledge_ioctl_vmm(p, com);
1193 			if (error == 0)
1194 				return 0;
1195 		}
1196 	}
1197 #endif
1198 
1199 	return pledge_fail(p, error, PLEDGE_TTY);
1200 }
1201 
1202 int
1203 pledge_sockopt(struct proc *p, int set, int level, int optname)
1204 {
1205 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1206 		return (0);
1207 
1208 	/* Always allow these, which are too common to reject */
1209 	switch (level) {
1210 	case SOL_SOCKET:
1211 		switch (optname) {
1212 		case SO_RCVBUF:
1213 		case SO_ERROR:
1214 			return 0;
1215 		}
1216 		break;
1217 	}
1218 
1219 	if ((p->p_p->ps_pledge & (PLEDGE_INET|PLEDGE_UNIX|PLEDGE_DNS|PLEDGE_YPACTIVE)) == 0)
1220 		return pledge_fail(p, EPERM, PLEDGE_INET);
1221 	/* In use by some service libraries */
1222 	switch (level) {
1223 	case SOL_SOCKET:
1224 		switch (optname) {
1225 		case SO_TIMESTAMP:
1226 			return 0;
1227 		}
1228 		break;
1229 	}
1230 
1231 	/* DNS resolver may do these requests */
1232 	if ((p->p_p->ps_pledge & PLEDGE_DNS)) {
1233 		switch (level) {
1234 		case IPPROTO_IPV6:
1235 			switch (optname) {
1236 			case IPV6_RECVPKTINFO:
1237 			case IPV6_USE_MIN_MTU:
1238 				return (0);
1239 			}
1240 		}
1241 	}
1242 
1243 	/* YP may do these requests */
1244 	if (p->p_p->ps_pledge & PLEDGE_YPACTIVE) {
1245 		switch (level) {
1246 		case IPPROTO_IP:
1247 			switch (optname) {
1248 			case IP_PORTRANGE:
1249 				return (0);
1250 			}
1251 			break;
1252 
1253 		case IPPROTO_IPV6:
1254 			switch (optname) {
1255 			case IPV6_PORTRANGE:
1256 				return (0);
1257 			}
1258 			break;
1259 		}
1260 	}
1261 
1262 	if ((p->p_p->ps_pledge & (PLEDGE_INET|PLEDGE_UNIX)) == 0)
1263 		return pledge_fail(p, EPERM, PLEDGE_INET);
1264 	switch (level) {
1265 	case SOL_SOCKET:
1266 		switch (optname) {
1267 		case SO_RTABLE:
1268 			return pledge_fail(p, EINVAL, PLEDGE_INET);
1269 		}
1270 		return (0);
1271 	}
1272 
1273 	if ((p->p_p->ps_pledge & PLEDGE_INET) == 0)
1274 		return pledge_fail(p, EPERM, PLEDGE_INET);
1275 	switch (level) {
1276 	case IPPROTO_TCP:
1277 		switch (optname) {
1278 		case TCP_NODELAY:
1279 		case TCP_MD5SIG:
1280 		case TCP_SACK_ENABLE:
1281 		case TCP_MAXSEG:
1282 		case TCP_NOPUSH:
1283 			return (0);
1284 		}
1285 		break;
1286 	case IPPROTO_IP:
1287 		switch (optname) {
1288 		case IP_OPTIONS:
1289 			if (!set)
1290 				return (0);
1291 			break;
1292 		case IP_TOS:
1293 		case IP_TTL:
1294 		case IP_MINTTL:
1295 		case IP_IPDEFTTL:
1296 		case IP_PORTRANGE:
1297 		case IP_RECVDSTADDR:
1298 		case IP_RECVDSTPORT:
1299 			return (0);
1300 		case IP_MULTICAST_IF:
1301 		case IP_MULTICAST_TTL:
1302 		case IP_MULTICAST_LOOP:
1303 		case IP_ADD_MEMBERSHIP:
1304 		case IP_DROP_MEMBERSHIP:
1305 			if (p->p_p->ps_pledge & PLEDGE_MCAST)
1306 				return (0);
1307 			break;
1308 		}
1309 		break;
1310 	case IPPROTO_ICMP:
1311 		break;
1312 	case IPPROTO_IPV6:
1313 		switch (optname) {
1314 		case IPV6_TCLASS:
1315 		case IPV6_UNICAST_HOPS:
1316 		case IPV6_MINHOPCOUNT:
1317 		case IPV6_RECVHOPLIMIT:
1318 		case IPV6_PORTRANGE:
1319 		case IPV6_RECVPKTINFO:
1320 		case IPV6_RECVDSTPORT:
1321 		case IPV6_V6ONLY:
1322 			return (0);
1323 		case IPV6_MULTICAST_IF:
1324 		case IPV6_MULTICAST_HOPS:
1325 		case IPV6_MULTICAST_LOOP:
1326 		case IPV6_JOIN_GROUP:
1327 		case IPV6_LEAVE_GROUP:
1328 			if (p->p_p->ps_pledge & PLEDGE_MCAST)
1329 				return (0);
1330 			break;
1331 		}
1332 		break;
1333 	case IPPROTO_ICMPV6:
1334 		break;
1335 	}
1336 	return pledge_fail(p, EPERM, PLEDGE_INET);
1337 }
1338 
1339 int
1340 pledge_socket(struct proc *p, int domain, unsigned int state)
1341 {
1342 	if (! ISSET(p->p_p->ps_flags, PS_PLEDGE))
1343 		return 0;
1344 
1345 	if (ISSET(state, SS_DNS)) {
1346 		if (ISSET(p->p_p->ps_pledge, PLEDGE_DNS))
1347 			return 0;
1348 		return pledge_fail(p, EPERM, PLEDGE_DNS);
1349 	}
1350 
1351 	switch (domain) {
1352 	case -1:		/* accept on any domain */
1353 		return (0);
1354 	case AF_INET:
1355 	case AF_INET6:
1356 		if (ISSET(p->p_p->ps_pledge, PLEDGE_INET) ||
1357 		    ISSET(p->p_p->ps_pledge, PLEDGE_YPACTIVE))
1358 			return 0;
1359 		return pledge_fail(p, EPERM, PLEDGE_INET);
1360 
1361 	case AF_UNIX:
1362 		if (ISSET(p->p_p->ps_pledge, PLEDGE_UNIX))
1363 			return 0;
1364 		return pledge_fail(p, EPERM, PLEDGE_UNIX);
1365 	}
1366 
1367 	return pledge_fail(p, EINVAL, PLEDGE_INET);
1368 }
1369 
1370 int
1371 pledge_flock(struct proc *p)
1372 {
1373 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1374 		return (0);
1375 
1376 	if ((p->p_p->ps_pledge & PLEDGE_FLOCK))
1377 		return (0);
1378 	return (pledge_fail(p, EPERM, PLEDGE_FLOCK));
1379 }
1380 
1381 int
1382 pledge_swapctl(struct proc *p)
1383 {
1384 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1385 		return (0);
1386 	return (EPERM);
1387 }
1388 
1389 /* bsearch over pledgereq. return flags value if found, 0 else */
1390 uint64_t
1391 pledgereq_flags(const char *req_name)
1392 {
1393 	int base = 0, cmp, i, lim;
1394 
1395 	for (lim = nitems(pledgereq); lim != 0; lim >>= 1) {
1396 		i = base + (lim >> 1);
1397 		cmp = strcmp(req_name, pledgereq[i].name);
1398 		if (cmp == 0)
1399 			return (pledgereq[i].flags);
1400 		if (cmp > 0) { /* not found before, move right */
1401 			base = i + 1;
1402 			lim--;
1403 		} /* else move left */
1404 	}
1405 	return (0);
1406 }
1407 
1408 int
1409 pledge_fcntl(struct proc *p, int cmd)
1410 {
1411 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1412 		return (0);
1413 	if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0 && cmd == F_SETOWN)
1414 		return pledge_fail(p, EPERM, PLEDGE_PROC);
1415 	return (0);
1416 }
1417 
1418 int
1419 pledge_kill(struct proc *p, pid_t pid)
1420 {
1421 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1422 		return 0;
1423 	if (p->p_p->ps_pledge & PLEDGE_PROC)
1424 		return 0;
1425 	if (pid == 0 || pid == p->p_p->ps_pid)
1426 		return 0;
1427 	return pledge_fail(p, EPERM, PLEDGE_PROC);
1428 }
1429 
1430 int
1431 pledge_protexec(struct proc *p, int prot)
1432 {
1433 	if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
1434 		return 0;
1435 	/* Before kbind(2) call, ld.so and crt may create EXEC mappings */
1436 	if (p->p_p->ps_kbind_addr == 0 && p->p_p->ps_kbind_cookie == 0)
1437 		return 0;
1438 	if (!(p->p_p->ps_pledge & PLEDGE_PROTEXEC) && (prot & PROT_EXEC))
1439 		return pledge_fail(p, EPERM, PLEDGE_PROTEXEC);
1440 	return 0;
1441 }
1442 
1443 int
1444 canonpath(const char *input, char *buf, size_t bufsize)
1445 {
1446 	const char *p;
1447 	char *q;
1448 
1449 	/* can't canon relative paths, don't bother */
1450 	if (input[0] != '/') {
1451 		if (strlcpy(buf, input, bufsize) >= bufsize)
1452 			return ENAMETOOLONG;
1453 		return 0;
1454 	}
1455 
1456 	p = input;
1457 	q = buf;
1458 	while (*p && (q - buf < bufsize)) {
1459 		if (p[0] == '/' && (p[1] == '/' || p[1] == '\0')) {
1460 			p += 1;
1461 
1462 		} else if (p[0] == '/' && p[1] == '.' &&
1463 		    (p[2] == '/' || p[2] == '\0')) {
1464 			p += 2;
1465 
1466 		} else if (p[0] == '/' && p[1] == '.' && p[2] == '.' &&
1467 		    (p[3] == '/' || p[3] == '\0')) {
1468 			p += 3;
1469 			if (q != buf)	/* "/../" at start of buf */
1470 				while (*--q != '/')
1471 					continue;
1472 
1473 		} else {
1474 			*q++ = *p++;
1475 		}
1476 	}
1477 	if ((*p == '\0') && (q - buf < bufsize)) {
1478 		*q = 0;
1479 		return 0;
1480 	} else
1481 		return ENAMETOOLONG;
1482 }
1483