| File: | kern/kern_pledge.c |
| Warning: | line 1259, column 15 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: kern_pledge.c,v 1.277 2021/12/23 18:50:32 guenther Exp $ */ | |||
| 2 | ||||
| 3 | /* | |||
| 4 | * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> | |||
| 5 | * Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org> | |||
| 6 | * | |||
| 7 | * Permission to use, copy, modify, and distribute this software for any | |||
| 8 | * purpose with or without fee is hereby granted, provided that the above | |||
| 9 | * copyright notice and this permission notice appear in all copies. | |||
| 10 | * | |||
| 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
| 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
| 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
| 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
| 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
| 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
| 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| 18 | */ | |||
| 19 | ||||
| 20 | #include <sys/param.h> | |||
| 21 | ||||
| 22 | #include <sys/mount.h> | |||
| 23 | #include <sys/proc.h> | |||
| 24 | #include <sys/fcntl.h> | |||
| 25 | #include <sys/file.h> | |||
| 26 | #include <sys/filedesc.h> | |||
| 27 | #include <sys/namei.h> | |||
| 28 | #include <sys/pool.h> | |||
| 29 | #include <sys/socketvar.h> | |||
| 30 | #include <sys/vnode.h> | |||
| 31 | #include <sys/mbuf.h> | |||
| 32 | #include <sys/mman.h> | |||
| 33 | #include <sys/sysctl.h> | |||
| 34 | #include <sys/syslog.h> | |||
| 35 | #include <sys/ktrace.h> | |||
| 36 | #include <sys/acct.h> | |||
| 37 | ||||
| 38 | #include <sys/ioctl.h> | |||
| 39 | #include <sys/termios.h> | |||
| 40 | #include <sys/tty.h> | |||
| 41 | #include <sys/device.h> | |||
| 42 | #include <sys/disklabel.h> | |||
| 43 | #include <sys/dkio.h> | |||
| 44 | #include <sys/mtio.h> | |||
| 45 | #include <sys/audioio.h> | |||
| 46 | #include <sys/videoio.h> | |||
| 47 | #include <net/bpf.h> | |||
| 48 | #include <net/route.h> | |||
| 49 | #include <net/if.h> | |||
| 50 | #include <net/if_var.h> | |||
| 51 | #include <netinet/in.h> | |||
| 52 | #include <netinet6/in6_var.h> | |||
| 53 | #include <netinet6/nd6.h> | |||
| 54 | #include <netinet/tcp.h> | |||
| 55 | #include <net/pfvar.h> | |||
| 56 | ||||
| 57 | #include <sys/conf.h> | |||
| 58 | #include <sys/specdev.h> | |||
| 59 | #include <sys/signal.h> | |||
| 60 | #include <sys/signalvar.h> | |||
| 61 | #include <sys/syscall.h> | |||
| 62 | #include <sys/syscallargs.h> | |||
| 63 | #include <sys/systm.h> | |||
| 64 | ||||
| 65 | #include <dev/biovar.h> | |||
| 66 | ||||
| 67 | #define PLEDGENAMES | |||
| 68 | #include <sys/pledge.h> | |||
| 69 | ||||
| 70 | #include "audio.h" | |||
| 71 | #include "bpfilter.h" | |||
| 72 | #include "pf.h" | |||
| 73 | #include "video.h" | |||
| 74 | #include "pty.h" | |||
| 75 | ||||
| 76 | #if defined(__amd64__1) | |||
| 77 | #include "vmm.h" | |||
| 78 | #if NVMM1 > 0 | |||
| 79 | #include <machine/conf.h> | |||
| 80 | #endif | |||
| 81 | #endif | |||
| 82 | ||||
| 83 | #include "drm.h" | |||
| 84 | ||||
| 85 | uint64_t pledgereq_flags(const char *req); | |||
| 86 | int parsepledges(struct proc *p, const char *kname, | |||
| 87 | const char *promises, u_int64_t *fp); | |||
| 88 | int canonpath(const char *input, char *buf, size_t bufsize); | |||
| 89 | void unveil_destroy(struct process *ps); | |||
| 90 | ||||
| 91 | /* #define DEBUG_PLEDGE */ | |||
| 92 | #ifdef DEBUG_PLEDGE | |||
| 93 | int debug_pledge = 1; | |||
| 94 | #define DPRINTF(x...) do { if (debug_pledge) printf(x); } while (0) | |||
| 95 | #define DNPRINTF(n,x...) do { if (debug_pledge >= (n)) printf(x); } while (0) | |||
| 96 | #else | |||
| 97 | #define DPRINTF(x...) | |||
| 98 | #define DNPRINTF(n,x...) | |||
| 99 | #endif | |||
| 100 | ||||
| 101 | /* | |||
| 102 | * Ordered in blocks starting with least risky and most required. | |||
| 103 | */ | |||
| 104 | const uint64_t pledge_syscalls[SYS_MAXSYSCALL331] = { | |||
| 105 | /* | |||
| 106 | * Minimum required | |||
| 107 | */ | |||
| 108 | [SYS_exit1] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
| 109 | [SYS_kbind86] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
| 110 | [SYS_msyscall37] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
| 111 | [SYS___get_tcb330] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
| 112 | [SYS___set_tcb329] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
| 113 | [SYS_pledge108] = PLEDGE_ALWAYS0xffffffffffffffffULL, | |||
| 114 | [SYS_sendsyslog112] = PLEDGE_ALWAYS0xffffffffffffffffULL, /* stack protector reporting */ | |||
| 115 | [SYS_thrkill119] = PLEDGE_ALWAYS0xffffffffffffffffULL, /* raise, abort, stack pro */ | |||
| 116 | [SYS_utrace209] = PLEDGE_ALWAYS0xffffffffffffffffULL, /* ltrace(1) from ld.so */ | |||
| 117 | ||||
| 118 | /* "getting" information about self is considered safe */ | |||
| 119 | [SYS_getuid24] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 120 | [SYS_geteuid25] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 121 | [SYS_getresuid281] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 122 | [SYS_getgid47] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 123 | [SYS_getegid43] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 124 | [SYS_getresgid283] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 125 | [SYS_getgroups79] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 126 | [SYS_getlogin_r141] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 127 | [SYS_getpgrp81] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 128 | [SYS_getpgid207] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 129 | [SYS_getppid39] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 130 | [SYS_getsid255] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 131 | [SYS_getthrid299] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 132 | [SYS_getrlimit194] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 133 | [SYS_getrtable311] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 134 | [SYS_gettimeofday67] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 135 | [SYS_getdtablecount18] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 136 | [SYS_getrusage19] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 137 | [SYS_issetugid253] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 138 | [SYS_clock_getres89] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 139 | [SYS_clock_gettime87] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 140 | [SYS_getpid20] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 141 | ||||
| 142 | /* | |||
| 143 | * Almost exclusively read-only, Very narrow subset. | |||
| 144 | * Use of "route", "inet", "dns", "ps", or "vminfo" | |||
| 145 | * expands access. | |||
| 146 | */ | |||
| 147 | [SYS_sysctl202] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 148 | ||||
| 149 | /* Support for malloc(3) family of operations */ | |||
| 150 | [SYS_getentropy7] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 151 | [SYS_madvise75] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 152 | [SYS_minherit250] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 153 | [SYS_mmap49] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 154 | [SYS_mprotect74] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 155 | [SYS_mquery78] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 156 | [SYS_munmap73] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 157 | [SYS_msync256] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 158 | [SYS_break17] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 159 | ||||
| 160 | [SYS_umask60] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 161 | ||||
| 162 | /* read/write operations */ | |||
| 163 | [SYS_read3] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 164 | [SYS_readv120] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 165 | [SYS_pread169] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 166 | [SYS_preadv171] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 167 | [SYS_write4] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 168 | [SYS_writev121] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 169 | [SYS_pwrite170] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 170 | [SYS_pwritev172] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 171 | [SYS_recvmsg27] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 172 | [SYS_recvfrom29] = PLEDGE_STDIO0x0000000000000008ULL | PLEDGE_YPACTIVE0x8000000000000000ULL, | |||
| 173 | [SYS_ftruncate168] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 174 | [SYS_lseek166] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 175 | [SYS_fpathconf192] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 176 | ||||
| 177 | #if 1 | |||
| 178 | [SYS_pad_mquery286] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 179 | [SYS_pad_mmap197] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 180 | [SYS_pad_pread173] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 181 | [SYS_pad_preadv267] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 182 | [SYS_pad_pwrite174] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 183 | [SYS_pad_pwritev268] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 184 | [SYS_pad_ftruncate201] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 185 | [SYS_pad_lseek199] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 186 | [SYS_pad_truncate200] = PLEDGE_WPATH0x0000000000000002ULL, | |||
| 187 | #endif | |||
| 188 | ||||
| 189 | /* | |||
| 190 | * Address selection required a network pledge ("inet", | |||
| 191 | * "unix", "dns". | |||
| 192 | */ | |||
| 193 | [SYS_sendto133] = PLEDGE_STDIO0x0000000000000008ULL | PLEDGE_YPACTIVE0x8000000000000000ULL, | |||
| 194 | ||||
| 195 | /* | |||
| 196 | * Address specification required a network pledge ("inet", | |||
| 197 | * "unix", "dns". SCM_RIGHTS requires "sendfd" or "recvfd". | |||
| 198 | */ | |||
| 199 | [SYS_sendmsg28] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 200 | ||||
| 201 | /* Common signal operations */ | |||
| 202 | [SYS_nanosleep91] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 203 | [SYS_sigaltstack288] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 204 | [SYS_sigprocmask48] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 205 | [SYS_sigsuspend111] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 206 | [SYS_sigaction46] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 207 | [SYS_sigreturn103] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 208 | [SYS_sigpending52] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 209 | [SYS_getitimer70] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 210 | [SYS_setitimer69] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 211 | ||||
| 212 | /* | |||
| 213 | * To support event driven programming. | |||
| 214 | */ | |||
| 215 | [SYS_poll252] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 216 | [SYS_ppoll109] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 217 | [SYS_kevent72] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 218 | [SYS_kqueue269] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 219 | [SYS_select71] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 220 | [SYS_pselect110] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 221 | ||||
| 222 | [SYS_fstat53] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 223 | [SYS_fsync95] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 224 | ||||
| 225 | [SYS_setsockopt105] = PLEDGE_STDIO0x0000000000000008ULL, /* narrow whitelist */ | |||
| 226 | [SYS_getsockopt118] = PLEDGE_STDIO0x0000000000000008ULL, /* narrow whitelist */ | |||
| 227 | ||||
| 228 | /* F_SETOWN requires PLEDGE_PROC */ | |||
| 229 | [SYS_fcntl92] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 230 | ||||
| 231 | [SYS_close6] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 232 | [SYS_dup41] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 233 | [SYS_dup290] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 234 | [SYS_dup3102] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 235 | [SYS_closefrom287] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 236 | [SYS_shutdown134] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 237 | [SYS_fchdir13] = PLEDGE_STDIO0x0000000000000008ULL, /* XXX consider tightening */ | |||
| 238 | ||||
| 239 | [SYS_pipe263] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 240 | [SYS_pipe2101] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 241 | [SYS_socketpair135] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 242 | ||||
| 243 | [SYS_wait411] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 244 | ||||
| 245 | /* | |||
| 246 | * Can kill self with "stdio". Killing another pid | |||
| 247 | * requires "proc" | |||
| 248 | */ | |||
| 249 | [SYS_kill122] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 250 | ||||
| 251 | /* | |||
| 252 | * FIONREAD/FIONBIO for "stdio" | |||
| 253 | * Other ioctl are selectively allowed based upon other pledges. | |||
| 254 | */ | |||
| 255 | [SYS_ioctl54] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 256 | ||||
| 257 | /* | |||
| 258 | * Path access/creation calls encounter many extensive | |||
| 259 | * checks done during pledge_namei() | |||
| 260 | */ | |||
| 261 | [SYS_open5] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 262 | [SYS_stat38] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 263 | [SYS_access33] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 264 | [SYS_readlink58] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 265 | [SYS___realpath115] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 266 | ||||
| 267 | [SYS_adjtime140] = PLEDGE_STDIO0x0000000000000008ULL, /* setting requires "settime" */ | |||
| 268 | [SYS_adjfreq305] = PLEDGE_SETTIME0x0000000000002000ULL, | |||
| 269 | [SYS_settimeofday68] = PLEDGE_SETTIME0x0000000000002000ULL, | |||
| 270 | ||||
| 271 | /* | |||
| 272 | * Needed by threaded programs | |||
| 273 | * XXX should we have a new "threads"? | |||
| 274 | */ | |||
| 275 | [SYS___tfork8] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 276 | [SYS_sched_yield298] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 277 | [SYS_futex83] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 278 | [SYS___thrsleep94] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 279 | [SYS___thrwakeup301] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 280 | [SYS___threxit302] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 281 | [SYS___thrsigdivert303] = PLEDGE_STDIO0x0000000000000008ULL, | |||
| 282 | ||||
| 283 | [SYS_fork2] = PLEDGE_PROC0x0000000000001000ULL, | |||
| 284 | [SYS_vfork66] = PLEDGE_PROC0x0000000000001000ULL, | |||
| 285 | [SYS_setpgid82] = PLEDGE_PROC0x0000000000001000ULL, | |||
| 286 | [SYS_setsid147] = PLEDGE_PROC0x0000000000001000ULL, | |||
| 287 | ||||
| 288 | [SYS_setrlimit195] = PLEDGE_PROC0x0000000000001000ULL | PLEDGE_ID0x0000000000000200ULL, | |||
| 289 | [SYS_getpriority100] = PLEDGE_PROC0x0000000000001000ULL | PLEDGE_ID0x0000000000000200ULL, | |||
| 290 | ||||
| 291 | [SYS_setpriority96] = PLEDGE_PROC0x0000000000001000ULL | PLEDGE_ID0x0000000000000200ULL, | |||
| 292 | ||||
| 293 | [SYS_setuid23] = PLEDGE_ID0x0000000000000200ULL, | |||
| 294 | [SYS_seteuid183] = PLEDGE_ID0x0000000000000200ULL, | |||
| 295 | [SYS_setreuid126] = PLEDGE_ID0x0000000000000200ULL, | |||
| 296 | [SYS_setresuid282] = PLEDGE_ID0x0000000000000200ULL, | |||
| 297 | [SYS_setgid181] = PLEDGE_ID0x0000000000000200ULL, | |||
| 298 | [SYS_setegid182] = PLEDGE_ID0x0000000000000200ULL, | |||
| 299 | [SYS_setregid127] = PLEDGE_ID0x0000000000000200ULL, | |||
| 300 | [SYS_setresgid284] = PLEDGE_ID0x0000000000000200ULL, | |||
| 301 | [SYS_setgroups80] = PLEDGE_ID0x0000000000000200ULL, | |||
| 302 | [SYS_setlogin50] = PLEDGE_ID0x0000000000000200ULL, | |||
| 303 | ||||
| 304 | [SYS_unveil114] = PLEDGE_UNVEIL0x0000001000000000ULL, | |||
| 305 | ||||
| 306 | [SYS_execve59] = PLEDGE_EXEC0x0000000000080000ULL, | |||
| 307 | ||||
| 308 | [SYS_chdir12] = PLEDGE_RPATH0x0000000000000001ULL, | |||
| 309 | [SYS_openat321] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
| 310 | [SYS_fstatat42] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
| 311 | [SYS_faccessat313] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
| 312 | [SYS_readlinkat322] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
| 313 | [SYS_lstat40] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL | PLEDGE_TMPPATH0x0000000000000010ULL, | |||
| 314 | [SYS_truncate167] = PLEDGE_WPATH0x0000000000000002ULL, | |||
| 315 | [SYS_rename128] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_CPATH0x0000000000000004ULL, | |||
| 316 | [SYS_rmdir137] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 317 | [SYS_renameat323] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 318 | [SYS_link9] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 319 | [SYS_linkat317] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 320 | [SYS_symlink57] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 321 | [SYS_symlinkat324] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 322 | [SYS_unlink10] = PLEDGE_CPATH0x0000000000000004ULL | PLEDGE_TMPPATH0x0000000000000010ULL, | |||
| 323 | [SYS_unlinkat325] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 324 | [SYS_mkdir136] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 325 | [SYS_mkdirat318] = PLEDGE_CPATH0x0000000000000004ULL, | |||
| 326 | ||||
| 327 | [SYS_mkfifo132] = PLEDGE_DPATH0x0000000010000000ULL, | |||
| 328 | [SYS_mkfifoat319] = PLEDGE_DPATH0x0000000010000000ULL, | |||
| 329 | [SYS_mknod14] = PLEDGE_DPATH0x0000000010000000ULL, | |||
| 330 | [SYS_mknodat320] = PLEDGE_DPATH0x0000000010000000ULL, | |||
| 331 | ||||
| 332 | [SYS_revoke56] = PLEDGE_TTY0x0000000000010000ULL, /* also requires PLEDGE_RPATH */ | |||
| 333 | ||||
| 334 | /* | |||
| 335 | * Classify as RPATH|WPATH, because of path information leakage. | |||
| 336 | * WPATH due to unknown use of mk*temp(3) on non-/tmp paths.. | |||
| 337 | */ | |||
| 338 | [SYS___getcwd304] = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL, | |||
| 339 | ||||
| 340 | /* Classify as RPATH, because these leak path information */ | |||
| 341 | [SYS_getdents99] = PLEDGE_RPATH0x0000000000000001ULL, | |||
| 342 | [SYS_getfsstat62] = PLEDGE_RPATH0x0000000000000001ULL, | |||
| 343 | [SYS_statfs63] = PLEDGE_RPATH0x0000000000000001ULL, | |||
| 344 | [SYS_fstatfs64] = PLEDGE_RPATH0x0000000000000001ULL, | |||
| 345 | [SYS_pathconf191] = PLEDGE_RPATH0x0000000000000001ULL, | |||
| 346 | ||||
| 347 | [SYS_utimes76] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 348 | [SYS_futimes77] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 349 | [SYS_utimensat84] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 350 | [SYS_futimens85] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 351 | [SYS_chmod15] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 352 | [SYS_fchmod124] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 353 | [SYS_fchmodat314] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 354 | [SYS_chflags34] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 355 | [SYS_chflagsat107] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 356 | [SYS_fchflags35] = PLEDGE_FATTR0x0000000000004000ULL, | |||
| 357 | ||||
| 358 | [SYS_chown16] = PLEDGE_CHOWN0x0000000080000000ULL, | |||
| 359 | [SYS_fchownat315] = PLEDGE_CHOWN0x0000000080000000ULL, | |||
| 360 | [SYS_lchown254] = PLEDGE_CHOWN0x0000000080000000ULL, | |||
| 361 | [SYS_fchown123] = PLEDGE_CHOWN0x0000000080000000ULL, | |||
| 362 | ||||
| 363 | [SYS_socket97] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL | PLEDGE_YPACTIVE0x8000000000000000ULL, | |||
| 364 | [SYS_connect98] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL | PLEDGE_YPACTIVE0x8000000000000000ULL, | |||
| 365 | [SYS_bind104] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL | PLEDGE_YPACTIVE0x8000000000000000ULL, | |||
| 366 | [SYS_getsockname32] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL | PLEDGE_YPACTIVE0x8000000000000000ULL, | |||
| 367 | ||||
| 368 | [SYS_listen106] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL, | |||
| 369 | [SYS_accept493] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL, | |||
| 370 | [SYS_accept30] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL, | |||
| 371 | [SYS_getpeername31] = PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL, | |||
| 372 | ||||
| 373 | [SYS_flock131] = PLEDGE_FLOCK0x0000000000000080ULL | PLEDGE_YPACTIVE0x8000000000000000ULL, | |||
| 374 | ||||
| 375 | [SYS_swapctl193] = PLEDGE_VMINFO0x0000000000400000ULL, /* XXX should limit to "get" operations */ | |||
| 376 | }; | |||
| 377 | ||||
| 378 | static const struct { | |||
| 379 | char *name; | |||
| 380 | uint64_t flags; | |||
| 381 | } pledgereq[] = { | |||
| 382 | { "audio", PLEDGE_AUDIO0x0000000008000000ULL }, | |||
| 383 | { "bpf", PLEDGE_BPF0x0000000200000000ULL }, | |||
| 384 | { "chown", PLEDGE_CHOWN0x0000000080000000ULL | PLEDGE_CHOWNUID0x0000000100000000ULL }, | |||
| 385 | { "cpath", PLEDGE_CPATH0x0000000000000004ULL }, | |||
| 386 | { "disklabel", PLEDGE_DISKLABEL0x0000000002000000ULL }, | |||
| 387 | { "dns", PLEDGE_DNS0x0000000000000020ULL }, | |||
| 388 | { "dpath", PLEDGE_DPATH0x0000000010000000ULL }, | |||
| 389 | { "drm", PLEDGE_DRM0x0000000020000000ULL }, | |||
| 390 | { "error", PLEDGE_ERROR0x0000000400000000ULL }, | |||
| 391 | { "exec", PLEDGE_EXEC0x0000000000080000ULL }, | |||
| 392 | { "fattr", PLEDGE_FATTR0x0000000000004000ULL | PLEDGE_CHOWN0x0000000080000000ULL }, | |||
| 393 | { "flock", PLEDGE_FLOCK0x0000000000000080ULL }, | |||
| 394 | { "getpw", PLEDGE_GETPW0x0000000000000800ULL }, | |||
| 395 | { "id", PLEDGE_ID0x0000000000000200ULL }, | |||
| 396 | { "inet", PLEDGE_INET0x0000000000000040ULL }, | |||
| 397 | { "mcast", PLEDGE_MCAST0x0000000000200000ULL }, | |||
| 398 | { "pf", PLEDGE_PF0x0000000004000000ULL }, | |||
| 399 | { "proc", PLEDGE_PROC0x0000000000001000ULL }, | |||
| 400 | { "prot_exec", PLEDGE_PROTEXEC0x0000000000008000ULL }, | |||
| 401 | { "ps", PLEDGE_PS0x0000000000800000ULL }, | |||
| 402 | { "recvfd", PLEDGE_RECVFD0x0000000000040000ULL }, | |||
| 403 | { "route", PLEDGE_ROUTE0x0000000000100000ULL }, | |||
| 404 | { "rpath", PLEDGE_RPATH0x0000000000000001ULL }, | |||
| 405 | { "sendfd", PLEDGE_SENDFD0x0000000000020000ULL }, | |||
| 406 | { "settime", PLEDGE_SETTIME0x0000000000002000ULL }, | |||
| 407 | { "stdio", PLEDGE_STDIO0x0000000000000008ULL }, | |||
| 408 | { "tape", PLEDGE_TAPE0x0000000000000400ULL }, | |||
| 409 | { "tmppath", PLEDGE_TMPPATH0x0000000000000010ULL }, | |||
| 410 | { "tty", PLEDGE_TTY0x0000000000010000ULL }, | |||
| 411 | { "unix", PLEDGE_UNIX0x0000000000000100ULL }, | |||
| 412 | { "unveil", PLEDGE_UNVEIL0x0000001000000000ULL }, | |||
| 413 | { "video", PLEDGE_VIDEO0x0000002000000000ULL }, | |||
| 414 | { "vminfo", PLEDGE_VMINFO0x0000000000400000ULL }, | |||
| 415 | { "vmm", PLEDGE_VMM0x0000000040000000ULL }, | |||
| 416 | { "wpath", PLEDGE_WPATH0x0000000000000002ULL }, | |||
| 417 | { "wroute", PLEDGE_WROUTE0x0000000800000000ULL }, | |||
| 418 | }; | |||
| 419 | ||||
| 420 | int | |||
| 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(MAXPATHLEN1024, M_TEMP127, M_WAITOK0x0001); | |||
| 429 | error = copyinstr(promises, rbuf, MAXPATHLEN1024, | |||
| 430 | &rbuflen); | |||
| 431 | if (error) { | |||
| 432 | free(rbuf, M_TEMP127, MAXPATHLEN1024); | |||
| 433 | return (error); | |||
| 434 | } | |||
| 435 | #ifdef KTRACE1 | |||
| 436 | if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) && ((p)->p_flag & 0x00000001) == 0)) | |||
| 437 | ktrstruct(p, kname, rbuf, rbuflen-1); | |||
| 438 | #endif | |||
| 439 | ||||
| 440 | for (rp = rbuf; rp && *rp; rp = pn) { | |||
| 441 | pn = strchr(rp, ' '); /* find terminator */ | |||
| 442 | if (pn) { | |||
| 443 | while (*pn == ' ') | |||
| 444 | *pn++ = '\0'; | |||
| 445 | } | |||
| 446 | if ((f = pledgereq_flags(rp)) == 0) { | |||
| 447 | free(rbuf, M_TEMP127, MAXPATHLEN1024); | |||
| 448 | return (EINVAL22); | |||
| 449 | } | |||
| 450 | flags |= f; | |||
| 451 | } | |||
| 452 | free(rbuf, M_TEMP127, MAXPATHLEN1024); | |||
| 453 | *fp = flags; | |||
| 454 | return 0; | |||
| 455 | } | |||
| 456 | ||||
| 457 | int | |||
| 458 | sys_pledge(struct proc *p, void *v, register_t *retval) | |||
| 459 | { | |||
| 460 | struct sys_pledge_args /* { | |||
| 461 | syscallarg(const char *)promises; | |||
| 462 | syscallarg(const char *)execpromises; | |||
| 463 | } */ *uap = v; | |||
| 464 | struct process *pr = p->p_p; | |||
| 465 | uint64_t promises, execpromises; | |||
| 466 | int error; | |||
| 467 | ||||
| 468 | if (SCARG(uap, promises)((uap)->promises.le.datum)) { | |||
| 469 | error = parsepledges(p, "pledgereq", | |||
| 470 | SCARG(uap, promises)((uap)->promises.le.datum), &promises); | |||
| 471 | if (error) | |||
| 472 | return (error); | |||
| 473 | ||||
| 474 | /* In "error" mode, ignore promise increase requests, | |||
| 475 | * but accept promise decrease requests */ | |||
| 476 | if (ISSET(pr->ps_flags, PS_PLEDGE)((pr->ps_flags) & (0x00100000)) && | |||
| 477 | (pr->ps_pledge & PLEDGE_ERROR0x0000000400000000ULL)) | |||
| 478 | promises &= (pr->ps_pledge & PLEDGE_USERSET0x0fffffffffffffffULL); | |||
| 479 | ||||
| 480 | /* Only permit reductions */ | |||
| 481 | if (ISSET(pr->ps_flags, PS_PLEDGE)((pr->ps_flags) & (0x00100000)) && | |||
| 482 | (((promises | pr->ps_pledge) != pr->ps_pledge))) | |||
| 483 | return (EPERM1); | |||
| 484 | } | |||
| 485 | if (SCARG(uap, execpromises)((uap)->execpromises.le.datum)) { | |||
| 486 | error = parsepledges(p, "pledgeexecreq", | |||
| 487 | SCARG(uap, execpromises)((uap)->execpromises.le.datum), &execpromises); | |||
| 488 | if (error) | |||
| 489 | return (error); | |||
| 490 | ||||
| 491 | /* Only permit reductions */ | |||
| 492 | if (ISSET(pr->ps_flags, PS_EXECPLEDGE)((pr->ps_flags) & (0x00400000)) && | |||
| 493 | (((execpromises | pr->ps_execpledge) != pr->ps_execpledge))) | |||
| 494 | return (EPERM1); | |||
| 495 | } | |||
| 496 | ||||
| 497 | if (SCARG(uap, promises)((uap)->promises.le.datum)) { | |||
| 498 | pr->ps_pledge = promises; | |||
| 499 | atomic_setbits_intx86_atomic_setbits_u32(&pr->ps_flags, PS_PLEDGE0x00100000); | |||
| 500 | /* | |||
| 501 | * Kill off unveil and drop unveil vnode refs if we no | |||
| 502 | * longer are holding any path-accessing pledge | |||
| 503 | */ | |||
| 504 | if ((pr->ps_pledge & (PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL | | |||
| 505 | PLEDGE_CPATH0x0000000000000004ULL | PLEDGE_DPATH0x0000000010000000ULL | PLEDGE_TMPPATH0x0000000000000010ULL | PLEDGE_EXEC0x0000000000080000ULL | | |||
| 506 | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_UNVEIL0x0000001000000000ULL)) == 0) | |||
| 507 | unveil_destroy(pr); | |||
| 508 | } | |||
| 509 | if (SCARG(uap, execpromises)((uap)->execpromises.le.datum)) { | |||
| 510 | pr->ps_execpledge = execpromises; | |||
| 511 | atomic_setbits_intx86_atomic_setbits_u32(&pr->ps_flags, PS_EXECPLEDGE0x00400000); | |||
| 512 | } | |||
| 513 | return (0); | |||
| 514 | } | |||
| 515 | ||||
| 516 | int | |||
| 517 | pledge_syscall(struct proc *p, int code, uint64_t *tval) | |||
| 518 | { | |||
| 519 | p->p_pledge_syscall = code; | |||
| 520 | *tval = 0; | |||
| 521 | ||||
| 522 | if (code < 0 || code > SYS_MAXSYSCALL331 - 1) | |||
| 523 | return (EINVAL22); | |||
| 524 | ||||
| 525 | if (pledge_syscalls[code] == PLEDGE_ALWAYS0xffffffffffffffffULL) | |||
| 526 | return (0); | |||
| 527 | ||||
| 528 | if (p->p_p->ps_pledge & pledge_syscalls[code]) | |||
| 529 | return (0); | |||
| 530 | ||||
| 531 | *tval = pledge_syscalls[code]; | |||
| 532 | return (EPERM1); | |||
| 533 | } | |||
| 534 | ||||
| 535 | int | |||
| 536 | pledge_fail(struct proc *p, int error, uint64_t code) | |||
| 537 | { | |||
| 538 | const char *codes = ""; | |||
| 539 | int i; | |||
| 540 | ||||
| 541 | /* Print first matching pledge */ | |||
| 542 | for (i = 0; code && pledgenames[i].bits != 0; i++) | |||
| 543 | if (pledgenames[i].bits & code) { | |||
| 544 | codes = pledgenames[i].name; | |||
| 545 | break; | |||
| 546 | } | |||
| 547 | #ifdef KTRACE1 | |||
| 548 | if (KTRPOINT(p, KTR_PLEDGE)((p)->p_p->ps_traceflag & (1<<(12)) && ((p)->p_flag & 0x00000001) == 0)) | |||
| 549 | ktrpledge(p, error, code, p->p_pledge_syscall); | |||
| 550 | #endif | |||
| 551 | if (p->p_p->ps_pledge & PLEDGE_ERROR0x0000000400000000ULL) | |||
| 552 | return (ENOSYS78); | |||
| 553 | ||||
| 554 | KERNEL_LOCK()_kernel_lock(); | |||
| 555 | log(LOG_ERR3, "%s[%d]: pledge \"%s\", syscall %d\n", | |||
| 556 | p->p_p->ps_comm, p->p_p->ps_pid, codes, p->p_pledge_syscall); | |||
| 557 | p->p_p->ps_acflag |= APLEDGE0x20; | |||
| 558 | ||||
| 559 | /* Stop threads immediately, because this process is suspect */ | |||
| 560 | if (P_HASSIBLING(p)(((&(p)->p_p->ps_threads)->tqh_first) != (p) || ( ((p))->p_thr_link.tqe_next) != ((void *)0))) | |||
| 561 | single_thread_set(p, SINGLE_SUSPEND, 1); | |||
| 562 | ||||
| 563 | /* Send uncatchable SIGABRT for coredump */ | |||
| 564 | sigabort(p); | |||
| 565 | ||||
| 566 | p->p_p->ps_pledge = 0; /* Disable all PLEDGE_ flags */ | |||
| 567 | KERNEL_UNLOCK()_kernel_unlock(); | |||
| 568 | return (error); | |||
| 569 | } | |||
| 570 | ||||
| 571 | /* | |||
| 572 | * Need to make it more obvious that one cannot get through here | |||
| 573 | * without the right flags set | |||
| 574 | */ | |||
| 575 | int | |||
| 576 | pledge_namei(struct proc *p, struct nameidata *ni, char *origpath) | |||
| 577 | { | |||
| 578 | char path[PATH_MAX1024]; | |||
| 579 | uint64_t pledge; | |||
| 580 | int error; | |||
| 581 | ||||
| 582 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0 || | |||
| 583 | (p->p_p->ps_flags & PS_COREDUMP0x00000800)) | |||
| 584 | return (0); | |||
| 585 | pledge = p->p_p->ps_pledge; | |||
| 586 | ||||
| 587 | if (ni->ni_pledge == 0) | |||
| 588 | panic("pledge_namei: ni_pledge"); | |||
| 589 | ||||
| 590 | /* | |||
| 591 | * We set the BYPASSUNVEIL flag to skip unveil checks | |||
| 592 | * as necessary | |||
| 593 | */ | |||
| 594 | ||||
| 595 | /* Doing a permitted execve() */ | |||
| 596 | if ((ni->ni_pledge & PLEDGE_EXEC0x0000000000080000ULL) && | |||
| 597 | (pledge & PLEDGE_EXEC0x0000000000080000ULL)) | |||
| 598 | return (0); | |||
| 599 | ||||
| 600 | error = canonpath(origpath, path, sizeof(path)); | |||
| 601 | if (error) | |||
| 602 | return (error); | |||
| 603 | ||||
| 604 | /* Detect what looks like a mkstemp(3) family operation */ | |||
| 605 | if ((pledge & PLEDGE_TMPPATH0x0000000000000010ULL) && | |||
| 606 | (p->p_pledge_syscall == SYS_open5) && | |||
| 607 | (ni->ni_pledge & PLEDGE_CPATH0x0000000000000004ULL) && | |||
| 608 | strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { | |||
| 609 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 610 | return (0); | |||
| 611 | } | |||
| 612 | ||||
| 613 | /* Allow unlinking of a mkstemp(3) file... | |||
| 614 | * Good opportunity for strict checks here. | |||
| 615 | */ | |||
| 616 | if ((pledge & PLEDGE_TMPPATH0x0000000000000010ULL) && | |||
| 617 | (p->p_pledge_syscall == SYS_unlink10) && | |||
| 618 | strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { | |||
| 619 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 620 | return (0); | |||
| 621 | } | |||
| 622 | ||||
| 623 | /* Whitelisted paths */ | |||
| 624 | switch (p->p_pledge_syscall) { | |||
| 625 | case SYS_access33: | |||
| 626 | /* tzset() needs this. */ | |||
| 627 | if (ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL && | |||
| 628 | strcmp(path, "/etc/localtime") == 0) { | |||
| 629 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 630 | return (0); | |||
| 631 | } | |||
| 632 | ||||
| 633 | /* when avoiding YP mode, getpw* functions touch this */ | |||
| 634 | if (ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL && | |||
| 635 | strcmp(path, "/var/run/ypbind.lock") == 0) { | |||
| 636 | if (pledge & PLEDGE_GETPW0x0000000000000800ULL) { | |||
| 637 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 638 | return (0); | |||
| 639 | } else | |||
| 640 | return (pledge_fail(p, error, PLEDGE_GETPW0x0000000000000800ULL)); | |||
| 641 | } | |||
| 642 | break; | |||
| 643 | case SYS_open5: | |||
| 644 | /* daemon(3) or other such functions */ | |||
| 645 | if ((ni->ni_pledge & ~(PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL)) == 0 && | |||
| 646 | strcmp(path, "/dev/null") == 0) { | |||
| 647 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 648 | return (0); | |||
| 649 | } | |||
| 650 | ||||
| 651 | /* readpassphrase(3), getpass(3) */ | |||
| 652 | if ((pledge & PLEDGE_TTY0x0000000000010000ULL) && | |||
| 653 | (ni->ni_pledge & ~(PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_WPATH0x0000000000000002ULL)) == 0 && | |||
| 654 | strcmp(path, "/dev/tty") == 0) { | |||
| 655 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 656 | return (0); | |||
| 657 | } | |||
| 658 | ||||
| 659 | /* getpw* and friends need a few files */ | |||
| 660 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
| 661 | (pledge & PLEDGE_GETPW0x0000000000000800ULL)) { | |||
| 662 | if (strcmp(path, "/etc/spwd.db") == 0) | |||
| 663 | return (EPERM1); /* don't call pledge_fail */ | |||
| 664 | if (strcmp(path, "/etc/pwd.db") == 0) { | |||
| 665 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 666 | return (0); | |||
| 667 | } | |||
| 668 | if (strcmp(path, "/etc/group") == 0) { | |||
| 669 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 670 | return (0); | |||
| 671 | } | |||
| 672 | if (strcmp(path, "/etc/netid") == 0) { | |||
| 673 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 674 | return (0); | |||
| 675 | } | |||
| 676 | } | |||
| 677 | ||||
| 678 | /* DNS needs /etc/{resolv.conf,hosts,services,protocols}. */ | |||
| 679 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
| 680 | (pledge & PLEDGE_DNS0x0000000000000020ULL)) { | |||
| 681 | if (strcmp(path, "/etc/resolv.conf") == 0) { | |||
| 682 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 683 | return (0); | |||
| 684 | } | |||
| 685 | if (strcmp(path, "/etc/hosts") == 0) { | |||
| 686 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 687 | return (0); | |||
| 688 | } | |||
| 689 | if (strcmp(path, "/etc/services") == 0) { | |||
| 690 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 691 | return (0); | |||
| 692 | } | |||
| 693 | if (strcmp(path, "/etc/protocols") == 0) { | |||
| 694 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 695 | return (0); | |||
| 696 | } | |||
| 697 | } | |||
| 698 | ||||
| 699 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
| 700 | (pledge & PLEDGE_GETPW0x0000000000000800ULL)) { | |||
| 701 | if (strcmp(path, "/var/run/ypbind.lock") == 0) { | |||
| 702 | /* | |||
| 703 | * XXX | |||
| 704 | * The current hack for YP support in "getpw" | |||
| 705 | * is to enable some "inet" features until | |||
| 706 | * next pledge call. Setting a bit in ps_pledge | |||
| 707 | * is not safe with respect to multiple threads, | |||
| 708 | * a very different approach is needed. | |||
| 709 | */ | |||
| 710 | p->p_p->ps_pledge |= PLEDGE_YPACTIVE0x8000000000000000ULL; | |||
| 711 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 712 | return (0); | |||
| 713 | } | |||
| 714 | if (strncmp(path, "/var/yp/binding/", | |||
| 715 | sizeof("/var/yp/binding/") - 1) == 0) { | |||
| 716 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 717 | return (0); | |||
| 718 | } | |||
| 719 | } | |||
| 720 | ||||
| 721 | /* tzset() needs these. */ | |||
| 722 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
| 723 | strncmp(path, "/usr/share/zoneinfo/", | |||
| 724 | sizeof("/usr/share/zoneinfo/") - 1) == 0) { | |||
| 725 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 726 | return (0); | |||
| 727 | } | |||
| 728 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
| 729 | strcmp(path, "/etc/localtime") == 0) { | |||
| 730 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 731 | return (0); | |||
| 732 | } | |||
| 733 | ||||
| 734 | break; | |||
| 735 | case SYS_stat38: | |||
| 736 | /* DNS needs /etc/resolv.conf. */ | |||
| 737 | if ((ni->ni_pledge == PLEDGE_RPATH0x0000000000000001ULL) && | |||
| 738 | (pledge & PLEDGE_DNS0x0000000000000020ULL) && | |||
| 739 | strcmp(path, "/etc/resolv.conf") == 0) { | |||
| 740 | ni->ni_cnd.cn_flags |= BYPASSUNVEIL0x400000; | |||
| 741 | return (0); | |||
| 742 | } | |||
| 743 | break; | |||
| 744 | } | |||
| 745 | ||||
| 746 | /* | |||
| 747 | * Ensure each flag of ni_pledge has counterpart allowing it in | |||
| 748 | * ps_pledge. | |||
| 749 | */ | |||
| 750 | if (ni->ni_pledge & ~pledge) | |||
| 751 | return (pledge_fail(p, EPERM1, (ni->ni_pledge & ~pledge))); | |||
| 752 | ||||
| 753 | /* continue, and check unveil if present */ | |||
| 754 | return (0); | |||
| 755 | } | |||
| 756 | ||||
| 757 | /* | |||
| 758 | * Only allow reception of safe file descriptors. | |||
| 759 | */ | |||
| 760 | int | |||
| 761 | pledge_recvfd(struct proc *p, struct file *fp) | |||
| 762 | { | |||
| 763 | struct vnode *vp; | |||
| 764 | ||||
| 765 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 766 | return (0); | |||
| 767 | if ((p->p_p->ps_pledge & PLEDGE_RECVFD0x0000000000040000ULL) == 0) | |||
| 768 | return pledge_fail(p, EPERM1, PLEDGE_RECVFD0x0000000000040000ULL); | |||
| 769 | ||||
| 770 | switch (fp->f_type) { | |||
| 771 | case DTYPE_SOCKET2: | |||
| 772 | case DTYPE_PIPE3: | |||
| 773 | case DTYPE_DMABUF5: | |||
| 774 | return (0); | |||
| 775 | case DTYPE_VNODE1: | |||
| 776 | vp = fp->f_data; | |||
| 777 | ||||
| 778 | if (vp->v_type != VDIR) | |||
| 779 | return (0); | |||
| 780 | } | |||
| 781 | return pledge_fail(p, EINVAL22, PLEDGE_RECVFD0x0000000000040000ULL); | |||
| 782 | } | |||
| 783 | ||||
| 784 | /* | |||
| 785 | * Only allow sending of safe file descriptors. | |||
| 786 | */ | |||
| 787 | int | |||
| 788 | pledge_sendfd(struct proc *p, struct file *fp) | |||
| 789 | { | |||
| 790 | struct vnode *vp; | |||
| 791 | ||||
| 792 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 793 | return (0); | |||
| 794 | if ((p->p_p->ps_pledge & PLEDGE_SENDFD0x0000000000020000ULL) == 0) | |||
| 795 | return pledge_fail(p, EPERM1, PLEDGE_SENDFD0x0000000000020000ULL); | |||
| 796 | ||||
| 797 | switch (fp->f_type) { | |||
| 798 | case DTYPE_SOCKET2: | |||
| 799 | case DTYPE_PIPE3: | |||
| 800 | case DTYPE_DMABUF5: | |||
| 801 | return (0); | |||
| 802 | case DTYPE_VNODE1: | |||
| 803 | vp = fp->f_data; | |||
| 804 | ||||
| 805 | if (vp->v_type != VDIR) | |||
| 806 | return (0); | |||
| 807 | break; | |||
| 808 | } | |||
| 809 | return pledge_fail(p, EINVAL22, PLEDGE_SENDFD0x0000000000020000ULL); | |||
| 810 | } | |||
| 811 | ||||
| 812 | int | |||
| 813 | pledge_sysctl(struct proc *p, int miblen, int *mib, void *new) | |||
| 814 | { | |||
| 815 | char buf[80]; | |||
| 816 | uint64_t pledge; | |||
| 817 | int i; | |||
| 818 | ||||
| 819 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 820 | return (0); | |||
| 821 | pledge = p->p_p->ps_pledge; | |||
| 822 | ||||
| 823 | if (new) | |||
| 824 | return pledge_fail(p, EFAULT14, 0); | |||
| 825 | ||||
| 826 | /* routing table observation */ | |||
| 827 | if ((pledge & PLEDGE_ROUTE0x0000000000100000ULL)) { | |||
| 828 | if ((miblen == 6 || miblen == 7) && | |||
| 829 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
| 830 | mib[2] == 0 && | |||
| 831 | mib[4] == NET_RT_DUMP1) | |||
| 832 | return (0); | |||
| 833 | ||||
| 834 | if (miblen == 6 && | |||
| 835 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
| 836 | mib[2] == 0 && | |||
| 837 | (mib[3] == 0 || mib[3] == AF_INET624 || mib[3] == AF_INET2) && | |||
| 838 | (mib[4] == NET_RT_TABLE5 || mib[4] == NET_RT_SOURCE7)) | |||
| 839 | return (0); | |||
| 840 | ||||
| 841 | if (miblen == 7 && /* exposes MACs */ | |||
| 842 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
| 843 | mib[2] == 0 && | |||
| 844 | (mib[3] == 0 || mib[3] == AF_INET624 || mib[3] == AF_INET2) && | |||
| 845 | mib[4] == NET_RT_FLAGS2 && mib[5] == RTF_LLINFO0x400) | |||
| 846 | return (0); | |||
| 847 | } | |||
| 848 | ||||
| 849 | if ((pledge & PLEDGE_WROUTE0x0000000800000000ULL)) { | |||
| 850 | if (miblen == 4 && | |||
| 851 | mib[0] == CTL_NET4 && mib[1] == PF_INET624 && | |||
| 852 | mib[2] == IPPROTO_IPV641 && mib[3] == IPV6CTL_SOIIKEY54) | |||
| 853 | return (0); | |||
| 854 | } | |||
| 855 | ||||
| 856 | if (pledge & (PLEDGE_PS0x0000000000800000ULL | PLEDGE_VMINFO0x0000000000400000ULL)) { | |||
| 857 | if (miblen == 2 && /* kern.fscale */ | |||
| 858 | mib[0] == CTL_KERN1 && mib[1] == KERN_FSCALE46) | |||
| 859 | return (0); | |||
| 860 | if (miblen == 2 && /* kern.boottime */ | |||
| 861 | mib[0] == CTL_KERN1 && mib[1] == KERN_BOOTTIME21) | |||
| 862 | return (0); | |||
| 863 | if (miblen == 2 && /* kern.consdev */ | |||
| 864 | mib[0] == CTL_KERN1 && mib[1] == KERN_CONSDEV75) | |||
| 865 | return (0); | |||
| 866 | if (miblen == 2 && /* kern.cptime */ | |||
| 867 | mib[0] == CTL_KERN1 && mib[1] == KERN_CPTIME40) | |||
| 868 | return (0); | |||
| 869 | if (miblen == 3 && /* kern.cptime2 */ | |||
| 870 | mib[0] == CTL_KERN1 && mib[1] == KERN_CPTIME271) | |||
| 871 | return (0); | |||
| 872 | if (miblen == 3 && /* kern.cpustats */ | |||
| 873 | mib[0] == CTL_KERN1 && mib[1] == KERN_CPUSTATS85) | |||
| 874 | return (0); | |||
| 875 | } | |||
| 876 | ||||
| 877 | if ((pledge & PLEDGE_PS0x0000000000800000ULL)) { | |||
| 878 | if (miblen == 4 && /* kern.procargs.* */ | |||
| 879 | mib[0] == CTL_KERN1 && mib[1] == KERN_PROC_ARGS55 && | |||
| 880 | (mib[3] == KERN_PROC_ARGV1 || mib[3] == KERN_PROC_ENV3)) | |||
| 881 | return (0); | |||
| 882 | if (miblen == 6 && /* kern.proc.* */ | |||
| 883 | mib[0] == CTL_KERN1 && mib[1] == KERN_PROC66) | |||
| 884 | return (0); | |||
| 885 | if (miblen == 3 && /* kern.proc_cwd.* */ | |||
| 886 | mib[0] == CTL_KERN1 && mib[1] == KERN_PROC_CWD78) | |||
| 887 | return (0); | |||
| 888 | if (miblen == 2 && /* kern.ccpu */ | |||
| 889 | mib[0] == CTL_KERN1 && mib[1] == KERN_CCPU45) | |||
| 890 | return (0); | |||
| 891 | if (miblen == 2 && /* vm.maxslp */ | |||
| 892 | mib[0] == CTL_VM2 && mib[1] == VM_MAXSLP10) | |||
| 893 | return (0); | |||
| 894 | } | |||
| 895 | ||||
| 896 | if ((pledge & PLEDGE_VMINFO0x0000000000400000ULL)) { | |||
| 897 | if (miblen == 2 && /* vm.uvmexp */ | |||
| 898 | mib[0] == CTL_VM2 && mib[1] == VM_UVMEXP4) | |||
| 899 | return (0); | |||
| 900 | if (miblen == 3 && /* vfs.generic.bcachestat */ | |||
| 901 | mib[0] == CTL_VFS10 && mib[1] == VFS_GENERIC0 && | |||
| 902 | mib[2] == VFS_BCACHESTAT3) | |||
| 903 | return (0); | |||
| 904 | } | |||
| 905 | ||||
| 906 | if ((pledge & (PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL))) { | |||
| 907 | if (miblen == 2 && /* kern.somaxconn */ | |||
| 908 | mib[0] == CTL_KERN1 && mib[1] == KERN_SOMAXCONN28) | |||
| 909 | return (0); | |||
| 910 | } | |||
| 911 | ||||
| 912 | if ((pledge & (PLEDGE_ROUTE0x0000000000100000ULL | PLEDGE_INET0x0000000000000040ULL | PLEDGE_DNS0x0000000000000020ULL))) { | |||
| 913 | if (miblen == 6 && /* getifaddrs() */ | |||
| 914 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
| 915 | mib[2] == 0 && | |||
| 916 | (mib[3] == 0 || mib[3] == AF_INET624 || mib[3] == AF_INET2) && | |||
| 917 | mib[4] == NET_RT_IFLIST3) | |||
| 918 | return (0); | |||
| 919 | } | |||
| 920 | ||||
| 921 | if ((pledge & PLEDGE_DISKLABEL0x0000000002000000ULL)) { | |||
| 922 | if (miblen == 2 && /* kern.rawpartition */ | |||
| 923 | mib[0] == CTL_KERN1 && | |||
| 924 | mib[1] == KERN_RAWPARTITION24) | |||
| 925 | return (0); | |||
| 926 | if (miblen == 2 && /* kern.maxpartitions */ | |||
| 927 | mib[0] == CTL_KERN1 && | |||
| 928 | mib[1] == KERN_MAXPARTITIONS23) | |||
| 929 | return (0); | |||
| 930 | #ifdef CPU_CHR2BLK4 | |||
| 931 | if (miblen == 3 && /* machdep.chr2blk */ | |||
| 932 | mib[0] == CTL_MACHDEP7 && | |||
| 933 | mib[1] == CPU_CHR2BLK4) | |||
| 934 | return (0); | |||
| 935 | #endif /* CPU_CHR2BLK */ | |||
| 936 | } | |||
| 937 | ||||
| 938 | if (miblen >= 3 && /* ntpd(8) to read sensors */ | |||
| 939 | mib[0] == CTL_HW6 && mib[1] == HW_SENSORS11) | |||
| 940 | return (0); | |||
| 941 | ||||
| 942 | if (miblen == 6 && /* if_nameindex() */ | |||
| 943 | mib[0] == CTL_NET4 && mib[1] == PF_ROUTE17 && | |||
| 944 | mib[2] == 0 && mib[3] == 0 && mib[4] == NET_RT_IFNAMES6) | |||
| 945 | return (0); | |||
| 946 | ||||
| 947 | if (miblen == 2) { | |||
| 948 | switch (mib[0]) { | |||
| 949 | case CTL_KERN1: | |||
| 950 | switch (mib[1]) { | |||
| 951 | case KERN_DOMAINNAME22: /* getdomainname() */ | |||
| 952 | case KERN_HOSTNAME10: /* gethostname() */ | |||
| 953 | case KERN_OSTYPE1: /* uname() */ | |||
| 954 | case KERN_OSRELEASE2: /* uname() */ | |||
| 955 | case KERN_OSVERSION27: /* uname() */ | |||
| 956 | case KERN_VERSION4: /* uname() */ | |||
| 957 | case KERN_CLOCKRATE12: /* kern.clockrate */ | |||
| 958 | case KERN_ARGMAX8: /* kern.argmax */ | |||
| 959 | case KERN_NGROUPS18: /* kern.ngroups */ | |||
| 960 | case KERN_SYSVSHM36: /* kern.sysvshm */ | |||
| 961 | case KERN_POSIX117: /* kern.posix1version */ | |||
| 962 | return (0); | |||
| 963 | } | |||
| 964 | break; | |||
| 965 | case CTL_HW6: | |||
| 966 | switch (mib[1]) { | |||
| 967 | case HW_MACHINE1: /* uname() */ | |||
| 968 | case HW_PAGESIZE7: /* getpagesize() */ | |||
| 969 | case HW_PHYSMEM6419: /* hw.physmem */ | |||
| 970 | case HW_NCPU3: /* hw.ncpu */ | |||
| 971 | case HW_NCPUONLINE25: /* hw.ncpuonline */ | |||
| 972 | return (0); | |||
| 973 | } | |||
| 974 | break; | |||
| 975 | case CTL_VM2: | |||
| 976 | switch (mib[1]) { | |||
| 977 | case VM_PSSTRINGS3: /* setproctitle() */ | |||
| 978 | case VM_LOADAVG2: /* vm.loadavg / getloadavg(3) */ | |||
| 979 | case VM_MALLOC_CONF12: /* vm.malloc_conf */ | |||
| 980 | return (0); | |||
| 981 | } | |||
| 982 | break; | |||
| 983 | default: | |||
| 984 | break; | |||
| 985 | } | |||
| 986 | } | |||
| 987 | ||||
| 988 | #ifdef CPU_SSE | |||
| 989 | if (miblen == 2 && /* i386 libm tests for SSE */ | |||
| 990 | mib[0] == CTL_MACHDEP7 && mib[1] == CPU_SSE) | |||
| 991 | return (0); | |||
| 992 | #endif /* CPU_SSE */ | |||
| 993 | ||||
| 994 | snprintf(buf, sizeof(buf), "%s(%d): pledge sysctl %d:", | |||
| 995 | p->p_p->ps_comm, p->p_p->ps_pid, miblen); | |||
| 996 | for (i = 0; i < miblen; i++) { | |||
| 997 | char *p = buf + strlen(buf); | |||
| 998 | snprintf(p, sizeof(buf) - (p - buf), " %d", mib[i]); | |||
| 999 | } | |||
| 1000 | log(LOG_ERR3, "%s\n", buf); | |||
| 1001 | ||||
| 1002 | return pledge_fail(p, EINVAL22, 0); | |||
| 1003 | } | |||
| 1004 | ||||
| 1005 | int | |||
| 1006 | pledge_chown(struct proc *p, uid_t uid, gid_t gid) | |||
| 1007 | { | |||
| 1008 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1009 | return (0); | |||
| 1010 | ||||
| 1011 | if (p->p_p->ps_pledge & PLEDGE_CHOWNUID0x0000000100000000ULL) | |||
| 1012 | return (0); | |||
| 1013 | ||||
| 1014 | if (uid != -1 && uid != p->p_ucred->cr_uid) | |||
| 1015 | return (EPERM1); | |||
| 1016 | if (gid != -1 && !groupmember(gid, p->p_ucred)) | |||
| 1017 | return (EPERM1); | |||
| 1018 | return (0); | |||
| 1019 | } | |||
| 1020 | ||||
| 1021 | int | |||
| 1022 | pledge_adjtime(struct proc *p, const void *v) | |||
| 1023 | { | |||
| 1024 | const struct timeval *delta = v; | |||
| 1025 | ||||
| 1026 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1027 | return (0); | |||
| 1028 | ||||
| 1029 | if ((p->p_p->ps_pledge & PLEDGE_SETTIME0x0000000000002000ULL)) | |||
| 1030 | return (0); | |||
| 1031 | if (delta) | |||
| 1032 | return (EPERM1); | |||
| 1033 | return (0); | |||
| 1034 | } | |||
| 1035 | ||||
| 1036 | int | |||
| 1037 | pledge_sendit(struct proc *p, const void *to) | |||
| 1038 | { | |||
| 1039 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1040 | return (0); | |||
| 1041 | ||||
| 1042 | if ((p->p_p->ps_pledge & (PLEDGE_INET0x0000000000000040ULL | PLEDGE_UNIX0x0000000000000100ULL | PLEDGE_DNS0x0000000000000020ULL | PLEDGE_YPACTIVE0x8000000000000000ULL))) | |||
| 1043 | return (0); /* may use address */ | |||
| 1044 | if (to == NULL((void *)0)) | |||
| 1045 | return (0); /* behaves just like write */ | |||
| 1046 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
| 1047 | } | |||
| 1048 | ||||
| 1049 | int | |||
| 1050 | pledge_ioctl(struct proc *p, long com, struct file *fp) | |||
| 1051 | { | |||
| 1052 | struct vnode *vp = NULL((void *)0); | |||
| ||||
| 1053 | int error = EPERM1; | |||
| 1054 | uint64_t pledge; | |||
| 1055 | ||||
| 1056 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1057 | return (0); | |||
| 1058 | pledge = p->p_p->ps_pledge; | |||
| 1059 | ||||
| 1060 | /* | |||
| 1061 | * The ioctl's which are always allowed. | |||
| 1062 | */ | |||
| 1063 | switch (com) { | |||
| 1064 | case FIONREAD((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('f')) << 8) | ((127))): | |||
| 1065 | case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('f')) << 8) | ((126))): | |||
| 1066 | case FIOCLEX((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('f')) << 8) | ((1))): | |||
| 1067 | case FIONCLEX((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('f')) << 8) | ((2))): | |||
| 1068 | return (0); | |||
| 1069 | } | |||
| 1070 | ||||
| 1071 | /* fp != NULL was already checked */ | |||
| 1072 | if (fp->f_type == DTYPE_VNODE1) { | |||
| 1073 | vp = fp->f_data; | |||
| 1074 | if (vp->v_type == VBAD) | |||
| 1075 | return (ENOTTY25); | |||
| 1076 | } | |||
| 1077 | ||||
| 1078 | if ((pledge & PLEDGE_INET0x0000000000000040ULL)) { | |||
| 1079 | switch (com) { | |||
| 1080 | case SIOCATMARK((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('s')) << 8) | ((7))): | |||
| 1081 | case SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((136))): | |||
| 1082 | if (fp->f_type == DTYPE_SOCKET2) | |||
| 1083 | return (0); | |||
| 1084 | break; | |||
| 1085 | } | |||
| 1086 | } | |||
| 1087 | ||||
| 1088 | #if NBPFILTER1 > 0 | |||
| 1089 | if ((pledge & PLEDGE_BPF0x0000000200000000ULL)) { | |||
| 1090 | switch (com) { | |||
| 1091 | case BIOCGSTATS((unsigned long)0x40000000 | ((sizeof(struct bpf_stat) & 0x1fff ) << 16) | ((('B')) << 8) | ((111))): /* bpf: tcpdump privsep on ^C */ | |||
| 1092 | if (fp->f_type == DTYPE_VNODE1 && | |||
| 1093 | fp->f_ops->fo_ioctl == vn_ioctl && | |||
| 1094 | vp->v_type == VCHR && | |||
| 1095 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == bpfopen) | |||
| 1096 | return (0); | |||
| 1097 | break; | |||
| 1098 | } | |||
| 1099 | } | |||
| 1100 | #endif /* NBPFILTER > 0 */ | |||
| 1101 | ||||
| 1102 | if ((pledge & PLEDGE_TAPE0x0000000000000400ULL)) { | |||
| 1103 | switch (com) { | |||
| 1104 | case MTIOCGET((unsigned long)0x40000000 | ((sizeof(struct mtget) & 0x1fff ) << 16) | ((('m')) << 8) | ((2))): | |||
| 1105 | case MTIOCTOP((unsigned long)0x80000000 | ((sizeof(struct mtop) & 0x1fff ) << 16) | ((('m')) << 8) | ((1))): | |||
| 1106 | /* for pax(1) and such, checking tapes... */ | |||
| 1107 | if (fp->f_type == DTYPE_VNODE1 && | |||
| 1108 | vp->v_type == VCHR) { | |||
| 1109 | if (vp->v_flag & VISTTY0x0008) | |||
| 1110 | return (ENOTTY25); | |||
| 1111 | else | |||
| 1112 | return (0); | |||
| 1113 | } | |||
| 1114 | break; | |||
| 1115 | } | |||
| 1116 | } | |||
| 1117 | ||||
| 1118 | #if NDRM1 > 0 | |||
| 1119 | if ((pledge & PLEDGE_DRM0x0000000020000000ULL)) { | |||
| 1120 | if ((fp->f_type == DTYPE_VNODE1) && | |||
| 1121 | (vp->v_type == VCHR) && | |||
| 1122 | (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == drmopen)) { | |||
| 1123 | error = pledge_ioctl_drm(p, com, vp->v_rdevv_un.vu_specinfo->si_rdev); | |||
| 1124 | if (error == 0) | |||
| 1125 | return 0; | |||
| 1126 | } | |||
| 1127 | } | |||
| 1128 | #endif /* NDRM > 0 */ | |||
| 1129 | ||||
| 1130 | #if NAUDIO1 > 0 | |||
| 1131 | if ((pledge & PLEDGE_AUDIO0x0000000008000000ULL)) { | |||
| 1132 | switch (com) { | |||
| 1133 | case AUDIO_GETPOS((unsigned long)0x40000000 | ((sizeof(struct audio_pos) & 0x1fff) << 16) | ((('A')) << 8) | ((35))): | |||
| 1134 | case AUDIO_GETPAR((unsigned long)0x40000000 | ((sizeof(struct audio_swpar) & 0x1fff) << 16) | ((('A')) << 8) | ((36))): | |||
| 1135 | case AUDIO_SETPAR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct audio_swpar) & 0x1fff) << 16) | ((('A')) << 8) | ((37))): | |||
| 1136 | case AUDIO_START((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('A')) << 8) | ((38))): | |||
| 1137 | case AUDIO_STOP((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('A')) << 8) | ((39))): | |||
| 1138 | case AUDIO_MIXER_DEVINFO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (mixer_devinfo_t) & 0x1fff) << 16) | ((('M')) << 8) | ((2))): | |||
| 1139 | case AUDIO_MIXER_READ(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (mixer_ctrl_t) & 0x1fff) << 16) | ((('M')) << 8) | ((0))): | |||
| 1140 | case AUDIO_MIXER_WRITE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (mixer_ctrl_t) & 0x1fff) << 16) | ((('M')) << 8) | ((1))): | |||
| 1141 | if (fp->f_type == DTYPE_VNODE1 && | |||
| 1142 | vp->v_type == VCHR && | |||
| 1143 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == audioopen) | |||
| 1144 | return (0); | |||
| 1145 | } | |||
| 1146 | } | |||
| 1147 | #endif /* NAUDIO > 0 */ | |||
| 1148 | ||||
| 1149 | if ((pledge & PLEDGE_DISKLABEL0x0000000002000000ULL)) { | |||
| 1150 | switch (com) { | |||
| 1151 | case DIOCGDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((101))): | |||
| 1152 | case DIOCGPDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((114))): | |||
| 1153 | case DIOCRLDINFO((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('d')) << 8) | ((115))): | |||
| 1154 | case DIOCWDINFO((unsigned long)0x80000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((103))): | |||
| 1155 | case BIOCDISK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bioc_disk) & 0x1fff) << 16) | ((('B')) << 8) | ((33))): | |||
| 1156 | case BIOCINQ(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bioc_inq) & 0x1fff) << 16) | ((('B')) << 8) | ((32))): | |||
| 1157 | case BIOCINSTALLBOOT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bioc_installboot) & 0x1fff) << 16) | ((('B' )) << 8) | ((41))): | |||
| 1158 | case BIOCVOL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct bioc_vol) & 0x1fff) << 16) | ((('B')) << 8) | ((34))): | |||
| 1159 | if (fp->f_type == DTYPE_VNODE1 && | |||
| 1160 | ((vp->v_type == VCHR && | |||
| 1161 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_type == D_DISK1) || | |||
| 1162 | (vp->v_type == VBLK && | |||
| 1163 | bdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_type == D_DISK1))) | |||
| 1164 | return (0); | |||
| 1165 | break; | |||
| 1166 | case DIOCMAP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct dk_diskmap) & 0x1fff) << 16) | ((('d')) << 8) | ((119))): | |||
| 1167 | if (fp->f_type == DTYPE_VNODE1 && | |||
| 1168 | vp->v_type == VCHR && | |||
| 1169 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_ioctl == diskmapioctl) | |||
| 1170 | return (0); | |||
| 1171 | break; | |||
| 1172 | } | |||
| 1173 | } | |||
| 1174 | ||||
| 1175 | #if NVIDEO1 > 0 | |||
| 1176 | if ((pledge & PLEDGE_VIDEO0x0000002000000000ULL)) { | |||
| 1177 | switch (com) { | |||
| 1178 | case VIDIOC_QUERYCAP((unsigned long)0x40000000 | ((sizeof(struct v4l2_capability) & 0x1fff) << 16) | ((('V')) << 8) | ((0))): | |||
| 1179 | case VIDIOC_TRY_FMT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_format) & 0x1fff) << 16) | ((('V')) << 8) | ((64))): | |||
| 1180 | case VIDIOC_ENUM_FMT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_fmtdesc) & 0x1fff) << 16) | ((('V')) << 8) | ((2))): | |||
| 1181 | case VIDIOC_S_FMT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_format) & 0x1fff) << 16) | ((('V')) << 8) | ((5))): | |||
| 1182 | case VIDIOC_QUERYCTRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_queryctrl) & 0x1fff) << 16) | ((('V')) << 8) | ((36))): | |||
| 1183 | case VIDIOC_G_CTRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_control) & 0x1fff) << 16) | ((('V')) << 8) | ((27))): | |||
| 1184 | case VIDIOC_S_CTRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_control) & 0x1fff) << 16) | ((('V')) << 8) | ((28))): | |||
| 1185 | case VIDIOC_G_PARM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_streamparm) & 0x1fff) << 16) | ((('V') ) << 8) | ((21))): | |||
| 1186 | case VIDIOC_S_PARM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_streamparm) & 0x1fff) << 16) | ((('V') ) << 8) | ((22))): | |||
| 1187 | case VIDIOC_REQBUFS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_requestbuffers) & 0x1fff) << 16) | ((( 'V')) << 8) | ((8))): | |||
| 1188 | case VIDIOC_QBUF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_buffer) & 0x1fff) << 16) | ((('V')) << 8) | ((15))): | |||
| 1189 | case VIDIOC_DQBUF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_buffer) & 0x1fff) << 16) | ((('V')) << 8) | ((17))): | |||
| 1190 | case VIDIOC_QUERYBUF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_buffer) & 0x1fff) << 16) | ((('V')) << 8) | ((9))): | |||
| 1191 | case VIDIOC_STREAMON((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('V')) << 8) | ((18))): | |||
| 1192 | case VIDIOC_STREAMOFF((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('V')) << 8) | ((19))): | |||
| 1193 | case VIDIOC_ENUM_FRAMESIZES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_frmsizeenum) & 0x1fff) << 16) | ((('V' )) << 8) | ((74))): | |||
| 1194 | case VIDIOC_ENUM_FRAMEINTERVALS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_frmivalenum) & 0x1fff) << 16) | ((('V' )) << 8) | ((75))): | |||
| 1195 | case VIDIOC_DQEVENT((unsigned long)0x40000000 | ((sizeof(struct v4l2_event) & 0x1fff) << 16) | ((('V')) << 8) | ((89))): | |||
| 1196 | case VIDIOC_ENCODER_CMD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_encoder_cmd) & 0x1fff) << 16) | ((('V' )) << 8) | ((77))): | |||
| 1197 | case VIDIOC_EXPBUF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_exportbuffer) & 0x1fff) << 16) | ((('V' )) << 8) | ((16))): | |||
| 1198 | case VIDIOC_G_CROP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_crop) & 0x1fff) << 16) | ((('V')) << 8) | ((59))): | |||
| 1199 | case VIDIOC_G_EXT_CTRLS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_ext_controls) & 0x1fff) << 16) | ((('V' )) << 8) | ((71))): | |||
| 1200 | case VIDIOC_G_FMT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_format) & 0x1fff) << 16) | ((('V')) << 8) | ((4))): | |||
| 1201 | case VIDIOC_G_SELECTION(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_selection) & 0x1fff) << 16) | ((('V')) << 8) | ((94))): | |||
| 1202 | case VIDIOC_QUERYMENU(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_querymenu) & 0x1fff) << 16) | ((('V')) << 8) | ((37))): | |||
| 1203 | case VIDIOC_SUBSCRIBE_EVENT((unsigned long)0x80000000 | ((sizeof(struct v4l2_event_subscription ) & 0x1fff) << 16) | ((('V')) << 8) | ((90))): | |||
| 1204 | case VIDIOC_S_EXT_CTRLS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_ext_controls) & 0x1fff) << 16) | ((('V' )) << 8) | ((72))): | |||
| 1205 | case VIDIOC_S_SELECTION(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_selection) & 0x1fff) << 16) | ((('V')) << 8) | ((95))): | |||
| 1206 | case VIDIOC_TRY_DECODER_CMD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_decoder_cmd) & 0x1fff) << 16) | ((('V' )) << 8) | ((97))): | |||
| 1207 | case VIDIOC_TRY_ENCODER_CMD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct v4l2_encoder_cmd) & 0x1fff) << 16) | ((('V' )) << 8) | ((78))): | |||
| 1208 | if (fp->f_type == DTYPE_VNODE1 && | |||
| 1209 | vp->v_type == VCHR && | |||
| 1210 | cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == videoopen) | |||
| 1211 | return (0); | |||
| 1212 | break; | |||
| 1213 | } | |||
| 1214 | } | |||
| 1215 | #endif | |||
| 1216 | ||||
| 1217 | #if NPF1 > 0 | |||
| 1218 | if ((pledge & PLEDGE_PF0x0000000004000000ULL)) { | |||
| 1219 | switch (com) { | |||
| 1220 | case DIOCADDRULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_rule) & 0x1fff) << 16) | ((('D')) << 8) | ((4))): | |||
| 1221 | case DIOCGETSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pf_status) & 0x1fff) << 16) | ((('D')) << 8) | ((21))): | |||
| 1222 | case DIOCNATLOOK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_natlook) & 0x1fff) << 16) | ((('D')) << 8) | ((23))): | |||
| 1223 | case DIOCRADDTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((61))): | |||
| 1224 | case DIOCRCLRADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((66))): | |||
| 1225 | case DIOCRCLRTABLES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((60))): | |||
| 1226 | case DIOCRCLRTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((65))): | |||
| 1227 | case DIOCRGETTSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((64))): | |||
| 1228 | case DIOCRSETADDRS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_table) & 0x1fff) << 16) | ((('D')) << 8) | ((69))): | |||
| 1229 | case DIOCXBEGIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_trans) & 0x1fff) << 16) | ((('D')) << 8) | ((81))): | |||
| 1230 | case DIOCXCOMMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_trans) & 0x1fff) << 16) | ((('D')) << 8) | ((82))): | |||
| 1231 | case DIOCKILLSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pfioc_src_node_kill) & 0x1fff) << 16) | ((( 'D')) << 8) | ((91))): | |||
| 1232 | if ((fp->f_type == DTYPE_VNODE1) && | |||
| 1233 | (vp->v_type == VCHR) && | |||
| 1234 | (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == pfopen)) | |||
| 1235 | return (0); | |||
| 1236 | break; | |||
| 1237 | } | |||
| 1238 | } | |||
| 1239 | #endif | |||
| 1240 | ||||
| 1241 | if ((pledge & PLEDGE_TTY0x0000000000010000ULL)) { | |||
| 1242 | switch (com) { | |||
| 1243 | #if NPTY16 > 0 | |||
| 1244 | case PTMGET((unsigned long)0x40000000 | ((sizeof(struct ptmget) & 0x1fff ) << 16) | ((('t')) << 8) | ((1))): | |||
| 1245 | if ((pledge & PLEDGE_RPATH0x0000000000000001ULL) == 0) | |||
| 1246 | break; | |||
| 1247 | if ((pledge & PLEDGE_WPATH0x0000000000000002ULL) == 0) | |||
| 1248 | break; | |||
| 1249 | if (fp->f_type != DTYPE_VNODE1 || vp->v_type != VCHR) | |||
| 1250 | break; | |||
| 1251 | if (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open != ptmopen) | |||
| 1252 | break; | |||
| 1253 | return (0); | |||
| 1254 | case TIOCUCNTL((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((102))): /* vmd */ | |||
| 1255 | if ((pledge & PLEDGE_RPATH0x0000000000000001ULL) == 0) | |||
| 1256 | break; | |||
| 1257 | if ((pledge & PLEDGE_WPATH0x0000000000000002ULL) == 0) | |||
| 1258 | break; | |||
| 1259 | if (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open != ptcopen) | |||
| ||||
| 1260 | break; | |||
| 1261 | return (0); | |||
| 1262 | #endif /* NPTY > 0 */ | |||
| 1263 | case TIOCSPGRP((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((118))): | |||
| 1264 | if ((pledge & PLEDGE_PROC0x0000000000001000ULL) == 0) | |||
| 1265 | break; | |||
| 1266 | /* FALLTHROUGH */ | |||
| 1267 | case TIOCFLUSH((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((16))): /* getty, telnet */ | |||
| 1268 | case TIOCSTART((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((110))): /* emacs, etc */ | |||
| 1269 | case TIOCGPGRP((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((119))): | |||
| 1270 | case TIOCGETA((unsigned long)0x40000000 | ((sizeof(struct termios) & 0x1fff ) << 16) | ((('t')) << 8) | ((19))): | |||
| 1271 | case TIOCGWINSZ((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff ) << 16) | ((('t')) << 8) | ((104))): /* ENOTTY return for non-tty */ | |||
| 1272 | case TIOCSTAT((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((101))): /* csh */ | |||
| 1273 | if (fp->f_type == DTYPE_VNODE1 && (vp->v_flag & VISTTY0x0008)) | |||
| 1274 | return (0); | |||
| 1275 | return (ENOTTY25); | |||
| 1276 | case TIOCSWINSZ((unsigned long)0x80000000 | ((sizeof(struct winsize) & 0x1fff ) << 16) | ((('t')) << 8) | ((103))): | |||
| 1277 | case TIOCEXT((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((96))): /* mail, libedit .. */ | |||
| 1278 | case TIOCCBRK((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((122))): /* cu */ | |||
| 1279 | case TIOCSBRK((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((123))): /* cu */ | |||
| 1280 | case TIOCCDTR((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((120))): /* cu */ | |||
| 1281 | case TIOCSDTR((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((121))): /* cu */ | |||
| 1282 | case TIOCEXCL((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((13))): /* cu */ | |||
| 1283 | case TIOCSETA((unsigned long)0x80000000 | ((sizeof(struct termios) & 0x1fff ) << 16) | ((('t')) << 8) | ((20))): /* cu, ... */ | |||
| 1284 | case TIOCSETAW((unsigned long)0x80000000 | ((sizeof(struct termios) & 0x1fff ) << 16) | ((('t')) << 8) | ((21))): /* cu, ... */ | |||
| 1285 | case TIOCSETAF((unsigned long)0x80000000 | ((sizeof(struct termios) & 0x1fff ) << 16) | ((('t')) << 8) | ((22))): /* tcsetattr TCSAFLUSH, script */ | |||
| 1286 | case TIOCSCTTY((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((97))): /* forkpty(3), login_tty(3), ... */ | |||
| 1287 | if (fp->f_type == DTYPE_VNODE1 && (vp->v_flag & VISTTY0x0008)) | |||
| 1288 | return (0); | |||
| 1289 | break; | |||
| 1290 | } | |||
| 1291 | } | |||
| 1292 | ||||
| 1293 | if ((pledge & PLEDGE_ROUTE0x0000000000100000ULL)) { | |||
| 1294 | switch (com) { | |||
| 1295 | case SIOCGIFADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((33))): | |||
| 1296 | case SIOCGIFAFLAG_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((73))): | |||
| 1297 | case SIOCGIFALIFETIME_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((81))): | |||
| 1298 | case SIOCGIFDESCR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((129))): | |||
| 1299 | case SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((17))): | |||
| 1300 | case SIOCGIFMETRIC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((23))): | |||
| 1301 | case SIOCGIFGMEMB(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((138))): | |||
| 1302 | case SIOCGIFRDOMAIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((160))): | |||
| 1303 | case SIOCGIFDSTADDR_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((34))): | |||
| 1304 | case SIOCGIFNETMASK_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((37))): | |||
| 1305 | case SIOCGIFXFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((158))): | |||
| 1306 | case SIOCGNBRINFO_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_nbrinfo) & 0x1fff) << 16) | ((('i')) << 8) | ((78))): | |||
| 1307 | case SIOCGIFINFO_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ndireq) & 0x1fff) << 16) | ((('i')) << 8) | ((108))): | |||
| 1308 | case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifmediareq) & 0x1fff) << 16) | ((('i')) << 8) | ((56))): | |||
| 1309 | if (fp->f_type == DTYPE_SOCKET2) | |||
| 1310 | return (0); | |||
| 1311 | break; | |||
| 1312 | } | |||
| 1313 | } | |||
| 1314 | ||||
| 1315 | if ((pledge & PLEDGE_WROUTE0x0000000800000000ULL)) { | |||
| 1316 | switch (com) { | |||
| 1317 | case SIOCAIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifaliasreq) & 0x1fff) << 16) | ((('i')) << 8) | ((26))): | |||
| 1318 | case SIOCDIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((25))): | |||
| 1319 | case SIOCAIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_aliasreq) & 0x1fff) << 16) | ((('i')) << 8) | ((26))): | |||
| 1320 | case SIOCDIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((25))): | |||
| 1321 | if (fp->f_type == DTYPE_SOCKET2) | |||
| 1322 | return (0); | |||
| 1323 | break; | |||
| 1324 | case SIOCSIFMTU((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((127))): | |||
| 1325 | if (fp->f_type == DTYPE_SOCKET2) | |||
| 1326 | return (0); | |||
| 1327 | break; | |||
| 1328 | } | |||
| 1329 | } | |||
| 1330 | ||||
| 1331 | #if NVMM1 > 0 | |||
| 1332 | if ((pledge & PLEDGE_VMM0x0000000040000000ULL)) { | |||
| 1333 | if ((fp->f_type == DTYPE_VNODE1) && | |||
| 1334 | (vp->v_type == VCHR) && | |||
| 1335 | (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8) & 0xff)].d_open == vmmopen)) { | |||
| 1336 | error = pledge_ioctl_vmm(p, com); | |||
| 1337 | if (error == 0) | |||
| 1338 | return 0; | |||
| 1339 | } | |||
| 1340 | } | |||
| 1341 | #endif | |||
| 1342 | ||||
| 1343 | return pledge_fail(p, error, PLEDGE_TTY0x0000000000010000ULL); | |||
| 1344 | } | |||
| 1345 | ||||
| 1346 | int | |||
| 1347 | pledge_sockopt(struct proc *p, int set, int level, int optname) | |||
| 1348 | { | |||
| 1349 | uint64_t pledge; | |||
| 1350 | ||||
| 1351 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1352 | return (0); | |||
| 1353 | pledge = p->p_p->ps_pledge; | |||
| 1354 | ||||
| 1355 | /* Always allow these, which are too common to reject */ | |||
| 1356 | switch (level) { | |||
| 1357 | case SOL_SOCKET0xffff: | |||
| 1358 | switch (optname) { | |||
| 1359 | case SO_RCVBUF0x1002: | |||
| 1360 | case SO_ERROR0x1007: | |||
| 1361 | return 0; | |||
| 1362 | } | |||
| 1363 | break; | |||
| 1364 | } | |||
| 1365 | ||||
| 1366 | if ((pledge & PLEDGE_WROUTE0x0000000800000000ULL)) { | |||
| 1367 | switch (level) { | |||
| 1368 | case SOL_SOCKET0xffff: | |||
| 1369 | switch (optname) { | |||
| 1370 | case SO_RTABLE0x1021: | |||
| 1371 | return (0); | |||
| 1372 | } | |||
| 1373 | } | |||
| 1374 | } | |||
| 1375 | ||||
| 1376 | if ((pledge & (PLEDGE_INET0x0000000000000040ULL|PLEDGE_UNIX0x0000000000000100ULL|PLEDGE_DNS0x0000000000000020ULL|PLEDGE_YPACTIVE0x8000000000000000ULL)) == 0) | |||
| 1377 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
| 1378 | /* In use by some service libraries */ | |||
| 1379 | switch (level) { | |||
| 1380 | case SOL_SOCKET0xffff: | |||
| 1381 | switch (optname) { | |||
| 1382 | case SO_TIMESTAMP0x0800: | |||
| 1383 | return 0; | |||
| 1384 | } | |||
| 1385 | break; | |||
| 1386 | } | |||
| 1387 | ||||
| 1388 | /* DNS resolver may do these requests */ | |||
| 1389 | if ((pledge & PLEDGE_DNS0x0000000000000020ULL)) { | |||
| 1390 | switch (level) { | |||
| 1391 | case IPPROTO_IPV641: | |||
| 1392 | switch (optname) { | |||
| 1393 | case IPV6_RECVPKTINFO36: | |||
| 1394 | case IPV6_USE_MIN_MTU42: | |||
| 1395 | return (0); | |||
| 1396 | } | |||
| 1397 | } | |||
| 1398 | } | |||
| 1399 | ||||
| 1400 | /* YP may do these requests */ | |||
| 1401 | if (pledge & PLEDGE_YPACTIVE0x8000000000000000ULL) { | |||
| 1402 | switch (level) { | |||
| 1403 | case IPPROTO_IP0: | |||
| 1404 | switch (optname) { | |||
| 1405 | case IP_PORTRANGE19: | |||
| 1406 | return (0); | |||
| 1407 | } | |||
| 1408 | break; | |||
| 1409 | ||||
| 1410 | case IPPROTO_IPV641: | |||
| 1411 | switch (optname) { | |||
| 1412 | case IPV6_PORTRANGE14: | |||
| 1413 | return (0); | |||
| 1414 | } | |||
| 1415 | break; | |||
| 1416 | } | |||
| 1417 | } | |||
| 1418 | ||||
| 1419 | if ((pledge & (PLEDGE_INET0x0000000000000040ULL|PLEDGE_UNIX0x0000000000000100ULL)) == 0) | |||
| 1420 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
| 1421 | switch (level) { | |||
| 1422 | case SOL_SOCKET0xffff: | |||
| 1423 | switch (optname) { | |||
| 1424 | case SO_RTABLE0x1021: | |||
| 1425 | return pledge_fail(p, EINVAL22, PLEDGE_WROUTE0x0000000800000000ULL); | |||
| 1426 | } | |||
| 1427 | return (0); | |||
| 1428 | } | |||
| 1429 | ||||
| 1430 | if ((pledge & PLEDGE_INET0x0000000000000040ULL) == 0) | |||
| 1431 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
| 1432 | switch (level) { | |||
| 1433 | case IPPROTO_TCP6: | |||
| 1434 | switch (optname) { | |||
| 1435 | case TCP_NODELAY0x01: | |||
| 1436 | case TCP_MD5SIG0x04: | |||
| 1437 | case TCP_SACK_ENABLE0x08: | |||
| 1438 | case TCP_MAXSEG0x02: | |||
| 1439 | case TCP_NOPUSH0x10: | |||
| 1440 | return (0); | |||
| 1441 | } | |||
| 1442 | break; | |||
| 1443 | case IPPROTO_IP0: | |||
| 1444 | switch (optname) { | |||
| 1445 | case IP_OPTIONS1: | |||
| 1446 | if (!set) | |||
| 1447 | return (0); | |||
| 1448 | break; | |||
| 1449 | case IP_TOS3: | |||
| 1450 | case IP_TTL4: | |||
| 1451 | case IP_MINTTL32: | |||
| 1452 | case IP_IPDEFTTL37: | |||
| 1453 | case IP_PORTRANGE19: | |||
| 1454 | case IP_RECVDSTADDR7: | |||
| 1455 | case IP_RECVDSTPORT33: | |||
| 1456 | return (0); | |||
| 1457 | case IP_MULTICAST_IF9: | |||
| 1458 | case IP_MULTICAST_TTL10: | |||
| 1459 | case IP_MULTICAST_LOOP11: | |||
| 1460 | case IP_ADD_MEMBERSHIP12: | |||
| 1461 | case IP_DROP_MEMBERSHIP13: | |||
| 1462 | if (pledge & PLEDGE_MCAST0x0000000000200000ULL) | |||
| 1463 | return (0); | |||
| 1464 | break; | |||
| 1465 | } | |||
| 1466 | break; | |||
| 1467 | case IPPROTO_ICMP1: | |||
| 1468 | break; | |||
| 1469 | case IPPROTO_IPV641: | |||
| 1470 | switch (optname) { | |||
| 1471 | case IPV6_TCLASS61: | |||
| 1472 | case IPV6_UNICAST_HOPS4: | |||
| 1473 | case IPV6_MINHOPCOUNT65: | |||
| 1474 | case IPV6_RECVHOPLIMIT37: | |||
| 1475 | case IPV6_PORTRANGE14: | |||
| 1476 | case IPV6_RECVPKTINFO36: | |||
| 1477 | case IPV6_RECVDSTPORT64: | |||
| 1478 | case IPV6_V6ONLY27: | |||
| 1479 | return (0); | |||
| 1480 | case IPV6_MULTICAST_IF9: | |||
| 1481 | case IPV6_MULTICAST_HOPS10: | |||
| 1482 | case IPV6_MULTICAST_LOOP11: | |||
| 1483 | case IPV6_JOIN_GROUP12: | |||
| 1484 | case IPV6_LEAVE_GROUP13: | |||
| 1485 | if (pledge & PLEDGE_MCAST0x0000000000200000ULL) | |||
| 1486 | return (0); | |||
| 1487 | break; | |||
| 1488 | } | |||
| 1489 | break; | |||
| 1490 | case IPPROTO_ICMPV658: | |||
| 1491 | break; | |||
| 1492 | } | |||
| 1493 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
| 1494 | } | |||
| 1495 | ||||
| 1496 | int | |||
| 1497 | pledge_socket(struct proc *p, int domain, unsigned int state) | |||
| 1498 | { | |||
| 1499 | uint64_t pledge; | |||
| 1500 | ||||
| 1501 | if (!ISSET(p->p_p->ps_flags, PS_PLEDGE)((p->p_p->ps_flags) & (0x00100000))) | |||
| 1502 | return 0; | |||
| 1503 | pledge = p->p_p->ps_pledge; | |||
| 1504 | ||||
| 1505 | if (ISSET(state, SS_DNS)((state) & (0x4000))) { | |||
| 1506 | if (ISSET(pledge, PLEDGE_DNS)((pledge) & (0x0000000000000020ULL))) | |||
| 1507 | return 0; | |||
| 1508 | return pledge_fail(p, EPERM1, PLEDGE_DNS0x0000000000000020ULL); | |||
| 1509 | } | |||
| 1510 | ||||
| 1511 | switch (domain) { | |||
| 1512 | case -1: /* accept on any domain */ | |||
| 1513 | return (0); | |||
| 1514 | case AF_INET2: | |||
| 1515 | case AF_INET624: | |||
| 1516 | if (ISSET(pledge, PLEDGE_INET)((pledge) & (0x0000000000000040ULL)) || | |||
| 1517 | ISSET(pledge, PLEDGE_YPACTIVE)((pledge) & (0x8000000000000000ULL))) | |||
| 1518 | return 0; | |||
| 1519 | return pledge_fail(p, EPERM1, PLEDGE_INET0x0000000000000040ULL); | |||
| 1520 | ||||
| 1521 | case AF_UNIX1: | |||
| 1522 | if (ISSET(pledge, PLEDGE_UNIX)((pledge) & (0x0000000000000100ULL))) | |||
| 1523 | return 0; | |||
| 1524 | return pledge_fail(p, EPERM1, PLEDGE_UNIX0x0000000000000100ULL); | |||
| 1525 | } | |||
| 1526 | ||||
| 1527 | return pledge_fail(p, EINVAL22, PLEDGE_INET0x0000000000000040ULL); | |||
| 1528 | } | |||
| 1529 | ||||
| 1530 | int | |||
| 1531 | pledge_flock(struct proc *p) | |||
| 1532 | { | |||
| 1533 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1534 | return (0); | |||
| 1535 | ||||
| 1536 | if ((p->p_p->ps_pledge & PLEDGE_FLOCK0x0000000000000080ULL)) | |||
| 1537 | return (0); | |||
| 1538 | return (pledge_fail(p, EPERM1, PLEDGE_FLOCK0x0000000000000080ULL)); | |||
| 1539 | } | |||
| 1540 | ||||
| 1541 | int | |||
| 1542 | pledge_swapctl(struct proc *p) | |||
| 1543 | { | |||
| 1544 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1545 | return (0); | |||
| 1546 | return (EPERM1); | |||
| 1547 | } | |||
| 1548 | ||||
| 1549 | /* bsearch over pledgereq. return flags value if found, 0 else */ | |||
| 1550 | uint64_t | |||
| 1551 | pledgereq_flags(const char *req_name) | |||
| 1552 | { | |||
| 1553 | int base = 0, cmp, i, lim; | |||
| 1554 | ||||
| 1555 | for (lim = nitems(pledgereq)(sizeof((pledgereq)) / sizeof((pledgereq)[0])); lim != 0; lim >>= 1) { | |||
| 1556 | i = base + (lim >> 1); | |||
| 1557 | cmp = strcmp(req_name, pledgereq[i].name); | |||
| 1558 | if (cmp == 0) | |||
| 1559 | return (pledgereq[i].flags); | |||
| 1560 | if (cmp > 0) { /* not found before, move right */ | |||
| 1561 | base = i + 1; | |||
| 1562 | lim--; | |||
| 1563 | } /* else move left */ | |||
| 1564 | } | |||
| 1565 | return (0); | |||
| 1566 | } | |||
| 1567 | ||||
| 1568 | int | |||
| 1569 | pledge_fcntl(struct proc *p, int cmd) | |||
| 1570 | { | |||
| 1571 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1572 | return (0); | |||
| 1573 | if ((p->p_p->ps_pledge & PLEDGE_PROC0x0000000000001000ULL) == 0 && cmd == F_SETOWN6) | |||
| 1574 | return pledge_fail(p, EPERM1, PLEDGE_PROC0x0000000000001000ULL); | |||
| 1575 | return (0); | |||
| 1576 | } | |||
| 1577 | ||||
| 1578 | int | |||
| 1579 | pledge_kill(struct proc *p, pid_t pid) | |||
| 1580 | { | |||
| 1581 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1582 | return 0; | |||
| 1583 | if (p->p_p->ps_pledge & PLEDGE_PROC0x0000000000001000ULL) | |||
| 1584 | return 0; | |||
| 1585 | if (pid == 0 || pid == p->p_p->ps_pid) | |||
| 1586 | return 0; | |||
| 1587 | return pledge_fail(p, EPERM1, PLEDGE_PROC0x0000000000001000ULL); | |||
| 1588 | } | |||
| 1589 | ||||
| 1590 | int | |||
| 1591 | pledge_protexec(struct proc *p, int prot) | |||
| 1592 | { | |||
| 1593 | if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0) | |||
| 1594 | return 0; | |||
| 1595 | /* Before kbind(2) call, ld.so and crt may create EXEC mappings */ | |||
| 1596 | if (p->p_p->ps_kbind_addr == 0 && p->p_p->ps_kbind_cookie == 0) | |||
| 1597 | return 0; | |||
| 1598 | if (!(p->p_p->ps_pledge & PLEDGE_PROTEXEC0x0000000000008000ULL) && (prot & PROT_EXEC0x04)) | |||
| 1599 | return pledge_fail(p, EPERM1, PLEDGE_PROTEXEC0x0000000000008000ULL); | |||
| 1600 | return 0; | |||
| 1601 | } | |||
| 1602 | ||||
| 1603 | int | |||
| 1604 | canonpath(const char *input, char *buf, size_t bufsize) | |||
| 1605 | { | |||
| 1606 | const char *p; | |||
| 1607 | char *q; | |||
| 1608 | ||||
| 1609 | /* can't canon relative paths, don't bother */ | |||
| 1610 | if (input[0] != '/') { | |||
| 1611 | if (strlcpy(buf, input, bufsize) >= bufsize) | |||
| 1612 | return ENAMETOOLONG63; | |||
| 1613 | return 0; | |||
| 1614 | } | |||
| 1615 | ||||
| 1616 | p = input; | |||
| 1617 | q = buf; | |||
| 1618 | while (*p && (q - buf < bufsize)) { | |||
| 1619 | if (p[0] == '/' && (p[1] == '/' || p[1] == '\0')) { | |||
| 1620 | p += 1; | |||
| 1621 | ||||
| 1622 | } else if (p[0] == '/' && p[1] == '.' && | |||
| 1623 | (p[2] == '/' || p[2] == '\0')) { | |||
| 1624 | p += 2; | |||
| 1625 | ||||
| 1626 | } else if (p[0] == '/' && p[1] == '.' && p[2] == '.' && | |||
| 1627 | (p[3] == '/' || p[3] == '\0')) { | |||
| 1628 | p += 3; | |||
| 1629 | if (q != buf) /* "/../" at start of buf */ | |||
| 1630 | while (*--q != '/') | |||
| 1631 | continue; | |||
| 1632 | ||||
| 1633 | } else { | |||
| 1634 | *q++ = *p++; | |||
| 1635 | } | |||
| 1636 | } | |||
| 1637 | if ((*p == '\0') && (q - buf < bufsize)) { | |||
| 1638 | *q = 0; | |||
| 1639 | return 0; | |||
| 1640 | } else | |||
| 1641 | return ENAMETOOLONG63; | |||
| 1642 | } |