xref: /freebsd/sys/i386/linux/linux_sysvec.c (revision 303b270b0a55fd0dc287afb82267317ca7826a7b)
1d66a5066SPeter Wemm /*-
2e1743d02SSøren Schmidt  * Copyright (c) 1994-1996 S�ren Schmidt
3d66a5066SPeter Wemm  * All rights reserved.
4d66a5066SPeter Wemm  *
5d66a5066SPeter Wemm  * Redistribution and use in source and binary forms, with or without
6d66a5066SPeter Wemm  * modification, are permitted provided that the following conditions
7d66a5066SPeter Wemm  * are met:
8d66a5066SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
9d66a5066SPeter Wemm  *    notice, this list of conditions and the following disclaimer
10d66a5066SPeter Wemm  *    in this position and unchanged.
11d66a5066SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
12d66a5066SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
13d66a5066SPeter Wemm  *    documentation and/or other materials provided with the distribution.
14d66a5066SPeter Wemm  * 3. The name of the author may not be used to endorse or promote products
15d66a5066SPeter Wemm  *    derived from this software withough specific prior written permission
16d66a5066SPeter Wemm  *
17d66a5066SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18d66a5066SPeter Wemm  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19d66a5066SPeter Wemm  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20d66a5066SPeter Wemm  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21d66a5066SPeter Wemm  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22d66a5066SPeter Wemm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23d66a5066SPeter Wemm  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24d66a5066SPeter Wemm  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25d66a5066SPeter Wemm  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26d66a5066SPeter Wemm  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27d66a5066SPeter Wemm  *
28303b270bSEivind Eklund  *  $Id: linux_sysvec.c,v 1.23 1998/02/06 12:13:19 eivind Exp $
29d66a5066SPeter Wemm  */
30d66a5066SPeter Wemm 
31d66a5066SPeter Wemm /* XXX we use functions that might not exist. */
325591b823SEivind Eklund #include "opt_compat.h"
335591b823SEivind Eklund 
345591b823SEivind Eklund #ifndef COMPAT_43
355591b823SEivind Eklund #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
365591b823SEivind Eklund #endif
37d66a5066SPeter Wemm 
38d66a5066SPeter Wemm #include <sys/param.h>
395e26fb6fSJordan K. Hubbard #include <sys/buf.h>
40aad9af2bSBruce Evans #include <sys/proc.h>
41d66a5066SPeter Wemm #include <sys/systm.h>
42d66a5066SPeter Wemm #include <sys/sysent.h>
43d66a5066SPeter Wemm #include <sys/imgact.h>
44e1743d02SSøren Schmidt #include <sys/imgact_elf.h>
45d66a5066SPeter Wemm #include <sys/signalvar.h>
46e1743d02SSøren Schmidt #include <sys/malloc.h>
47d66a5066SPeter Wemm #include <vm/vm.h>
48d66a5066SPeter Wemm #include <vm/vm_param.h>
49d66a5066SPeter Wemm #include <vm/vm_prot.h>
50d66a5066SPeter Wemm #include <vm/vm_page.h>
51d66a5066SPeter Wemm #include <vm/vm_extern.h>
52d66a5066SPeter Wemm #include <sys/exec.h>
535cf588ebSPeter Wemm #include <sys/kernel.h>
54d66a5066SPeter Wemm #include <machine/cpu.h>
55d66a5066SPeter Wemm 
56d66a5066SPeter Wemm #include <i386/linux/linux.h>
57d66a5066SPeter Wemm #include <i386/linux/linux_proto.h>
58e1743d02SSøren Schmidt 
59303b270bSEivind Eklund static int	linux_fixup __P((int **stack_base,
60303b270bSEivind Eklund 				 struct image_params *iparams));
61303b270bSEivind Eklund static int	elf_linux_fixup __P((int **stack_base,
62303b270bSEivind Eklund 				     struct image_params *iparams));
63303b270bSEivind Eklund static void	linux_prepsyscall __P((struct trapframe *tf, int *args,
64303b270bSEivind Eklund 				       u_int *code, caddr_t *params));
65303b270bSEivind Eklund static void     linux_sendsig __P((sig_t catcher, int sig, int mask,
66303b270bSEivind Eklund 				   u_long code));
67d66a5066SPeter Wemm 
68d66a5066SPeter Wemm /*
69d66a5066SPeter Wemm  * Linux syscalls return negative errno's, we do positive and map them
70d66a5066SPeter Wemm  */
71d66a5066SPeter Wemm int bsd_to_linux_errno[ELAST] = {
72d66a5066SPeter Wemm   	-0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,  -8,  -9,
73d66a5066SPeter Wemm  	-10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
74d66a5066SPeter Wemm  	-20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
75d66a5066SPeter Wemm  	-30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
76d66a5066SPeter Wemm  	-90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
77d66a5066SPeter Wemm 	-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
78d66a5066SPeter Wemm 	-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
79d66a5066SPeter Wemm 	-116, -66,  -6,  -6,  -6,  -6,  -6, -37, -38,  -9,
80d66a5066SPeter Wemm   	-6,
81d66a5066SPeter Wemm };
82d66a5066SPeter Wemm 
83d66a5066SPeter Wemm int bsd_to_linux_signal[NSIG] = {
84d66a5066SPeter Wemm 	0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT,
85d66a5066SPeter Wemm 	LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0,
86d66a5066SPeter Wemm 	LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV,
87d66a5066SPeter Wemm 	0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM,
88d66a5066SPeter Wemm 	LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT,
89d66a5066SPeter Wemm 	LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO,
90d66a5066SPeter Wemm 	LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF,
91d66a5066SPeter Wemm 	LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2
92d66a5066SPeter Wemm };
93d66a5066SPeter Wemm 
94d66a5066SPeter Wemm int linux_to_bsd_signal[LINUX_NSIG] = {
95d66a5066SPeter Wemm 	0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
96d66a5066SPeter Wemm 	SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
97d66a5066SPeter Wemm 	SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO,
98d66a5066SPeter Wemm 	SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0
99d66a5066SPeter Wemm };
100d66a5066SPeter Wemm 
101303b270bSEivind Eklund static int
102303b270bSEivind Eklund linux_fixup(int **stack_base, struct image_params *imgp)
103d66a5066SPeter Wemm {
104d66a5066SPeter Wemm 	int *argv, *envp;
105d66a5066SPeter Wemm 
106d66a5066SPeter Wemm 	argv = *stack_base;
107d66a5066SPeter Wemm 	envp = *stack_base + (imgp->argc + 1);
108d66a5066SPeter Wemm 	(*stack_base)--;
109d66a5066SPeter Wemm 	**stack_base = (int)envp;
110d66a5066SPeter Wemm 	(*stack_base)--;
111d66a5066SPeter Wemm 	**stack_base = (int)argv;
112d66a5066SPeter Wemm 	(*stack_base)--;
113d66a5066SPeter Wemm 	**stack_base = (int)imgp->argc;
114e1743d02SSøren Schmidt 	return 0;
115d66a5066SPeter Wemm }
116d66a5066SPeter Wemm 
117303b270bSEivind Eklund static int
118303b270bSEivind Eklund elf_linux_fixup(int **stack_base, struct image_params *imgp)
119e1743d02SSøren Schmidt {
120e1743d02SSøren Schmidt 	Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
121e1743d02SSøren Schmidt 	int *pos;
122d66a5066SPeter Wemm 
123e1743d02SSøren Schmidt 	pos = *stack_base + (imgp->argc + imgp->envc + 2);
124e1743d02SSøren Schmidt 
125e1743d02SSøren Schmidt 	if (args->trace) {
126e1743d02SSøren Schmidt 		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
127e1743d02SSøren Schmidt 	}
128e1743d02SSøren Schmidt 	if (args->execfd != -1) {
129e1743d02SSøren Schmidt 		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
130e1743d02SSøren Schmidt 	}
131e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
132e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
133e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
134e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
135e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
136e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
137e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_BASE, args->base);
138e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid);
139e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid);
140e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid);
141e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid);
142e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_NULL, 0);
143e1743d02SSøren Schmidt 
144e1743d02SSøren Schmidt 	free(imgp->auxargs, M_TEMP);
145e1743d02SSøren Schmidt 	imgp->auxargs = NULL;
146e1743d02SSøren Schmidt 
147e1743d02SSøren Schmidt 	(*stack_base)--;
148e1743d02SSøren Schmidt 	**stack_base = (int)imgp->argc;
149e1743d02SSøren Schmidt 	return 0;
150e1743d02SSøren Schmidt }
151d66a5066SPeter Wemm 
152d66a5066SPeter Wemm extern int _ucodesel, _udatasel;
153d66a5066SPeter Wemm 
154d66a5066SPeter Wemm /*
155d66a5066SPeter Wemm  * Send an interrupt to process.
156d66a5066SPeter Wemm  *
157d66a5066SPeter Wemm  * Stack is set up to allow sigcode stored
158d66a5066SPeter Wemm  * in u. to call routine, followed by kcall
159d66a5066SPeter Wemm  * to sigreturn routine below.  After sigreturn
160d66a5066SPeter Wemm  * resets the signal mask, the stack, and the
161d66a5066SPeter Wemm  * frame pointer, it returns to the user
162d66a5066SPeter Wemm  * specified pc, psl.
163d66a5066SPeter Wemm  */
164d66a5066SPeter Wemm 
165303b270bSEivind Eklund static void
166b36546f6SPeter Wemm linux_sendsig(sig_t catcher, int sig, int mask, u_long code)
167d66a5066SPeter Wemm {
168d66a5066SPeter Wemm 	register struct proc *p = curproc;
169213fdd80SPeter Wemm 	register struct trapframe *regs;
170d66a5066SPeter Wemm 	struct linux_sigframe *fp, frame;
171d66a5066SPeter Wemm 	struct sigacts *psp = p->p_sigacts;
172d66a5066SPeter Wemm 	int oonstack;
173d66a5066SPeter Wemm 
174d66a5066SPeter Wemm 	regs = p->p_md.md_regs;
175d66a5066SPeter Wemm 	oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
176d66a5066SPeter Wemm 
177d66a5066SPeter Wemm #ifdef DEBUG
178b36546f6SPeter Wemm 	printf("Linux-emul(%d): linux_sendsig(%8x, %d, %d, %ld)\n",
179d66a5066SPeter Wemm 		p->p_pid, catcher, sig, mask, code);
180d66a5066SPeter Wemm #endif
181d66a5066SPeter Wemm 	/*
182d66a5066SPeter Wemm 	 * Allocate space for the signal handler context.
183d66a5066SPeter Wemm 	 */
184d66a5066SPeter Wemm 	if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
185d66a5066SPeter Wemm 	    (psp->ps_sigonstack & sigmask(sig))) {
186d66a5066SPeter Wemm 		fp = (struct linux_sigframe *)(psp->ps_sigstk.ss_sp +
187d66a5066SPeter Wemm 		    psp->ps_sigstk.ss_size - sizeof(struct linux_sigframe));
188d66a5066SPeter Wemm 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
189d66a5066SPeter Wemm 	} else {
190213fdd80SPeter Wemm 		fp = (struct linux_sigframe *)regs->tf_esp - 1;
191d66a5066SPeter Wemm 	}
192d66a5066SPeter Wemm 
193d66a5066SPeter Wemm 	/*
194d66a5066SPeter Wemm 	 * grow() will return FALSE if the fp will not fit inside the stack
195d66a5066SPeter Wemm 	 *	and the stack can not be grown. useracc will return FALSE
196d66a5066SPeter Wemm 	 *	if access is denied.
197d66a5066SPeter Wemm 	 */
198d66a5066SPeter Wemm 	if ((grow(p, (int)fp) == FALSE) ||
199d66a5066SPeter Wemm 	    (useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) {
200d66a5066SPeter Wemm 		/*
201d66a5066SPeter Wemm 		 * Process has trashed its stack; give it an illegal
202d66a5066SPeter Wemm 		 * instruction to halt it in its tracks.
203d66a5066SPeter Wemm 		 */
204d66a5066SPeter Wemm 		SIGACTION(p, SIGILL) = SIG_DFL;
205d66a5066SPeter Wemm 		sig = sigmask(SIGILL);
206d66a5066SPeter Wemm 		p->p_sigignore &= ~sig;
207d66a5066SPeter Wemm 		p->p_sigcatch &= ~sig;
208d66a5066SPeter Wemm 		p->p_sigmask &= ~sig;
209d66a5066SPeter Wemm 		psignal(p, SIGILL);
210d66a5066SPeter Wemm 		return;
211d66a5066SPeter Wemm 	}
212d66a5066SPeter Wemm 
213d66a5066SPeter Wemm 	/*
214d66a5066SPeter Wemm 	 * Build the argument list for the signal handler.
215d66a5066SPeter Wemm 	 */
216d66a5066SPeter Wemm 	if (p->p_sysent->sv_sigtbl) {
217d66a5066SPeter Wemm 		if (sig < p->p_sysent->sv_sigsize)
218d66a5066SPeter Wemm 			sig = p->p_sysent->sv_sigtbl[sig];
219d66a5066SPeter Wemm 		else
220d66a5066SPeter Wemm 			sig = p->p_sysent->sv_sigsize + 1;
221d66a5066SPeter Wemm 	}
222d66a5066SPeter Wemm 
223d66a5066SPeter Wemm 	frame.sf_handler = catcher;
224d66a5066SPeter Wemm 	frame.sf_sig = sig;
225d66a5066SPeter Wemm 
226d66a5066SPeter Wemm 	/*
227d66a5066SPeter Wemm 	 * Build the signal context to be used by sigreturn.
228d66a5066SPeter Wemm 	 */
229d66a5066SPeter Wemm 	frame.sf_sc.sc_mask   = mask;
230d66a5066SPeter Wemm 	__asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs));
231d66a5066SPeter Wemm 	__asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
232213fdd80SPeter Wemm 	frame.sf_sc.sc_es     = regs->tf_es;
233213fdd80SPeter Wemm 	frame.sf_sc.sc_ds     = regs->tf_ds;
234213fdd80SPeter Wemm 	frame.sf_sc.sc_edi    = regs->tf_edi;
235213fdd80SPeter Wemm 	frame.sf_sc.sc_esi    = regs->tf_esi;
236213fdd80SPeter Wemm 	frame.sf_sc.sc_ebp    = regs->tf_ebp;
237213fdd80SPeter Wemm 	frame.sf_sc.sc_ebx    = regs->tf_ebx;
238213fdd80SPeter Wemm 	frame.sf_sc.sc_edx    = regs->tf_edx;
239213fdd80SPeter Wemm 	frame.sf_sc.sc_ecx    = regs->tf_ecx;
240213fdd80SPeter Wemm 	frame.sf_sc.sc_eax    = regs->tf_eax;
241213fdd80SPeter Wemm 	frame.sf_sc.sc_eip    = regs->tf_eip;
242213fdd80SPeter Wemm 	frame.sf_sc.sc_cs     = regs->tf_cs;
243213fdd80SPeter Wemm 	frame.sf_sc.sc_eflags = regs->tf_eflags;
244213fdd80SPeter Wemm 	frame.sf_sc.sc_esp_at_signal = regs->tf_esp;
245213fdd80SPeter Wemm 	frame.sf_sc.sc_ss     = regs->tf_ss;
246213fdd80SPeter Wemm 	frame.sf_sc.sc_err    = regs->tf_err;
247d66a5066SPeter Wemm 	frame.sf_sc.sc_trapno = code;	/* XXX ???? */
248d66a5066SPeter Wemm 
249d66a5066SPeter Wemm 	if (copyout(&frame, fp, sizeof(frame)) != 0) {
250d66a5066SPeter Wemm 		/*
251d66a5066SPeter Wemm 		 * Process has trashed its stack; give it an illegal
252d66a5066SPeter Wemm 		 * instruction to halt it in its tracks.
253d66a5066SPeter Wemm 		 */
254d66a5066SPeter Wemm 		sigexit(p, SIGILL);
255d66a5066SPeter Wemm 		/* NOTREACHED */
256d66a5066SPeter Wemm 	}
257d66a5066SPeter Wemm 
258d66a5066SPeter Wemm 	/*
259d66a5066SPeter Wemm 	 * Build context to run handler in.
260d66a5066SPeter Wemm 	 */
261213fdd80SPeter Wemm 	regs->tf_esp = (int)fp;
262213fdd80SPeter Wemm 	regs->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode));
263213fdd80SPeter Wemm 	regs->tf_eflags &= ~PSL_VM;
264213fdd80SPeter Wemm 	regs->tf_cs = _ucodesel;
265213fdd80SPeter Wemm 	regs->tf_ds = _udatasel;
266213fdd80SPeter Wemm 	regs->tf_es = _udatasel;
267213fdd80SPeter Wemm 	regs->tf_ss = _udatasel;
268d66a5066SPeter Wemm }
269d66a5066SPeter Wemm 
270d66a5066SPeter Wemm /*
271d66a5066SPeter Wemm  * System call to cleanup state after a signal
272d66a5066SPeter Wemm  * has been taken.  Reset signal mask and
273d66a5066SPeter Wemm  * stack state from context left by sendsig (above).
274d66a5066SPeter Wemm  * Return to previous pc and psl as specified by
275d66a5066SPeter Wemm  * context left by sendsig. Check carefully to
276d66a5066SPeter Wemm  * make sure that the user has not modified the
277d66a5066SPeter Wemm  * psl to gain improper privileges or to cause
278d66a5066SPeter Wemm  * a machine fault.
279d66a5066SPeter Wemm  */
280d66a5066SPeter Wemm int
281cb226aaaSPoul-Henning Kamp linux_sigreturn(p, args)
282d66a5066SPeter Wemm 	struct proc *p;
283d66a5066SPeter Wemm 	struct linux_sigreturn_args *args;
284d66a5066SPeter Wemm {
285d66a5066SPeter Wemm 	struct linux_sigcontext *scp, context;
286213fdd80SPeter Wemm 	register struct trapframe *regs;
287d66a5066SPeter Wemm 	int eflags;
288d66a5066SPeter Wemm 
289d66a5066SPeter Wemm 	regs = p->p_md.md_regs;
290d66a5066SPeter Wemm 
291d66a5066SPeter Wemm #ifdef DEBUG
292d66a5066SPeter Wemm 	printf("Linux-emul(%d): linux_sigreturn(%8x)\n", p->p_pid, args->scp);
293d66a5066SPeter Wemm #endif
294d66a5066SPeter Wemm 	/*
295d66a5066SPeter Wemm 	 * The trampoline code hands us the context.
296d66a5066SPeter Wemm 	 * It is unsafe to keep track of it ourselves, in the event that a
297d66a5066SPeter Wemm 	 * program jumps out of a signal handler.
298d66a5066SPeter Wemm 	 */
299d66a5066SPeter Wemm 	scp = args->scp;
300d66a5066SPeter Wemm 	if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
301d66a5066SPeter Wemm 		return (EFAULT);
302d66a5066SPeter Wemm 
303d66a5066SPeter Wemm 	/*
304d66a5066SPeter Wemm 	 * Check for security violations.
305d66a5066SPeter Wemm 	 */
306d66a5066SPeter Wemm #define	EFLAGS_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
307d66a5066SPeter Wemm 	eflags = context.sc_eflags;
308d66a5066SPeter Wemm 	/*
309d66a5066SPeter Wemm 	 * XXX do allow users to change the privileged flag PSL_RF.  The
310d66a5066SPeter Wemm 	 * cpu sets PSL_RF in tf_eflags for faults.  Debuggers should
311d66a5066SPeter Wemm 	 * sometimes set it there too.  tf_eflags is kept in the signal
312d66a5066SPeter Wemm 	 * context during signal handling and there is no other place
313d66a5066SPeter Wemm 	 * to remember it, so the PSL_RF bit may be corrupted by the
314d66a5066SPeter Wemm 	 * signal handler without us knowing.  Corruption of the PSL_RF
315d66a5066SPeter Wemm 	 * bit at worst causes one more or one less debugger trap, so
316d66a5066SPeter Wemm 	 * allowing it is fairly harmless.
317d66a5066SPeter Wemm 	 */
318213fdd80SPeter Wemm 	if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
319d66a5066SPeter Wemm     		return(EINVAL);
320d66a5066SPeter Wemm 	}
321d66a5066SPeter Wemm 
322d66a5066SPeter Wemm 	/*
323d66a5066SPeter Wemm 	 * Don't allow users to load a valid privileged %cs.  Let the
324d66a5066SPeter Wemm 	 * hardware check for invalid selectors, excess privilege in
325d66a5066SPeter Wemm 	 * other selectors, invalid %eip's and invalid %esp's.
326d66a5066SPeter Wemm 	 */
32740d50994SPhilippe Charnier #define	CS_SECURE(cs)	(ISPL(cs) == SEL_UPL)
328d66a5066SPeter Wemm 	if (!CS_SECURE(context.sc_cs)) {
329d66a5066SPeter Wemm 		trapsignal(p, SIGBUS, T_PROTFLT);
330d66a5066SPeter Wemm 		return(EINVAL);
331d66a5066SPeter Wemm 	}
332d66a5066SPeter Wemm 
333d66a5066SPeter Wemm 	p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
334d66a5066SPeter Wemm 	p->p_sigmask = context.sc_mask &~
335d66a5066SPeter Wemm 		(sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
336d66a5066SPeter Wemm 	/*
337d66a5066SPeter Wemm 	 * Restore signal context.
338d66a5066SPeter Wemm 	 */
339d66a5066SPeter Wemm 	/* %fs and %gs were restored by the trampoline. */
340213fdd80SPeter Wemm 	regs->tf_es     = context.sc_es;
341213fdd80SPeter Wemm 	regs->tf_ds     = context.sc_ds;
342213fdd80SPeter Wemm 	regs->tf_edi    = context.sc_edi;
343213fdd80SPeter Wemm 	regs->tf_esi    = context.sc_esi;
344213fdd80SPeter Wemm 	regs->tf_ebp    = context.sc_ebp;
345213fdd80SPeter Wemm 	regs->tf_ebx    = context.sc_ebx;
346213fdd80SPeter Wemm 	regs->tf_edx    = context.sc_edx;
347213fdd80SPeter Wemm 	regs->tf_ecx    = context.sc_ecx;
348213fdd80SPeter Wemm 	regs->tf_eax    = context.sc_eax;
349213fdd80SPeter Wemm 	regs->tf_eip    = context.sc_eip;
350213fdd80SPeter Wemm 	regs->tf_cs     = context.sc_cs;
351213fdd80SPeter Wemm 	regs->tf_eflags = eflags;
352213fdd80SPeter Wemm 	regs->tf_esp    = context.sc_esp_at_signal;
353213fdd80SPeter Wemm 	regs->tf_ss     = context.sc_ss;
354d66a5066SPeter Wemm 
355d66a5066SPeter Wemm 	return (EJUSTRETURN);
356d66a5066SPeter Wemm }
357d66a5066SPeter Wemm 
358303b270bSEivind Eklund static void
359d66a5066SPeter Wemm linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
360d66a5066SPeter Wemm {
361d66a5066SPeter Wemm 	args[0] = tf->tf_ebx;
362d66a5066SPeter Wemm 	args[1] = tf->tf_ecx;
363d66a5066SPeter Wemm 	args[2] = tf->tf_edx;
364d66a5066SPeter Wemm 	args[3] = tf->tf_esi;
365d66a5066SPeter Wemm 	args[4] = tf->tf_edi;
366d66a5066SPeter Wemm 	*params = NULL;		/* no copyin */
367d66a5066SPeter Wemm }
368d66a5066SPeter Wemm 
369d66a5066SPeter Wemm struct sysentvec linux_sysvec = {
370e1743d02SSøren Schmidt 	LINUX_SYS_MAXSYSCALL,
371d66a5066SPeter Wemm 	linux_sysent,
372d66a5066SPeter Wemm 	0xff,
373d66a5066SPeter Wemm 	NSIG,
374d66a5066SPeter Wemm 	bsd_to_linux_signal,
375d66a5066SPeter Wemm 	ELAST,
376d66a5066SPeter Wemm 	bsd_to_linux_errno,
377d66a5066SPeter Wemm 	linux_fixup,
378d66a5066SPeter Wemm 	linux_sendsig,
379d66a5066SPeter Wemm 	linux_sigcode,
380d66a5066SPeter Wemm 	&linux_szsigcode,
381d66a5066SPeter Wemm 	linux_prepsyscall,
3826ead3eddSJohn Dyson 	"Linux a.out"
383d66a5066SPeter Wemm };
384e1743d02SSøren Schmidt 
385e1743d02SSøren Schmidt struct sysentvec elf_linux_sysvec = {
386e1743d02SSøren Schmidt         LINUX_SYS_MAXSYSCALL,
387e1743d02SSøren Schmidt         linux_sysent,
388e1743d02SSøren Schmidt         0xff,
389e1743d02SSøren Schmidt         NSIG,
390e1743d02SSøren Schmidt         bsd_to_linux_signal,
391e1743d02SSøren Schmidt         ELAST,
392e1743d02SSøren Schmidt         bsd_to_linux_errno,
393e1743d02SSøren Schmidt         elf_linux_fixup,
394e1743d02SSøren Schmidt         linux_sendsig,
395e1743d02SSøren Schmidt         linux_sigcode,
396e1743d02SSøren Schmidt         &linux_szsigcode,
397e1743d02SSøren Schmidt         linux_prepsyscall,
3986ead3eddSJohn Dyson 	"Linux ELF"
399e1743d02SSøren Schmidt };
400e1743d02SSøren Schmidt 
4015cf588ebSPeter Wemm /*
4025cf588ebSPeter Wemm  * Installed either via SYSINIT() or via LKM stubs.
4035cf588ebSPeter Wemm  */
404303b270bSEivind Eklund static Elf32_Brandinfo linux_brand = {
405ea5a2b2eSSøren Schmidt 					"Linux",
406ea5a2b2eSSøren Schmidt 					"/compat/linux",
4075cf588ebSPeter Wemm 					"/lib/ld-linux.so.1",
408ea5a2b2eSSøren Schmidt 					&elf_linux_sysvec
4095cf588ebSPeter Wemm 				 };
4105cf588ebSPeter Wemm 
4115cf588ebSPeter Wemm #ifndef LKM
4125cf588ebSPeter Wemm /*
4135cf588ebSPeter Wemm  * XXX: this is WRONG, it needs to be SI_SUB_EXEC, but this is just at the
4145cf588ebSPeter Wemm  * "proof of concept" stage and will be fixed shortly
4155cf588ebSPeter Wemm  */
41617bd614dSBruce Evans static void linux_elf_init __P((void *dummy));
41717bd614dSBruce Evans 
418d30ea4f5SPeter Wemm static void
419d30ea4f5SPeter Wemm linux_elf_init(dummy)
420d30ea4f5SPeter Wemm 	void *dummy;
421d30ea4f5SPeter Wemm {
422d30ea4f5SPeter Wemm 	if (elf_insert_brand_entry(&linux_brand) < 0)
423d30ea4f5SPeter Wemm 		printf("cannot insert Linux elf brand handler\n");
424d30ea4f5SPeter Wemm 	else if (bootverbose)
425d30ea4f5SPeter Wemm 		printf("Linux-ELF exec handler installed\n");
426d30ea4f5SPeter Wemm }
427d30ea4f5SPeter Wemm 
428d30ea4f5SPeter Wemm SYSINIT(linuxelf, SI_SUB_VFS, SI_ORDER_ANY, linux_elf_init, NULL);
4295cf588ebSPeter Wemm #endif
430