Bug Summary

File:kern/kern_pledge.c
Warning:line 1268, column 15
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

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