Bug Summary

File:sys/syscall_mi.h
Warning:line 123, column 2
4th function call argument is an uninitialized value

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 trap.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/arch/amd64/amd64/trap.c

/usr/src/sys/arch/amd64/amd64/trap.c

1/* $OpenBSD: trap.c,v 1.102 2023/12/12 15:30:55 deraadt Exp $ */
2/* $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $ */
3
4/*-
5 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Charles M. Hannum.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*-
34 * Copyright (c) 1990 The Regents of the University of California.
35 * All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * the University of Utah, and William Jolitz.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)trap.c 7.4 (Berkeley) 5/13/91
65 */
66
67/*
68 * amd64 Trap and System call handling
69 */
70#undef TRAP_SIGDEBUG
71
72#include <sys/param.h>
73#include <sys/systm.h>
74#include <sys/proc.h>
75#include <sys/signalvar.h>
76#include <sys/user.h>
77#include <sys/signal.h>
78#include <sys/syscall.h>
79#include <sys/syscall_mi.h>
80#include <sys/stdarg.h>
81
82#include <uvm/uvm_extern.h>
83
84#include <machine/cpu.h>
85#include <machine/cpufunc.h>
86#include <machine/fpu.h>
87#include <machine/psl.h>
88#include <machine/trap.h>
89#ifdef DDB1
90#include <ddb/db_output.h>
91#include <machine/db_machdep.h>
92#endif
93
94#include "isa.h"
95
96int upageflttrap(struct trapframe *, uint64_t);
97int kpageflttrap(struct trapframe *, uint64_t);
98void kerntrap(struct trapframe *);
99void usertrap(struct trapframe *);
100void ast(struct trapframe *);
101void syscall(struct trapframe *);
102
103const char * const trap_type[] = {
104 "privileged instruction fault", /* 0 T_PRIVINFLT */
105 "breakpoint trap", /* 1 T_BPTFLT */
106 "arithmetic trap", /* 2 T_ARITHTRAP */
107 "reserved trap", /* 3 T_RESERVED */
108 "protection fault", /* 4 T_PROTFLT */
109 "trace trap", /* 5 T_TRCTRAP */
110 "page fault", /* 6 T_PAGEFLT */
111 "alignment fault", /* 7 T_ALIGNFLT */
112 "integer divide fault", /* 8 T_DIVIDE */
113 "non-maskable interrupt", /* 9 T_NMI */
114 "overflow trap", /* 10 T_OFLOW */
115 "bounds check fault", /* 11 T_BOUND */
116 "FPU not available fault", /* 12 T_DNA */
117 "double fault", /* 13 T_DOUBLEFLT */
118 "FPU operand fetch fault", /* 14 T_FPOPFLT */
119 "invalid TSS fault", /* 15 T_TSSFLT */
120 "segment not present fault", /* 16 T_SEGNPFLT */
121 "stack fault", /* 17 T_STKFLT */
122 "machine check", /* 18 T_MCA */
123 "SSE FP exception", /* 19 T_XMM */
124 "virtualization exception", /* 20 T_VE */
125 "control protection exception", /* 21 T_CP */
126};
127const int trap_types = nitems(trap_type)(sizeof((trap_type)) / sizeof((trap_type)[0]));
128
129#ifdef DEBUG
130int trapdebug = 0;
131#endif
132
133static void trap_print(struct trapframe *, int _type);
134static inline void frame_dump(struct trapframe *_tf, struct proc *_p,
135 const char *_sig, uint64_t _cr2);
136static inline void verify_smap(const char *_func);
137static inline int verify_pkru(struct proc *);
138static inline void debug_trap(struct trapframe *_frame, struct proc *_p,
139 long _type);
140
141static inline void
142fault(const char *fmt, ...)
143{
144 struct cpu_info *ci = curcpu()({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})
;
145 va_list ap;
146
147 atomic_cas_ptr(&panicstr, NULL, ci->ci_panicbuf)_atomic_cas_ptr((&panicstr), (((void *)0)), (ci->ci_panicbuf
))
;
148
149 va_start(ap, fmt)__builtin_va_start((ap), fmt);
150 vsnprintf(ci->ci_panicbuf, sizeof(ci->ci_panicbuf), fmt, ap);
151 va_end(ap)__builtin_va_end((ap));
152#ifdef DDB1
153 db_printf("%s\n", ci->ci_panicbuf);
154#else
155 printf("%s\n", ci->ci_panicbuf);
156#endif
157}
158
159static inline int
160pgex2access(int pgex)
161{
162 if (pgex & PGEX_W0x02)
163 return PROT_WRITE0x02;
164 else if (pgex & PGEX_I0x10)
165 return PROT_EXEC0x04;
166 return PROT_READ0x01;
167}
168
169/*
170 * upageflttrap(frame, usermode): page fault handler
171 * Returns non-zero if the fault was handled (possibly by generating
172 * a signal). Returns zero, possibly still holding the kernel lock,
173 * if something was so broken that we should panic.
174 */
175int
176upageflttrap(struct trapframe *frame, uint64_t cr2)
177{
178 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
179 vaddr_t va = trunc_page((vaddr_t)cr2)(((vaddr_t)cr2) & ~((1 << 12) - 1));
180 vm_prot_t access_type = pgex2access(frame->tf_err);
181 union sigval sv;
182 int signal, sicode, error;
183
184 /*
185 * If NX is not enabled, we cant distinguish between PROT_READ
186 * and PROT_EXEC access, so try both.
187 */
188 error = uvm_fault(&p->p_vmspace->vm_map, va, 0, access_type);
189 if (pg_nx == 0 && error == EACCES13 && access_type == PROT_READ0x01)
190 error = uvm_fault(&p->p_vmspace->vm_map, va, 0, PROT_EXEC0x04);
191 if (error == 0) {
192 uvm_grow(p, va);
193 return 1;
194 }
195
196 signal = SIGSEGV11;
197 sicode = SEGV_MAPERR1;
198 if (error == ENOMEM12) {
199 printf("UVM: pid %d (%s), uid %d killed:"
200 " out of swap\n", p->p_p->ps_pid, p->p_p->ps_comm,
201 p->p_ucred ? (int)p->p_ucred->cr_uid : -1);
202 signal = SIGKILL9;
203 } else {
204 if (error == EACCES13)
205 sicode = SEGV_ACCERR2;
206 else if (error == EIO5) {
207 signal = SIGBUS10;
208 sicode = BUS_OBJERR3;
209 }
210 }
211 sv.sival_ptr = (void *)cr2;
212 trapsignal(p, signal, T_PAGEFLT6, sicode, sv);
213 return 1;
214}
215
216
217/*
218 * kpageflttrap(frame, usermode): page fault handler
219 * Returns non-zero if the fault was handled (possibly by generating a signal).
220 * Returns zero if something was so broken that we should panic.
221 */
222int
223kpageflttrap(struct trapframe *frame, uint64_t cr2)
224{
225 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
226 struct pcb *pcb;
227 vaddr_t va = trunc_page((vaddr_t)cr2)(((vaddr_t)cr2) & ~((1 << 12) - 1));
228 struct vm_map *map;
229 vm_prot_t access_type = pgex2access(frame->tf_err);
230 caddr_t onfault;
231 int error;
232
233 if (p == NULL((void *)0) || p->p_addr == NULL((void *)0) || p->p_vmspace == NULL((void *)0))
234 return 0;
235
236 pcb = &p->p_addr->u_pcb;
237 if (pcb->pcb_onfault != NULL((void *)0)) {
238 extern caddr_t __nofault_start[], __nofault_end[];
239 caddr_t *nf = __nofault_start;
240 while (*nf++ != pcb->pcb_onfault) {
241 if (nf >= __nofault_end) {
242 fault("invalid pcb_nofault=%lx",
243 (long)pcb->pcb_onfault);
244 return 0;
245 }
246 }
247 }
248
249 /* This will only trigger if SMEP is enabled */
250 if (pcb->pcb_onfault == NULL((void *)0) && cr2 <= VM_MAXUSER_ADDRESS0x00007f7fffffc000 &&
251 frame->tf_err & PGEX_I0x10) {
252 fault("attempt to execute user address %p "
253 "in supervisor mode", (void *)cr2);
254 return 0;
255 }
256 /* This will only trigger if SMAP is enabled */
257 if (pcb->pcb_onfault == NULL((void *)0) && cr2 <= VM_MAXUSER_ADDRESS0x00007f7fffffc000 &&
258 frame->tf_err & PGEX_P0x01) {
259 fault("attempt to access user address %p "
260 "in supervisor mode", (void *)cr2);
261 return 0;
262 }
263
264 /*
265 * It is only a kernel address space fault iff:
266 * 1. when running in ring 0 and
267 * 2. pcb_onfault not set or
268 * 3. pcb_onfault set but supervisor space fault
269 * The last can occur during an exec() copyin where the
270 * argument space is lazy-allocated.
271 */
272 map = &p->p_vmspace->vm_map;
273 if (va >= VM_MIN_KERNEL_ADDRESS0xffff800000000000)
274 map = kernel_map;
275
276 if (curcpu()({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})
->ci_inatomic == 0 || map == kernel_map) {
277 onfault = pcb->pcb_onfault;
278 pcb->pcb_onfault = NULL((void *)0);
279 error = uvm_fault(map, va, 0, access_type);
280 pcb->pcb_onfault = onfault;
281
282 if (error == 0 && map != kernel_map)
283 uvm_grow(p, va);
284 } else
285 error = EFAULT14;
286
287 if (error) {
288 if (pcb->pcb_onfault == NULL((void *)0)) {
289 /* bad memory access in the kernel */
290 fault("uvm_fault(%p, 0x%llx, 0, %d) -> %x",
291 map, cr2, access_type, error);
292 return 0;
293 }
294 frame->tf_rip = (u_int64_t)pcb->pcb_onfault;
295 }
296
297 return 1;
298}
299
300
301/*
302 * kerntrap(frame):
303 * Exception, fault, and trap interface to BSD kernel. This
304 * common code is called from assembly language IDT gate entry
305 * routines that prepare a suitable stack frame, and restore this
306 * frame after the exception has been processed.
307 */
308void
309kerntrap(struct trapframe *frame)
310{
311 int type = (int)frame->tf_trapno;
312 uint64_t cr2 = rcr2();
313
314 verify_smap(__func__);
315 uvmexp.traps++;
316 debug_trap(frame, curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
, type);
317
318 switch (type) {
319
320 default:
321 we_re_toast:
322#ifdef DDB1
323 if (db_ktrap(type, frame->tf_err, frame))
324 return;
325#endif
326 trap_print(frame, type);
327 panic("trap type %d, code=%llx, pc=%llx",
328 type, frame->tf_err, frame->tf_rip);
329 /*NOTREACHED*/
330
331 case T_PAGEFLT6: /* allow page faults in kernel mode */
332 if (kpageflttrap(frame, cr2))
333 return;
334 goto we_re_toast;
335
336#if NISA1 > 0
337 case T_NMI9:
338#ifdef DDB1
339 /* NMI can be hooked up to a pushbutton for debugging */
340 printf ("NMI ... going to debugger\n");
341 if (db_ktrap(type, 0, frame))
342 return;
343#endif
344 /* machine/parity/power fail/"kitchen sink" faults */
345
346 if (x86_nmi() != 0)
347 goto we_re_toast;
348 else
349 return;
350#endif /* NISA > 0 */
351 }
352}
353
354/* If we find out userland changed the pkru register, punish the process */
355static inline int
356verify_pkru(struct proc *p)
357{
358 if (pg_xo == 0 || rdpkru(0) == PGK_VALUE0xfffffffc)
359 return 0;
360 KERNEL_LOCK()_kernel_lock();
361 sigabort(p);
362 KERNEL_UNLOCK()_kernel_unlock();
363 return 1;
364}
365
366/*
367 * usertrap(frame): handler for exceptions, faults, and traps from userspace
368 * This is called from the assembly language IDT gate entries
369 * which prepare a suitable stack frame and restores the CPU state
370 * after the fault has been processed.
371 */
372void
373usertrap(struct trapframe *frame)
374{
375 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
376 int type = (int)frame->tf_trapno;
377 uint64_t cr2 = rcr2();
378 union sigval sv;
379 int sig, code;
380
381 verify_smap(__func__);
382 uvmexp.traps++;
383 debug_trap(frame, p, type);
384
385 p->p_md.md_regs = frame;
386 refreshcreds(p);
387
388 if (verify_pkru(p))
389 goto out;
390
391 switch (type) {
392 case T_TSSFLT15:
393 sig = SIGBUS10;
394 code = BUS_OBJERR3;
395 break;
396 case T_PROTFLT4: /* protection fault */
397 case T_SEGNPFLT16:
398 case T_STKFLT17:
399 frame_dump(frame, p, "SEGV", 0);
400 sig = SIGSEGV11;
401 code = SEGV_MAPERR1;
402 break;
403 case T_ALIGNFLT7:
404 sig = SIGBUS10;
405 code = BUS_ADRALN1;
406 break;
407 case T_PRIVINFLT0: /* privileged instruction fault */
408 sig = SIGILL4;
409 code = ILL_PRVOPC5;
410 break;
411 case T_DIVIDE8:
412 sig = SIGFPE8;
413 code = FPE_INTDIV1;
414 break;
415 case T_ARITHTRAP2:
416 case T_XMM19: /* real arithmetic exceptions */
417 sig = SIGFPE8;
418 code = fputrap(type);
419 break;
420 case T_BPTFLT1: /* bpt instruction fault */
421 case T_TRCTRAP5: /* trace trap */
422 sig = SIGTRAP5;
423 code = TRAP_BRKPT1;
424 break;
425 case T_CP21:
426 sig = SIGILL4;
427 code = (frame->tf_err & 0x7fff) < 4 ? ILL_ILLOPC1
428 : ILL_BADSTK8;
429 break;
430
431 case T_PAGEFLT6: /* page fault */
432 if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p)((p)->p_md.md_regs->tf_rsp),
433 "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n",
434 uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial))
435 goto out;
436 if (upageflttrap(frame, cr2))
437 goto out;
438 /* FALLTHROUGH */
439
440 default:
441 trap_print(frame, type);
442 panic("impossible trap");
443 }
444
445 sv.sival_ptr = (void *)frame->tf_rip;
446 trapsignal(p, sig, type, code, sv);
447
448out:
449 userret(p);
450}
451
452
453static void
454trap_print(struct trapframe *frame, int type)
455{
456 if (type < trap_types)
457 printf("fatal %s", trap_type[type]);
458 else
459 printf("unknown trap %d", type);
460 printf(" in %s mode\n", KERNELMODE(frame->tf_cs, frame->tf_rflags)(((frame->tf_cs) & 3) == 0) ?
461 "supervisor" : "user");
462 printf("trap type %d code %llx rip %llx cs %llx rflags %llx cr2 "
463 "%llx cpl %x rsp %llx\n",
464 type, frame->tf_err, frame->tf_rip, frame->tf_cs,
465 frame->tf_rflags, rcr2(), curcpu()({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})
->ci_ilevel, frame->tf_rsp);
466 printf("gsbase %p kgsbase %p\n",
467 (void *)rdmsr(MSR_GSBASE0xc0000101), (void *)rdmsr(MSR_KERNELGSBASE0xc0000102));
468}
469
470
471static inline void
472frame_dump(struct trapframe *tf, struct proc *p, const char *sig, uint64_t cr2)
473{
474#ifdef TRAP_SIGDEBUG
475 printf("pid %d (%s): %s at rip %llx addr %llx\n",
476 p->p_p->ps_pid, p->p_p->ps_comm, sig, tf->tf_rip, cr2);
477 printf("rip %p cs 0x%x rfl %p rsp %p ss 0x%x\n",
478 (void *)tf->tf_rip, (unsigned)tf->tf_cs & 0xffff,
479 (void *)tf->tf_rflags,
480 (void *)tf->tf_rsp, (unsigned)tf->tf_ss & 0xffff);
481 printf("err 0x%llx trapno 0x%llx\n",
482 tf->tf_err, tf->tf_trapno);
483 printf("rdi %p rsi %p rdx %p\n",
484 (void *)tf->tf_rdi, (void *)tf->tf_rsi, (void *)tf->tf_rdx);
485 printf("rcx %p r8 %p r9 %p\n",
486 (void *)tf->tf_rcx, (void *)tf->tf_r8, (void *)tf->tf_r9);
487 printf("r10 %p r11 %p r12 %p\n",
488 (void *)tf->tf_r10, (void *)tf->tf_r11, (void *)tf->tf_r12);
489 printf("r13 %p r14 %p r15 %p\n",
490 (void *)tf->tf_r13, (void *)tf->tf_r14, (void *)tf->tf_r15);
491 printf("rbp %p rbx %p rax %p\n",
492 (void *)tf->tf_rbp, (void *)tf->tf_rbx, (void *)tf->tf_rax);
493#endif
494}
495
496static inline void
497verify_smap(const char *func)
498{
499#ifdef DIAGNOSTIC1
500 if (curcpu()({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})
->ci_feature_sefflags_ebx & SEFF0EBX_SMAP0x00100000) {
501 u_long rf = read_rflags();
502 if (rf & PSL_AC0x00040000) {
503 write_rflags(rf & ~PSL_AC0x00040000);
504 panic("%s: AC set on entry", func);
505 }
506 }
507#endif
508}
509
510static inline void
511debug_trap(struct trapframe *frame, struct proc *p, long type)
512{
513#ifdef DEBUG
514 if (trapdebug) {
515 printf("trap %ld code %llx rip %llx cs %llx rflags %llx "
516 "cr2 %llx cpl %x\n",
517 type, frame->tf_err, frame->tf_rip, frame->tf_cs,
518 frame->tf_rflags, rcr2(), curcpu()({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})
->ci_ilevel);
519 printf("curproc %p\n", (void *)p);
520 if (p != NULL((void *)0))
521 printf("pid %d\n", p->p_p->ps_pid);
522 }
523#endif
524}
525
526/*
527 * ast(frame):
528 * AST handler. This is called from assembly language stubs when
529 * returning to userspace after a syscall or interrupt.
530 */
531void
532ast(struct trapframe *frame)
533{
534 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
535
536 uvmexp.traps++;
537 KASSERT(!KERNELMODE(frame->tf_cs, frame->tf_rflags))((!(((frame->tf_cs) & 3) == 0)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/arch/amd64/amd64/trap.c", 537, "!KERNELMODE(frame->tf_cs, frame->tf_rflags)"
))
;
538 p->p_md.md_regs = frame;
539 refreshcreds(p);
540 uvmexp.softs++;
541 mi_ast(p, curcpu()({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})
->ci_want_resched);
542 userret(p);
543}
544
545
546/*
547 * syscall(frame):
548 * System call request from POSIX system call gate interface to kernel.
549 */
550void
551syscall(struct trapframe *frame)
552{
553 caddr_t params;
554 const struct sysent *callp;
555 struct proc *p;
556 int error = ENOSYS78;
557 size_t argsize, argoff;
558 register_t code, args[9], rval[2], *argp;
559
560 verify_smap(__func__);
561 uvmexp.syscalls++;
562 p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
563
564 if (verify_pkru(p)) {
1
Taking false branch
565 userret(p);
566 return;
567 }
568
569 code = frame->tf_rax;
570 argp = &args[0];
571 argoff = 0;
572
573 if (code <= 0 || code >= SYS_MAXSYSCALL331)
2
Assuming 'code' is <= 0
574 goto bad;
3
Control jumps to line 622
575 callp = sysent + code;
576 argsize = (callp->sy_argsize >> 3) + argoff;
577 if (argsize) {
578 switch (MIN(argsize, 6)(((argsize)<(6))?(argsize):(6))) {
579 case 6:
580 args[5] = frame->tf_r9;
581 case 5:
582 args[4] = frame->tf_r8;
583 case 4:
584 args[3] = frame->tf_r10;
585 case 3:
586 args[2] = frame->tf_rdx;
587 case 2:
588 args[1] = frame->tf_rsi;
589 case 1:
590 args[0] = frame->tf_rdi;
591 break;
592 default:
593 panic("impossible syscall argsize");
594 }
595 if (argsize > 6) {
596 argsize -= 6;
597 params = (caddr_t)frame->tf_rsp + sizeof(register_t);
598 if ((error = copyin(params, &args[6], argsize << 3)))
599 goto bad;
600 }
601 }
602
603 rval[0] = 0;
604 rval[1] = 0;
605
606 error = mi_syscall(p, code, callp, argp, rval);
607
608 switch (error) {
609 case 0:
610 frame->tf_rax = rval[0];
611 frame->tf_rflags &= ~PSL_C0x00000001; /* carry bit */
612 break;
613 case ERESTART-1:
614 /* Back up over the syscall instruction (2 bytes) */
615 frame->tf_rip -= 2;
616 break;
617 case EJUSTRETURN-2:
618 /* nothing to do */
619 break;
620 default:
621 bad:
622 frame->tf_rax = error;
623 frame->tf_rflags |= PSL_C0x00000001; /* carry bit */
624 break;
625 }
626
627 mi_syscall_return(p, code, error, rval);
4
Calling 'mi_syscall_return'
628}
629
630void
631child_return(void *arg)
632{
633 struct proc *p = arg;
634 struct trapframe *tf = p->p_md.md_regs;
635
636 tf->tf_rax = 0;
637 tf->tf_rflags &= ~PSL_C0x00000001;
638
639 KERNEL_UNLOCK()_kernel_unlock();
640
641 mi_child_return(p);
642}
643

