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