1114987Speter/*- 2114987Speter * Copyright (C) 1994, David Greenman 3114987Speter * Copyright (c) 1990, 1993 4114987Speter * The Regents of the University of California. All rights reserved. 5114987Speter * 6114987Speter * This code is derived from software contributed to Berkeley by 7114987Speter * the University of Utah, and William Jolitz. 8114987Speter * 9114987Speter * Redistribution and use in source and binary forms, with or without 10114987Speter * modification, are permitted provided that the following conditions 11114987Speter * are met: 12114987Speter * 1. Redistributions of source code must retain the above copyright 13114987Speter * notice, this list of conditions and the following disclaimer. 14114987Speter * 2. Redistributions in binary form must reproduce the above copyright 15114987Speter * notice, this list of conditions and the following disclaimer in the 16114987Speter * documentation and/or other materials provided with the distribution. 17114987Speter * 3. All advertising materials mentioning features or use of this software 18114987Speter * must display the following acknowledgement: 19114987Speter * This product includes software developed by the University of 20114987Speter * California, Berkeley and its contributors. 21114987Speter * 4. Neither the name of the University nor the names of its contributors 22114987Speter * may be used to endorse or promote products derived from this software 23114987Speter * without specific prior written permission. 24114987Speter * 25114987Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26114987Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27114987Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28114987Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29114987Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30114987Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31114987Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32114987Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33114987Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34114987Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35114987Speter * SUCH DAMAGE. 36114987Speter */ 37114987Speter 38118031Sobrien#include <sys/cdefs.h> 39118031Sobrien__FBSDID("$FreeBSD: stable/11/sys/amd64/ia32/ia32_syscall.c 332428 2018-04-12 13:40:02Z kib $"); 40118031Sobrien 41114987Speter/* 42114987Speter * 386 Trap and System call handling 43114987Speter */ 44114987Speter 45114987Speter#include "opt_clock.h" 46220238Skib#include "opt_compat.h" 47114987Speter#include "opt_cpu.h" 48114987Speter#include "opt_isa.h" 49114987Speter 50114987Speter#include <sys/param.h> 51114987Speter#include <sys/bus.h> 52114987Speter#include <sys/systm.h> 53114987Speter#include <sys/proc.h> 54114987Speter#include <sys/pioctl.h> 55114987Speter#include <sys/kernel.h> 56114987Speter#include <sys/ktr.h> 57114987Speter#include <sys/lock.h> 58114987Speter#include <sys/mutex.h> 59208453Skib#include <sys/proc.h> 60160764Sjhb#include <sys/ptrace.h> 61114987Speter#include <sys/resourcevar.h> 62114987Speter#include <sys/signalvar.h> 63114987Speter#include <sys/syscall.h> 64114987Speter#include <sys/sysctl.h> 65114987Speter#include <sys/sysent.h> 66114987Speter#include <sys/uio.h> 67114987Speter#include <sys/vmmeter.h> 68155313Swsalamon#include <security/audit/audit.h> 69114987Speter 70114987Speter#include <vm/vm.h> 71114987Speter#include <vm/vm_param.h> 72114987Speter#include <vm/pmap.h> 73114987Speter#include <vm/vm_kern.h> 74114987Speter#include <vm/vm_map.h> 75114987Speter#include <vm/vm_page.h> 76114987Speter#include <vm/vm_extern.h> 77114987Speter 78114987Speter#include <machine/cpu.h> 79122849Speter#include <machine/intr_machdep.h> 80114987Speter#include <machine/md_var.h> 81114987Speter 82220238Skib#include <compat/freebsd32/freebsd32_signal.h> 83208453Skib#include <compat/freebsd32/freebsd32_util.h> 84220238Skib#include <compat/ia32/ia32_signal.h> 85220238Skib#include <machine/psl.h> 86220238Skib#include <machine/segments.h> 87220238Skib#include <machine/specialreg.h> 88220238Skib#include <machine/sysarch.h> 89220238Skib#include <machine/frame.h> 90220238Skib#include <machine/md_var.h> 91220238Skib#include <machine/pcb.h> 92220238Skib#include <machine/cpufunc.h> 93208453Skib 94114987Speter#define IDTVEC(name) __CONCAT(X,name) 95114987Speter 96329462Skibextern inthand_t IDTVEC(int0x80_syscall), IDTVEC(int0x80_syscall_pti), 97329462Skib IDTVEC(rsvd), IDTVEC(rsvd_pti); 98114987Speter 99165303Skmacyvoid ia32_syscall(struct trapframe *frame); /* Called from asm code */ 100114987Speter 101208453Skibvoid 102208453Skibia32_set_syscall_retval(struct thread *td, int error) 103208453Skib{ 104202882Skib 105208453Skib cpu_set_syscall_retval(td, error); 106208453Skib} 107208453Skib 108208453Skibint 109321343Skibia32_fetch_syscall_args(struct thread *td) 110202882Skib{ 111202882Skib struct proc *p; 112202882Skib struct trapframe *frame; 113321343Skib struct syscall_args *sa; 114208453Skib caddr_t params; 115273784Skib u_int32_t args[8], tmp; 116202882Skib int error, i; 117331839Skib#ifdef COMPAT_43 118331839Skib u_int32_t eip; 119331839Skib int cs; 120331839Skib#endif 121114987Speter 122202882Skib p = td->td_proc; 123202882Skib frame = td->td_frame; 124321343Skib sa = &td->td_sa; 125114987Speter 126331839Skib#ifdef COMPAT_43 127331839Skib if (__predict_false(frame->tf_cs == 7 && frame->tf_rip == 2)) { 128331839Skib /* 129331839Skib * In lcall $7,$0 after int $0x80. Convert the user 130331839Skib * frame to what it would be for a direct int 0x80 instead 131331839Skib * of lcall $7,$0, by popping the lcall return address. 132331839Skib */ 133331839Skib error = fueword32((void *)frame->tf_rsp, &eip); 134331839Skib if (error == -1) 135331839Skib return (EFAULT); 136331839Skib cs = fuword16((void *)(frame->tf_rsp + sizeof(u_int32_t))); 137331839Skib if (cs == -1) 138331839Skib return (EFAULT); 139331839Skib 140331839Skib /* 141331839Skib * Unwind in-kernel frame after all stack frame pieces 142331839Skib * were successfully read. 143331839Skib */ 144331839Skib frame->tf_rip = eip; 145331839Skib frame->tf_cs = cs; 146331839Skib frame->tf_rsp += 2 * sizeof(u_int32_t); 147332428Skib frame->tf_err = 7; /* size of lcall $7,$0 */ 148331839Skib } 149331839Skib#endif 150331839Skib 151208453Skib params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t); 152202882Skib sa->code = frame->tf_rax; 153202882Skib 154208453Skib /* 155208453Skib * Need to check if this is a 32 bit or 64 bit syscall. 156208453Skib */ 157208453Skib if (sa->code == SYS_syscall) { 158114987Speter /* 159208453Skib * Code is first argument, followed by actual args. 160114987Speter */ 161273784Skib error = fueword32(params, &tmp); 162273784Skib if (error == -1) 163273784Skib return (EFAULT); 164273784Skib sa->code = tmp; 165208453Skib params += sizeof(int); 166208453Skib } else if (sa->code == SYS___syscall) { 167114987Speter /* 168208453Skib * Like syscall, but code is a quad, so as to maintain 169208453Skib * quad alignment for the rest of the arguments. 170208453Skib * We use a 32-bit fetch in case params is not 171208453Skib * aligned. 172114987Speter */ 173273784Skib error = fueword32(params, &tmp); 174273784Skib if (error == -1) 175273784Skib return (EFAULT); 176273784Skib sa->code = tmp; 177208453Skib params += sizeof(quad_t); 178114987Speter } 179114987Speter if (p->p_sysent->sv_mask) 180202882Skib sa->code &= p->p_sysent->sv_mask; 181202882Skib if (sa->code >= p->p_sysent->sv_size) 182202882Skib sa->callp = &p->p_sysent->sv_table[0]; 183114987Speter else 184202882Skib sa->callp = &p->p_sysent->sv_table[sa->code]; 185202882Skib sa->narg = sa->callp->sy_narg; 186114987Speter 187208453Skib if (params != NULL && sa->narg != 0) 188208453Skib error = copyin(params, (caddr_t)args, 189202882Skib (u_int)(sa->narg * sizeof(int))); 190114987Speter else 191114987Speter error = 0; 192114987Speter 193202882Skib for (i = 0; i < sa->narg; i++) 194208453Skib sa->args[i] = args[i]; 195114987Speter 196208453Skib if (error == 0) { 197208453Skib td->td_retval[0] = 0; 198208453Skib td->td_retval[1] = frame->tf_rdx; 199208453Skib } 200202882Skib 201202882Skib return (error); 202202882Skib} 203202882Skib 204225474Skib#include "../../kern/subr_syscall.c" 205225474Skib 206202882Skibvoid 207202882Skibia32_syscall(struct trapframe *frame) 208202882Skib{ 209202882Skib struct thread *td; 210202882Skib register_t orig_tf_rflags; 211202882Skib int error; 212202882Skib ksiginfo_t ksi; 213202882Skib 214208453Skib orig_tf_rflags = frame->tf_rflags; 215202882Skib td = curthread; 216202882Skib td->td_frame = frame; 217202882Skib 218321343Skib error = syscallenter(td); 219160770Sjhb 220114987Speter /* 221114987Speter * Traced syscall. 222114987Speter */ 223114987Speter if (orig_tf_rflags & PSL_T) { 224165303Skmacy frame->tf_rflags &= ~PSL_T; 225151316Sdavidxu ksiginfo_init_trap(&ksi); 226151316Sdavidxu ksi.ksi_signo = SIGTRAP; 227151316Sdavidxu ksi.ksi_code = TRAP_TRACE; 228165303Skmacy ksi.ksi_addr = (void *)frame->tf_rip; 229151316Sdavidxu trapsignal(td, &ksi); 230114987Speter } 231114987Speter 232321343Skib syscallret(td, error); 233114987Speter} 234114987Speter 235114987Speterstatic void 236114987Speteria32_syscall_enable(void *dummy) 237114987Speter{ 238114987Speter 239329462Skib setidt(IDT_SYSCALL, pti ? &IDTVEC(int0x80_syscall_pti) : 240329462Skib &IDTVEC(int0x80_syscall), SDT_SYSIGT, SEL_UPL, 0); 241114987Speter} 242114987Speter 243114987Speterstatic void 244114987Speteria32_syscall_disable(void *dummy) 245114987Speter{ 246114987Speter 247329462Skib setidt(IDT_SYSCALL, pti ? &IDTVEC(rsvd_pti) : &IDTVEC(rsvd), 248329462Skib SDT_SYSIGT, SEL_KPL, 0); 249114987Speter} 250114987Speter 251114987SpeterSYSINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_enable, NULL); 252114987SpeterSYSUNINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_disable, NULL); 253220238Skib 254220238Skib#ifdef COMPAT_43 255220238Skibint 256220238Skibsetup_lcall_gate(void) 257220238Skib{ 258220238Skib struct i386_ldt_args uap; 259276322Skib struct user_segment_descriptor desc; 260220238Skib uint32_t lcall_addr; 261220238Skib int error; 262220238Skib 263220238Skib bzero(&uap, sizeof(uap)); 264220238Skib uap.start = 0; 265276322Skib uap.num = 1; 266276322Skib lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp; 267276322Skib bzero(&desc, sizeof(desc)); 268276322Skib desc.sd_type = SDT_MEMERA; 269276322Skib desc.sd_dpl = SEL_UPL; 270276322Skib desc.sd_p = 1; 271276322Skib desc.sd_def32 = 1; 272276322Skib desc.sd_gran = 1; 273276322Skib desc.sd_lolimit = 0xffff; 274276322Skib desc.sd_hilimit = 0xf; 275276322Skib desc.sd_lobase = lcall_addr; 276276322Skib desc.sd_hibase = lcall_addr >> 24; 277276322Skib error = amd64_set_ldt(curthread, &uap, &desc); 278220238Skib if (error != 0) 279220238Skib return (error); 280220238Skib 281220238Skib return (0); 282220238Skib} 283220238Skib#endif 284