Bug Summary

File:sys/syscall_mi.h
Warning:line 122, 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.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name trap.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/arch/amd64/amd64/trap.c

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

1/* $OpenBSD: trap.c,v 1.90 2021/12/09 00:26:11 guenther 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};
125const int trap_types = nitems(trap_type)(sizeof((trap_type)) / sizeof((trap_type)[0]));
126
127#ifdef DEBUG
128int trapdebug = 0;
129#endif
130
131static void trap_print(struct trapframe *, int _type);
132static inline void frame_dump(struct trapframe *_tf, struct proc *_p,
133 const char *_sig, uint64_t _cr2);
134static inline void verify_smap(const char *_func);
135static inline void debug_trap(struct trapframe *_frame, struct proc *_p,
136 long _type);
137
138static inline void
139fault(const char *fmt, ...)
140{
141 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;})
;
142 va_list ap;
143
144 atomic_cas_ptr(&panicstr, NULL, ci->ci_panicbuf)_atomic_cas_ptr((&panicstr), (((void *)0)), (ci->ci_panicbuf
))
;
145
146 va_start(ap, fmt)__builtin_va_start((ap), fmt);
147 vsnprintf(ci->ci_panicbuf, sizeof(ci->ci_panicbuf), fmt, ap);
148 va_end(ap)__builtin_va_end((ap));
149#ifdef DDB1
150 db_printf("%s\n", ci->ci_panicbuf);
151#else
152 printf("%s\n", ci->ci_panicbuf);
153#endif
154}
155
156static inline int
157pgex2access(int pgex)
158{
159 if (pgex & PGEX_W0x02)
160 return PROT_WRITE0x02;
161 else if (pgex & PGEX_I0x10)
162 return PROT_EXEC0x04;
163 return PROT_READ0x01;
164}
165
166/*
167 * upageflttrap(frame, usermode): page fault handler
168 * Returns non-zero if the fault was handled (possibly by generating
169 * a signal). Returns zero, possibly still holding the kernel lock,
170 * if something was so broken that we should panic.
171 */
172int
173upageflttrap(struct trapframe *frame, uint64_t cr2)
174{
175 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
;
176 vaddr_t va = trunc_page((vaddr_t)cr2)(((vaddr_t)cr2) & ~((1 << 12) - 1));
177 vm_prot_t access_type = pgex2access(frame->tf_err);
178 union sigval sv;
179 int signal, sicode, error;
180
181 error = uvm_fault(&p->p_vmspace->vm_map, va, 0, access_type);
182 if (error == 0) {
183 uvm_grow(p, va);
184 return 1;
185 }
186
187 signal = SIGSEGV11;
188 sicode = SEGV_MAPERR1;
189 if (error == ENOMEM12) {
190 printf("UVM: pid %d (%s), uid %d killed:"
191 " out of swap\n", p->p_p->ps_pid, p->p_p->ps_comm,
192 p->p_ucred ? (int)p->p_ucred->cr_uid : -1);
193 signal = SIGKILL9;
194 } else {
195 if (error == EACCES13)
196 sicode = SEGV_ACCERR2;
197 else if (error == EIO5) {
198 signal = SIGBUS10;
199 sicode = BUS_OBJERR3;
200 }
201 }
202 sv.sival_ptr = (void *)cr2;
203 trapsignal(p, signal, T_PAGEFLT6, sicode, sv);
204 return 1;
205}
206
207
208/*
209 * kpageflttrap(frame, usermode): page fault handler
210 * Returns non-zero if the fault was handled (possibly by generating
211 * a signal). Returns zero, possibly still holding the kernel lock,
212 * if something was so broken that we should panic.
213 */
214int
215kpageflttrap(struct trapframe *frame, uint64_t cr2)
216{
217 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
;
218 struct pcb *pcb;
219 vaddr_t va = trunc_page((vaddr_t)cr2)(((vaddr_t)cr2) & ~((1 << 12) - 1));
220 struct vm_map *map;
221 vm_prot_t access_type = pgex2access(frame->tf_err);
222 caddr_t onfault;
223 int error;
224
225 if (p == NULL((void *)0) || p->p_addr == NULL((void *)0) || p->p_vmspace == NULL((void *)0))
226 return 0;
227
228 pcb = &p->p_addr->u_pcb;
229
230 /* This will only trigger if SMEP is enabled */
231 if (cr2 <= VM_MAXUSER_ADDRESS0x00007f7fffffc000 && frame->tf_err & PGEX_I0x10) {
232 KERNEL_LOCK()_kernel_lock();
233 fault("attempt to execute user address %p "
234 "in supervisor mode", (void *)cr2);
235 /* retain kernel lock */
236 return 0;
237 }
238 /* This will only trigger if SMAP is enabled */
239 if (pcb->pcb_onfault == NULL((void *)0) && cr2 <= VM_MAXUSER_ADDRESS0x00007f7fffffc000 &&
240 frame->tf_err & PGEX_P0x01) {
241 KERNEL_LOCK()_kernel_lock();
242 fault("attempt to access user address %p "
243 "in supervisor mode", (void *)cr2);
244 /* retain kernel lock */
245 return 0;
246 }
247
248 /*
249 * It is only a kernel address space fault iff:
250 * 1. when running in ring 0 and
251 * 2. pcb_onfault not set or
252 * 3. pcb_onfault set but supervisor space fault
253 * The last can occur during an exec() copyin where the
254 * argument space is lazy-allocated.
255 */
256 map = &p->p_vmspace->vm_map;
257 if (va >= VM_MIN_KERNEL_ADDRESS0xffff800000000000)
258 map = kernel_map;
259
260 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) {
261 onfault = pcb->pcb_onfault;
262 pcb->pcb_onfault = NULL((void *)0);
263 error = uvm_fault(map, va, 0, access_type);
264 pcb->pcb_onfault = onfault;
265
266 if (error == 0 && map != kernel_map)
267 uvm_grow(p, va);
268 } else
269 error = EFAULT14;
270
271 if (error) {
272 if (pcb->pcb_onfault == NULL((void *)0)) {
273 /* bad memory access in the kernel */
274 KERNEL_LOCK()_kernel_lock();
275 fault("uvm_fault(%p, 0x%llx, 0, %d) -> %x",
276 map, cr2, access_type, error);
277 /* retain kernel lock */
278 return 0;
279 }
280 frame->tf_rip = (u_int64_t)pcb->pcb_onfault;
281 }
282
283 return 1;
284}
285
286
287/*
288 * kerntrap(frame):
289 * Exception, fault, and trap interface to BSD kernel. This
290 * common code is called from assembly language IDT gate entry
291 * routines that prepare a suitable stack frame, and restore this
292 * frame after the exception has been processed.
293 */
294void
295kerntrap(struct trapframe *frame)
296{
297 int type = (int)frame->tf_trapno;
298 uint64_t cr2 = rcr2();
299
300 verify_smap(__func__);
301 uvmexp.traps++;
302 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);
303
304 switch (type) {
305
306 default:
307 we_re_toast:
308#ifdef DDB1
309 if (db_ktrap(type, 0, frame))
310 return;
311#endif
312 trap_print(frame, type);
313 panic("trap type %d, code=%llx, pc=%llx",
314 type, frame->tf_err, frame->tf_rip);
315 /*NOTREACHED*/
316
317 case T_PAGEFLT6: /* allow page faults in kernel mode */
318 if (kpageflttrap(frame, cr2))
319 return;
320 goto we_re_toast;
321
322#if NISA1 > 0
323 case T_NMI9:
324#ifdef DDB1
325 /* NMI can be hooked up to a pushbutton for debugging */
326 printf ("NMI ... going to debugger\n");
327 if (db_ktrap(type, 0, frame))
328 return;
329#endif
330 /* machine/parity/power fail/"kitchen sink" faults */
331
332 if (x86_nmi() != 0)
333 goto we_re_toast;
334 else
335 return;
336#endif /* NISA > 0 */
337 }
338}
339
340
341/*
342 * usertrap(frame): handler for exceptions, faults, and traps from userspace
343 * This is called from the assembly language IDT gate entries
344 * which prepare a suitable stack frame and restores the CPU state
345 * after the fault has been processed.
346 */
347void
348usertrap(struct trapframe *frame)
349{
350 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
;
351 int type = (int)frame->tf_trapno;
352 uint64_t cr2 = rcr2();
353 union sigval sv;
354 int sig, code;
355
356 verify_smap(__func__);
357 uvmexp.traps++;
358 debug_trap(frame, p, type);
359
360 p->p_md.md_regs = frame;
361 refreshcreds(p);
362
363 switch (type) {
364 case T_TSSFLT15:
365 sig = SIGBUS10;
366 code = BUS_OBJERR3;
367 break;
368 case T_PROTFLT4: /* protection fault */
369 case T_SEGNPFLT16:
370 case T_STKFLT17:
371 frame_dump(frame, p, "SEGV", 0);
372 sig = SIGSEGV11;
373 code = SEGV_MAPERR1;
374 break;
375 case T_ALIGNFLT7:
376 sig = SIGBUS10;
377 code = BUS_ADRALN1;
378 break;
379 case T_PRIVINFLT0: /* privileged instruction fault */
380 sig = SIGILL4;
381 code = ILL_PRVOPC5;
382 break;
383 case T_DIVIDE8:
384 sig = SIGFPE8;
385 code = FPE_INTDIV1;
386 break;
387 case T_ARITHTRAP2:
388 case T_XMM19: /* real arithmetic exceptions */
389 sig = SIGFPE8;
390 code = fputrap(type);
391 break;
392 case T_BPTFLT1: /* bpt instruction fault */
393 case T_TRCTRAP5: /* trace trap */
394 sig = SIGTRAP5;
395 code = TRAP_BRKPT1;
396 break;
397
398 case T_PAGEFLT6: /* page fault */
399 if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p)((p)->p_md.md_regs->tf_rsp),
400 "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n",
401 uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial))
402 goto out;
403 if (upageflttrap(frame, cr2))
404 goto out;
405 /* FALLTHROUGH */
406
407 default:
408 trap_print(frame, type);
409 panic("impossible trap");
410 }
411
412 sv.sival_ptr = (void *)frame->tf_rip;
413 trapsignal(p, sig, type, code, sv);
414
415out:
416 userret(p);
417}
418
419
420static void
421trap_print(struct trapframe *frame, int type)
422{
423 if (type < trap_types)
424 printf("fatal %s", trap_type[type]);
425 else
426 printf("unknown trap %d", type);
427 printf(" in %s mode\n", KERNELMODE(frame->tf_cs, frame->tf_rflags)(((frame->tf_cs) & 3) == 0) ?
428 "supervisor" : "user");
429 printf("trap type %d code %llx rip %llx cs %llx rflags %llx cr2 "
430 "%llx cpl %x rsp %llx\n",
431 type, frame->tf_err, frame->tf_rip, frame->tf_cs,
432 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);
433 printf("gsbase %p kgsbase %p\n",
434 (void *)rdmsr(MSR_GSBASE0xc0000101), (void *)rdmsr(MSR_KERNELGSBASE0xc0000102));
435}
436
437
438static inline void
439frame_dump(struct trapframe *tf, struct proc *p, const char *sig, uint64_t cr2)
440{
441#ifdef TRAP_SIGDEBUG
442 printf("pid %d (%s): %s at rip %llx addr %llx\n",
443 p->p_p->ps_pid, p->p_p->ps_comm, sig, tf->tf_rip, cr2);
444 printf("rip %p cs 0x%x rfl %p rsp %p ss 0x%x\n",
445 (void *)tf->tf_rip, (unsigned)tf->tf_cs & 0xffff,
446 (void *)tf->tf_rflags,
447 (void *)tf->tf_rsp, (unsigned)tf->tf_ss & 0xffff);
448 printf("err 0x%llx trapno 0x%llx\n",
449 tf->tf_err, tf->tf_trapno);
450 printf("rdi %p rsi %p rdx %p\n",
451 (void *)tf->tf_rdi, (void *)tf->tf_rsi, (void *)tf->tf_rdx);
452 printf("rcx %p r8 %p r9 %p\n",
453 (void *)tf->tf_rcx, (void *)tf->tf_r8, (void *)tf->tf_r9);
454 printf("r10 %p r11 %p r12 %p\n",
455 (void *)tf->tf_r10, (void *)tf->tf_r11, (void *)tf->tf_r12);
456 printf("r13 %p r14 %p r15 %p\n",
457 (void *)tf->tf_r13, (void *)tf->tf_r14, (void *)tf->tf_r15);
458 printf("rbp %p rbx %p rax %p\n",
459 (void *)tf->tf_rbp, (void *)tf->tf_rbx, (void *)tf->tf_rax);
460#endif
461}
462
463static inline void
464verify_smap(const char *func)
465{
466#ifdef DIAGNOSTIC1
467 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) {
468 u_long rf = read_rflags();
469 if (rf & PSL_AC0x00040000) {
470 write_rflags(rf & ~PSL_AC0x00040000);
471 panic("%s: AC set on entry", func);
472 }
473 }
474#endif
475}
476
477static inline void
478debug_trap(struct trapframe *frame, struct proc *p, long type)
479{
480#ifdef DEBUG
481 if (trapdebug) {
482 printf("trap %ld code %llx rip %llx cs %llx rflags %llx "
483 "cr2 %llx cpl %x\n",
484 type, frame->tf_err, frame->tf_rip, frame->tf_cs,
485 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);
486 printf("curproc %p\n", (void *)p);
487 if (p != NULL((void *)0))
488 printf("pid %d\n", p->p_p->ps_pid);
489 }
490#endif
491}
492
493/*
494 * ast(frame):
495 * AST handler. This is called from assembly language stubs when
496 * returning to userspace after a syscall or interrupt.
497 */
498void
499ast(struct trapframe *frame)
500{
501 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
;
502
503 uvmexp.traps++;
504 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", 504, "!KERNELMODE(frame->tf_cs, frame->tf_rflags)"
))
;
505 p->p_md.md_regs = frame;
506 refreshcreds(p);
507 uvmexp.softs++;
508 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);
509 userret(p);
510}
511
512
513/*
514 * syscall(frame):
515 * System call request from POSIX system call gate interface to kernel.
516 */
517void
518syscall(struct trapframe *frame)
519{
520 caddr_t params;
521 const struct sysent *callp;
522 struct proc *p;
523 int error;
524 size_t argsize, argoff;
525 register_t code, args[9], rval[2], *argp;
526
527 verify_smap(__func__);
528 uvmexp.syscalls++;
529 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
;
530
531 code = frame->tf_rax;
532 argp = &args[0];
533 argoff = 0;
534
535 switch (code) {
1
Control jumps to the 'default' case at line 545
536 case SYS_syscall0:
537 case SYS___syscall198:
538 /*
539 * Code is first argument, followed by actual args.
540 */
541 code = frame->tf_rdi;
542 argp = &args[1];
543 argoff = 1;
544 break;
545 default:
546 break;
2
Execution continues on line 549
547 }
548
549 callp = sysent;
550 if (code < 0 || code >= SYS_MAXSYSCALL331)
3
Assuming 'code' is >= 0
4
Assuming 'code' is < SYS_MAXSYSCALL
5
Taking false branch
551 callp += SYS_syscall0;
552 else
553 callp += code;
554
555 argsize = (callp->sy_argsize >> 3) + argoff;
556 if (argsize) {
6
Assuming 'argsize' is not equal to 0
7
Taking true branch
557 switch (MIN(argsize, 6)(((argsize)<(6))?(argsize):(6))) {
8
Assuming 'argsize' is >= 6
9
'?' condition is false
10
Control jumps to 'case 6:' at line 558
558 case 6:
559 args[5] = frame->tf_r9;
560 case 5:
561 args[4] = frame->tf_r8;
562 case 4:
563 args[3] = frame->tf_r10;
564 case 3:
565 args[2] = frame->tf_rdx;
566 case 2:
567 args[1] = frame->tf_rsi;
568 case 1:
569 args[0] = frame->tf_rdi;
570 break;
11
Execution continues on line 574
571 default:
572 panic("impossible syscall argsize");
573 }
574 if (argsize > 6) {
12
Assuming 'argsize' is > 6
13
Taking true branch
575 argsize -= 6;
576 params = (caddr_t)frame->tf_rsp + sizeof(register_t);
577 if ((error = copyin(params, &args[6], argsize << 3)))
14
Assuming 'error' is not equal to 0
15
Taking true branch
578 goto bad;
16
Control jumps to line 602
579 }
580 }
581
582 rval[0] = 0;
583 rval[1] = frame->tf_rdx;
584
585 error = mi_syscall(p, code, callp, argp, rval);
586
587 switch (error) {
588 case 0:
589 frame->tf_rax = rval[0];
590 frame->tf_rdx = rval[1];
591 frame->tf_rflags &= ~PSL_C0x00000001; /* carry bit */
592 break;
593 case ERESTART-1:
594 /* Back up over the syscall instruction (2 bytes) */
595 frame->tf_rip -= 2;
596 break;
597 case EJUSTRETURN-2:
598 /* nothing to do */
599 break;
600 default:
601 bad:
602 frame->tf_rax = error;
603 frame->tf_rflags |= PSL_C0x00000001; /* carry bit */
604 break;
17
Execution continues on line 607
605 }
606
607 mi_syscall_return(p, code, error, rval);
18
Calling 'mi_syscall_return'
608}
609
610void
611child_return(void *arg)
612{
613 struct proc *p = arg;
614 struct trapframe *tf = p->p_md.md_regs;
615
616 tf->tf_rax = 0;
617 tf->tf_rdx = 1;
618 tf->tf_rflags &= ~PSL_C0x00000001;
619
620 KERNEL_UNLOCK()_kernel_unlock();
621
622 mi_child_return(p);
623}
624

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