/usr/src/sys/sys/syscall_mi.h

1/* $OpenBSD: syscall_mi.h,v 1.29 2023/12/12 15:30:55 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)kern_xxx.c 8.2 (Berkeley) 11/14/93
32 */
33
34#include <sys/param.h>
35#include <sys/pledge.h>
36#include <sys/tracepoint.h>
37#include <sys/syscall.h>
38#include <uvm/uvm_extern.h>
39
40#ifdef KTRACE1
41#include <sys/ktrace.h>
42#endif
43
44#include "dt.h"
45#if NDT1 > 0
46#include <dev/dt/dtvar.h>
47#endif
48
49
50/*
51 * The MD setup for a system call has been done; here's the MI part.
52 */
53static inline int
54mi_syscall(struct proc *p, register_t code, const struct sysent *callp,
55 register_t *argp, register_t retval[2])
56{
57 uint64_t tval;
58 int lock = !(callp->sy_flags & SY_NOLOCK0x01);
59 int error, pledged;
60
61 /* refresh the thread's cache of the process's creds */
62 refreshcreds(p);
63
64#ifdef SYSCALL_DEBUG
65 KERNEL_LOCK()_kernel_lock();
66 scdebug_call(p, code, argp);
67 KERNEL_UNLOCK()_kernel_unlock();
68#endif
69 TRACEPOINT(raw_syscalls, sys_enter, code, NULL)do { extern struct dt_probe (dt_static_raw_syscalls_sys_enter
); struct dt_probe *dtp = &(dt_static_raw_syscalls_sys_enter
); if (__builtin_expect(((dt_tracing) != 0), 0) && __builtin_expect
(((dtp->dtp_recording) != 0), 0)) { struct dt_provider *dtpv
= dtp->dtp_prov; dtpv->dtpv_enter(dtpv, dtp, code, ((void
*)0)); } } while (0)
;
70#if NDT1 > 0
71 DT_ENTER(syscall, code, callp->sy_argsize, argp)do { extern struct dt_provider dt_prov_syscall ; struct dt_provider
*dtpv = &dt_prov_syscall ; if (__builtin_expect(((dt_tracing
) != 0), 0) && __builtin_expect(((dtpv->dtpv_recording
) != 0), 0)) { dtpv->dtpv_enter(dtpv, code, callp->sy_argsize
, argp); } } while (0)
;
72#endif
73#ifdef KTRACE1
74 if (KTRPOINT(p, KTR_SYSCALL)((p)->p_p->ps_traceflag & (1<<(1)) &&
((p)->p_flag & 0x00000001) == 0)
) {
75 /* convert to mask, then include with code */
76 KERNEL_LOCK()_kernel_lock();
77 ktrsyscall(p, code, callp->sy_argsize, argp);
78 KERNEL_UNLOCK()_kernel_unlock();
79 }
80#endif
81
82 /* SP must be within MAP_STACK space */
83 if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p)((p)->p_md.md_regs->tf_rsp),
84 "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n",
85 uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial))
86 return (EPERM1);
87
88 /* PC must be in un-writeable permitted text (sigtramp, libc, ld.so) */
89 if (!uvm_map_inentry(p, &p->p_pcinentry, PROC_PC(p)((p)->p_md.md_regs->tf_rip),
90 "[%s]%d/%d pc=%lx inside %lx-%lx: bogus syscall\n",
91 uvm_map_inentry_pc, p->p_vmspace->vm_map.wserial))
92 return (EPERM1);
93
94 pledged = (p->p_p->ps_flags & PS_PLEDGE0x00100000);
95 if (pledged && (error = pledge_syscall(p, code, &tval))) {
96 KERNEL_LOCK()_kernel_lock();
97 error = pledge_fail(p, error, tval);
98 KERNEL_UNLOCK()_kernel_unlock();
99 return (error);
100 }
101 if (lock)
102 KERNEL_LOCK()_kernel_lock();
103 error = (*callp->sy_call)(p, argp, retval);
104 if (lock)
105 KERNEL_UNLOCK()_kernel_unlock();
106
107 return (error);
108}
109
110/*
111 * Finish MI stuff on return, after the registers have been set
112 */
113static inline void
114mi_syscall_return(struct proc *p, register_t code, int error,
115 const register_t retval[2])
116{
117#ifdef SYSCALL_DEBUG
118 KERNEL_LOCK()_kernel_lock();
119 scdebug_ret(p, code, error, retval);
120 KERNEL_UNLOCK()_kernel_unlock();
121#endif
122#if NDT1 > 0
123 DT_LEAVE(syscall, code, error, retval[0], retval[1])do { extern struct dt_provider dt_prov_syscall ; struct dt_provider
*dtpv = &dt_prov_syscall ; if (__builtin_expect(((dt_tracing
) != 0), 0) && __builtin_expect(((dtpv->dtpv_recording
) != 0), 0)) { dtpv->dtpv_leave(dtpv, code, error, retval[
0], retval[1]); } } while (0)
;
5
Assuming 'dt_tracing' is not equal to 0
6
Assuming field 'dtpv_recording' is not equal to 0
7
Taking true branch
8
4th function call argument is an uninitialized value
124#endif
125 TRACEPOINT(raw_syscalls, sys_exit, code, NULL)do { extern struct dt_probe (dt_static_raw_syscalls_sys_exit)
; struct dt_probe *dtp = &(dt_static_raw_syscalls_sys_exit
); if (__builtin_expect(((dt_tracing) != 0), 0) && __builtin_expect
(((dtp->dtp_recording) != 0), 0)) { struct dt_provider *dtpv
= dtp->dtp_prov; dtpv->dtpv_enter(dtpv, dtp, code, ((void
*)0)); } } while (0)
;
126
127 userret(p);
128
129#ifdef KTRACE1
130 if (KTRPOINT(p, KTR_SYSRET)((p)->p_p->ps_traceflag & (1<<(2)) &&
((p)->p_flag & 0x00000001) == 0)
) {
131 KERNEL_LOCK()_kernel_lock();
132 ktrsysret(p, code, error, retval);
133 KERNEL_UNLOCK()_kernel_unlock();
134 }
135#endif
136}
137
138/*
139 * Finish MI stuff for a new process/thread to return
140 */
141static inline void
142mi_child_return(struct proc *p)
143{
144#if defined(SYSCALL_DEBUG) || defined(KTRACE1) || NDT1 > 0
145 int code = (p->p_flag & P_THREAD0x04000000) ? SYS___tfork8 :
146 (p->p_p->ps_flags & PS_PPWAIT0x00000040) ? SYS_vfork66 : SYS_fork2;
147 const register_t child_retval[2] = { 0, 1 };
148#endif
149
150 TRACEPOINT(sched, on__cpu, NULL)do { extern struct dt_probe (dt_static_sched_on__cpu); struct
dt_probe *dtp = &(dt_static_sched_on__cpu); if (__builtin_expect
(((dt_tracing) != 0), 0) && __builtin_expect(((dtp->
dtp_recording) != 0), 0)) { struct dt_provider *dtpv = dtp->
dtp_prov; dtpv->dtpv_enter(dtpv, dtp, ((void *)0)); } } while
(0)
;
151
152#ifdef SYSCALL_DEBUG
153 KERNEL_LOCK()_kernel_lock();
154 scdebug_ret(p, code, 0, child_retval);
155 KERNEL_UNLOCK()_kernel_unlock();
156#endif
157#if NDT1 > 0
158 DT_LEAVE(syscall, code, 0, child_retval[0], child_retval[1])do { extern struct dt_provider dt_prov_syscall ; struct dt_provider
*dtpv = &dt_prov_syscall ; if (__builtin_expect(((dt_tracing
) != 0), 0) && __builtin_expect(((dtpv->dtpv_recording
) != 0), 0)) { dtpv->dtpv_leave(dtpv, code, 0, child_retval
[0], child_retval[1]); } } while (0)
;
159#endif
160 TRACEPOINT(raw_syscalls, sys_exit, code, NULL)do { extern struct dt_probe (dt_static_raw_syscalls_sys_exit)
; struct dt_probe *dtp = &(dt_static_raw_syscalls_sys_exit
); if (__builtin_expect(((dt_tracing) != 0), 0) && __builtin_expect
(((dtp->dtp_recording) != 0), 0)) { struct dt_provider *dtpv
= dtp->dtp_prov; dtpv->dtpv_enter(dtpv, dtp, code, ((void
*)0)); } } while (0)
;
161
162 userret(p);
163
164#ifdef KTRACE1
165 if (KTRPOINT(p, KTR_SYSRET)((p)->p_p->ps_traceflag & (1<<(2)) &&
((p)->p_flag & 0x00000001) == 0)
) {
166 KERNEL_LOCK()_kernel_lock();
167 ktrsysret(p, code, 0, child_retval);
168 KERNEL_UNLOCK()_kernel_unlock();
169 }
170#endif
171}
172
173/*
174 * Do the specific processing necessary for an AST
175 */
176static inline void
177mi_ast(struct proc *p, int resched)
178{
179 if (p->p_flag & P_OWEUPC0x00008000) {
180 KERNEL_LOCK()_kernel_lock();
181 ADDUPROF(p)do { x86_atomic_clearbits_u32(&(p)->p_flag, 0x00008000
); addupc_task((p), (p)->p_prof_addr, (p)->p_prof_ticks
); (p)->p_prof_ticks = 0; } while (0)
;
182 KERNEL_UNLOCK()_kernel_unlock();
183 }
184 if (resched)
185 preempt();
186
187 /*
188 * XXX could move call to userret() here, but
189 * hppa calls ast() in syscall return and sh calls
190 * it after userret()
191 */
192}