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