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