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