Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name kern_pledge.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -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 -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/lib/clang/13.0.0 -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/swsmu -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/powerplay -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/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 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 -D CONFIG_DRM_AMD_DC_DCN3_0 -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 -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 /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/kern/kern_pledge.c
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
85uint64_t pledgereq_flags(const char *req);
86int parsepledges(struct proc *p, const char *kname,
87 const char *promises, u_int64_t *fp);
88int canonpath(const char *input, char *buf, size_t bufsize);
89void unveil_destroy(struct process *ps);
90
91/* #define DEBUG_PLEDGE */
92#ifdef DEBUG_PLEDGE
93int 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 */
104const 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
378static 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
420int
421parsepledges(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
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
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
516int
517pledge_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
535int
536pledge_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 */
575int
576pledge_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 */
760int
761pledge_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 */
787int
788pledge_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
812int
813pledge_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
1005int
1006pledge_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
1021int
1022pledge_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
1036int
1037pledge_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
1049int
1050pledge_ioctl(struct proc *p, long com, struct file *fp)
1051{
1052 struct vnode *vp = NULL((void *)0);
1
'vp' initialized to a null pointer value
1053 int error = EPERM1;
1054 uint64_t pledge;
1055
1056 if ((p->p_p->ps_flags & PS_PLEDGE0x00100000) == 0)
2
Assuming the condition is false
3
Taking false branch
1057 return (0);
1058 pledge = p->p_p->ps_pledge;
1059
1060 /*
1061 * The ioctl's which are always allowed.
1062 */
1063 switch (com) {
4
'Default' branch taken. Execution continues on line 1072
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) {
5
Assuming field 'f_type' is not equal to DTYPE_VNODE
6
Taking false branch
1073 vp = fp->f_data;
1074 if (vp->v_type == VBAD)
1075 return (ENOTTY25);
1076 }
1077
1078 if ((pledge & PLEDGE_INET0x0000000000000040ULL)) {
7
Assuming the condition is false
8
Taking false branch
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)) {
9
Assuming the condition is false
10
Taking false branch
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)) {
11
Assuming the condition is false
12
Taking false branch
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)) {
13
Assuming the condition is false
14
Taking false branch
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)) {
15
Assuming the condition is false
16
Taking false branch
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)) {
17
Assuming the condition is false
18
Taking false branch
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)) {
19
Assuming the condition is false
20
Taking false branch
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)) {
21
Assuming the condition is false
22
Taking false branch
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)) {
23
Assuming the condition is true
24
Taking true branch
1242 switch (com) {
25
Control jumps to 'case 2147775590:' at line 1254
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)
26
Assuming the condition is false
27
Taking false branch
1256 break;
1257 if ((pledge & PLEDGE_WPATH0x0000000000000002ULL) == 0)
28
Assuming the condition is false
29
Taking false branch
1258 break;
1259 if (cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8)
& 0xff)
].d_open != ptcopen)
30
Dereference of null pointer
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
1346int
1347pledge_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
1496int
1497pledge_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
1530int
1531pledge_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
1541int
1542pledge_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 */
1550uint64_t
1551pledgereq_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
1568int
1569pledge_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
1578int
1579pledge_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
1590int
1591pledge_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
1603int
1604canonpath(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}