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