1/* $OpenBSD: syscall_mi.h,v 1.25 2020/01/21 16:16:23 mpi 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 <uvm/uvm_extern.h>
38
39#ifdef KTRACE1
40#include <sys/ktrace.h>
41#endif
42
43#include "dt.h"
44#if NDT1 > 0
45#include <dev/dt/dtvar.h>
46#endif
47
48
49/*
50 * The MD setup for a system call has been done; here's the MI part.
51 */
52static inline int
53mi_syscall(struct proc *p, register_t code, const struct sysent *callp,
54 register_t *argp, register_t retval[2])
55{
56 uint64_t tval;
57 int lock = !(callp->sy_flags & SY_NOLOCK0x01);
58 int error, pledged;
59
60 /* refresh the thread's cache of the process's creds */
61 refreshcreds(p);
62
63#ifdef SYSCALL_DEBUG
64 KERNEL_LOCK()_kernel_lock();
65 scdebug_call(p, code, argp);
66 KERNEL_UNLOCK()_kernel_unlock();
67#endif
68 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
); struct dt_provider *dtpv = dtp->dtp_prov; if (__builtin_expect
(((dt_tracing) != 0), 0) && __builtin_expect(((dtp->
dtp_recording) != 0), 0)) { dtpv->dtpv_enter(dtpv, dtp, code
, ((void *)0)); } } while (0)
;
69#if NDT1 > 0
70 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)
;
71#endif
72#ifdef KTRACE1
73 if (KTRPOINT(p, KTR_SYSCALL)((p)->p_p->ps_traceflag & (1<<(1)) &&
((p)->p_flag & 0x00000001) == 0)
) {
74 KERNEL_LOCK()_kernel_lock();
75 ktrsyscall(p, code, callp->sy_argsize, argp);
76 KERNEL_UNLOCK()_kernel_unlock();
77 }
78#endif
79
80 /* SP must be within MAP_STACK space */
81 if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p)((p)->p_md.md_regs->tf_rsp),
82 "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n",
83 uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial))
84 return (EPERM1);
85
86 /* PC must be in un-writeable permitted text (sigtramp, libc, ld.so) */
87 if (!uvm_map_inentry(p, &p->p_pcinentry, PROC_PC(p)((p)->p_md.md_regs->tf_rip),
88 "[%s]%d/%d pc=%lx inside %lx-%lx: bogus syscall\n",
89 uvm_map_inentry_pc, p->p_vmspace->vm_map.wserial))
90 return (EPERM1);
91
92 if (lock)
93 KERNEL_LOCK()_kernel_lock();
94 pledged = (p->p_p->ps_flags & PS_PLEDGE0x00100000);
95 if (pledged && (error = pledge_syscall(p, code, &tval))) {
96 if (!lock)
97 KERNEL_LOCK()_kernel_lock();
98 error = pledge_fail(p, error, tval);
99 KERNEL_UNLOCK()_kernel_unlock();
100 return (error);
101 }
102 error = (*callp->sy_call)(p, argp, retval);
103 if (lock)
104 KERNEL_UNLOCK()_kernel_unlock();
105
106 return (error);
107}
108
109/*
110 * Finish MI stuff on return, after the registers have been set
111 */
112static inline void
113mi_syscall_return(struct proc *p, register_t code, int error,
114 const register_t retval[2])
115{
116#ifdef SYSCALL_DEBUG
117 KERNEL_LOCK()_kernel_lock();
118 scdebug_ret(p, code, error, retval);
119 KERNEL_UNLOCK()_kernel_unlock();
120#endif
121#if NDT1 > 0
122 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)
;
19
Assuming 'dt_tracing' is not equal to 0
20
Assuming field 'dtpv_recording' is not equal to 0
21
Taking true branch
22
4th function call argument is an uninitialized value
123#endif
124 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
); struct dt_provider *dtpv = dtp->dtp_prov; if (__builtin_expect
(((dt_tracing) != 0), 0) && __builtin_expect(((dtp->
dtp_recording) != 0), 0)) { dtpv->dtpv_enter(dtpv, dtp, code
, ((void *)0)); } } while (0)
;
125
126 userret(p);
127
128#ifdef KTRACE1
129 if (KTRPOINT(p, KTR_SYSRET)((p)->p_p->ps_traceflag & (1<<(2)) &&
((p)->p_flag & 0x00000001) == 0)
) {
130 KERNEL_LOCK()_kernel_lock();
131 ktrsysret(p, code, error, retval);
132 KERNEL_UNLOCK()_kernel_unlock();
133 }
134#endif
135}
136
137/*
138 * Finish MI stuff for a new process/thread to return
139 */
140static inline void
141mi_child_return(struct proc *p)
142{
143#if defined(SYSCALL_DEBUG) || defined(KTRACE1) || NDT1 > 0
144 int code = (p->p_flag & P_THREAD0x04000000) ? SYS___tfork8 :
145 (p->p_p->ps_flags & PS_PPWAIT0x00000040) ? SYS_vfork66 : SYS_fork2;
146 const register_t child_retval[2] = { 0, 1 };
147#endif
148
149 TRACEPOINT(sched, on__cpu, NULL)do { extern struct dt_probe (dt_static_sched_on__cpu); struct
dt_probe *dtp = &(dt_static_sched_on__cpu); struct dt_provider
*dtpv = dtp->dtp_prov; if (__builtin_expect(((dt_tracing)
!= 0), 0) && __builtin_expect(((dtp->dtp_recording
) != 0), 0)) { dtpv->dtpv_enter(dtpv, dtp, ((void *)0)); }
} while (0)
;
150
151#ifdef SYSCALL_DEBUG
152 KERNEL_LOCK()_kernel_lock();
153 scdebug_ret(p, code, 0, child_retval);
154 KERNEL_UNLOCK()_kernel_unlock();
155#endif
156#if NDT1 > 0
157 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)
;
158#endif
159 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
); struct dt_provider *dtpv = dtp->dtp_prov; if (__builtin_expect
(((dt_tracing) != 0), 0) && __builtin_expect(((dtp->
dtp_recording) != 0), 0)) { dtpv->dtpv_enter(dtpv, dtp, code
, ((void *)0)); } } while (0)
;
160
161 userret(p);
162
163#ifdef KTRACE1
164 if (KTRPOINT(p, KTR_SYSRET)((p)->p_p->ps_traceflag & (1<<(2)) &&
((p)->p_flag & 0x00000001) == 0)
) {
165 KERNEL_LOCK()_kernel_lock();
166 ktrsysret(p, code, 0, child_retval);
167 KERNEL_UNLOCK()_kernel_unlock();
168 }
169#endif
170}
171
172/*
173 * Do the specific processing necessary for an AST
174 */
175static inline void
176mi_ast(struct proc *p, int resched)
177{
178 if (p->p_flag & P_OWEUPC0x00008000) {
179 KERNEL_LOCK()_kernel_lock();
180 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)
;
181 KERNEL_UNLOCK()_kernel_unlock();
182 }
183 if (resched)
184 preempt();
185
186 /*
187 * XXX could move call to userret() here, but
188 * hppa calls ast() in syscall return and sh calls
189 * it after userret()
190 */
191}