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