From 4e9f66f9ca6d1262520ee04519283c1e5eedec5a Mon Sep 17 00:00:00 2001 From: mycroft Date: Sun, 7 May 1995 02:59:30 +0000 Subject: [PATCH] Improve Linux signal emulation, and emulate the modify_ldt() call. --- sys/arch/i386/i386/genassym.c | 12 +- sys/arch/i386/i386/linux_machdep.c | 215 ++++++++++++++++----- sys/arch/i386/include/linux_machdep.h | 51 ++--- sys/compat/linux/arch/i386/linux_machdep.c | 215 ++++++++++++++++----- sys/compat/linux/arch/i386/linux_machdep.h | 51 ++--- sys/compat/linux/i386/linux_machdep.c | 215 ++++++++++++++++----- sys/compat/linux/i386/linux_machdep.h | 51 ++--- 7 files changed, 576 insertions(+), 234 deletions(-) diff --git a/sys/arch/i386/i386/genassym.c b/sys/arch/i386/i386/genassym.c index fad7f111371e..f380ab92233a 100644 --- a/sys/arch/i386/i386/genassym.c +++ b/sys/arch/i386/i386/genassym.c @@ -1,4 +1,4 @@ -/* $NetBSD: genassym.c,v 1.42 1995/05/01 14:19:14 mycroft Exp $ */ +/* $NetBSD: genassym.c,v 1.43 1995/05/07 02:59:30 mycroft Exp $ */ /*- * Copyright (c) 1995 Charles M. Hannum. All rights reserved. @@ -138,11 +138,11 @@ main() #endif #ifdef COMPAT_LINUX - def("LINUX_SIGF_HANDLER", &linux_sigf->ls_handler); - def("LINUX_SIGF_SC", &linux_sigf->ls_sc); - def("LINUX_SC_FS", &linux_sc->lsc_fs); - def("LINUX_SC_GS", &linux_sc->lsc_gs); - def("LINUX_SC_EFLAGS", &linux_sc->lsc_eflags); + def("LINUX_SIGF_HANDLER", &linux_sigf->sf_handler); + def("LINUX_SIGF_SC", &linux_sigf->sf_sc); + def("LINUX_SC_FS", &linux_sc->sc_fs); + def("LINUX_SC_GS", &linux_sc->sc_gs); + def("LINUX_SC_EFLAGS", &linux_sc->sc_eflags); #endif #if NISA > 0 diff --git a/sys/arch/i386/i386/linux_machdep.c b/sys/arch/i386/i386/linux_machdep.c index b252d2806908..4d9bf5800031 100644 --- a/sys/arch/i386/i386/linux_machdep.c +++ b/sys/arch/i386/i386/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.6 1995/05/06 18:17:15 mycroft Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.7 1995/05/07 02:59:32 mycroft Exp $ */ /* * Copyright (c) 1995 Frank van der Linden @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -52,14 +51,18 @@ #include #include #include + #include #include +#include #include #include #include #include +#include #include +#include #include /* @@ -107,42 +110,42 @@ linux_sendsig(catcher, sig, mask, code) fp = (struct linux_sigframe *)tf->tf_esp - 1; } - frame.ls_handler = catcher; - frame.ls_sig = bsd_to_linux_sig(sig); + frame.sf_handler = catcher; + frame.sf_sig = bsd_to_linux_sig(sig); /* * Build the signal context to be used by sigreturn. */ - frame.ls_sc.lsc_mask = mask; + frame.sf_sc.sc_mask = mask; #ifdef VM86 if (tf->tf_eflags & PSL_VM) { - frame.ls_sc.lsc_gs = tf->tf_vm86_gs; - frame.ls_sc.lsc_fs = tf->tf_vm86_fs; - frame.ls_sc.lsc_es = tf->tf_vm86_es; - frame.ls_sc.lsc_ds = tf->tf_vm86_ds; + frame.sf_sc.sc_gs = tf->tf_vm86_gs; + frame.sf_sc.sc_fs = tf->tf_vm86_fs; + frame.sf_sc.sc_es = tf->tf_vm86_es; + frame.sf_sc.sc_ds = tf->tf_vm86_ds; } else #else { - __asm("movl %%gs,%w0" : "=r" (frame.ls_sc.lsc_gs)); - __asm("movl %%fs,%w0" : "=r" (frame.ls_sc.lsc_fs)); - frame.ls_sc.lsc_es = tf->tf_es; - frame.ls_sc.lsc_ds = tf->tf_ds; + __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs)); + __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs)); + frame.sf_sc.sc_es = tf->tf_es; + frame.sf_sc.sc_ds = tf->tf_ds; } #endif - frame.ls_sc.lsc_edi = tf->tf_edi; - frame.ls_sc.lsc_esi = tf->tf_esi; - frame.ls_sc.lsc_ebp = tf->tf_ebp; - frame.ls_sc.lsc_ebx = tf->tf_ebx; - frame.ls_sc.lsc_edx = tf->tf_edx; - frame.ls_sc.lsc_ecx = tf->tf_ecx; - frame.ls_sc.lsc_eax = tf->tf_eax; - frame.ls_sc.lsc_eip = tf->tf_eip; - frame.ls_sc.lsc_cs = tf->tf_cs; - frame.ls_sc.lsc_eflags = tf->tf_eflags; - frame.ls_sc.lsc_esp = tf->tf_esp; - frame.ls_sc.lsc_ss = tf->tf_ss; - frame.ls_sc.lsc_err = tf->tf_err; - frame.ls_sc.lsc_trapno = tf->tf_trapno; + frame.sf_sc.sc_edi = tf->tf_edi; + frame.sf_sc.sc_esi = tf->tf_esi; + frame.sf_sc.sc_ebp = tf->tf_ebp; + frame.sf_sc.sc_ebx = tf->tf_ebx; + frame.sf_sc.sc_edx = tf->tf_edx; + frame.sf_sc.sc_ecx = tf->tf_ecx; + frame.sf_sc.sc_eax = tf->tf_eax; + frame.sf_sc.sc_eip = tf->tf_eip; + frame.sf_sc.sc_cs = tf->tf_cs; + frame.sf_sc.sc_eflags = tf->tf_eflags; + frame.sf_sc.sc_esp_at_signal = tf->tf_esp; + frame.sf_sc.sc_ss = tf->tf_ss; + frame.sf_sc.sc_err = tf->tf_err; + frame.sf_sc.sc_trapno = tf->tf_trapno; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* @@ -203,45 +206,151 @@ linux_sigreturn(p, uap, retval) /* * Check for security violations. */ - if (((context.lsc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || - ISPL(context.lsc_cs) != SEL_UPL) + if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || + ISPL(context.sc_cs) != SEL_UPL) return (EINVAL); p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; - p->p_sigmask = context.lsc_mask & ~sigcantmask; + p->p_sigmask = context.sc_mask & ~sigcantmask; /* * Restore signal context. */ #ifdef VM86 - if (context.lsc_eflags & PSL_VM) { - tf->tf_vm86_gs = context.lsc_gs; - tf->tf_vm86_fs = context.lsc_fs; - tf->tf_vm86_es = context.lsc_es; - tf->tf_vm86_ds = context.lsc_ds; + if (context.sc_eflags & PSL_VM) { + tf->tf_vm86_gs = context.sc_gs; + tf->tf_vm86_fs = context.sc_fs; + tf->tf_vm86_es = context.sc_es; + tf->tf_vm86_ds = context.sc_ds; } else #endif { /* %fs and %gs were restored by the trampoline. */ - tf->tf_es = context.lsc_es; - tf->tf_ds = context.lsc_ds; + tf->tf_es = context.sc_es; + tf->tf_ds = context.sc_ds; } - tf->tf_edi = context.lsc_edi; - tf->tf_esi = context.lsc_esi; - tf->tf_ebp = context.lsc_ebp; - tf->tf_ebx = context.lsc_ebx; - tf->tf_edx = context.lsc_edx; - tf->tf_ecx = context.lsc_ecx; - tf->tf_eax = context.lsc_eax; - tf->tf_eip = context.lsc_eip; - tf->tf_cs = context.lsc_cs; - tf->tf_eflags = context.lsc_eflags; - tf->tf_esp = context.lsc_esp; - tf->tf_ss = context.lsc_ss; + tf->tf_edi = context.sc_edi; + tf->tf_esi = context.sc_esi; + tf->tf_ebp = context.sc_ebp; + tf->tf_ebx = context.sc_ebx; + tf->tf_edx = context.sc_edx; + tf->tf_ecx = context.sc_ecx; + tf->tf_eax = context.sc_eax; + tf->tf_eip = context.sc_eip; + tf->tf_cs = context.sc_cs; + tf->tf_eflags = context.sc_eflags; + tf->tf_esp = context.sc_esp_at_signal; + tf->tf_ss = context.sc_ss; return (EJUSTRETURN); } +#ifdef USER_LDT + +int +linux_read_ldt(p, uap, retval) + struct proc *p; + struct linux_modify_ldt_args /* { + syscallarg(int) func; + syscallarg(void *) ptr; + syscallarg(size_t) bytecount; + } */ *uap; + register_t *retval; +{ + struct i386_get_ldt_args gl; + int error; + caddr_t sg; + char *parms; + + sg = stackgap_init(); + + gl.start = 0; + gl.desc = SCARG(uap, ptr); + gl.num = SCARG(uap, bytecount) / sizeof(union descriptor); + + parms = stackgap_alloc(&sg, sizeof(gl)); + + if (error = copyout(&gl, parms, sizeof(gl))) + return (error); + + if (error = i386_get_ldt(p, parms, retval)) + return (error); + + *retval *= sizeof(union descriptor); + return (0); +} + +struct linux_ldt_info { + u_int entry_number; + u_long base_addr; + u_int limit; + u_int seg_32bit:1; + u_int contents:2; + u_int read_exec_only:1; + u_int limit_in_pages:1; + u_int seg_not_present:1; +}; + +int +linux_write_ldt(p, uap, retval) + struct proc *p; + struct linux_modify_ldt_args /* { + syscallarg(int) func; + syscallarg(void *) ptr; + syscallarg(size_t) bytecount; + } */ *uap; + register_t *retval; +{ + struct linux_ldt_info ldt_info; + struct segment_descriptor sd; + struct i386_set_ldt_args sl; + int error; + caddr_t sg; + char *parms; + + if (SCARG(uap, bytecount) != sizeof(ldt_info)) + return (EINVAL); + if (error = copyin(SCARG(uap, ptr), &ldt_info, sizeof(ldt_info))) + return error; + if (ldt_info.contents == 3) + return (EINVAL); + + sg = stackgap_init(); + + sd.sd_lobase = ldt_info.base_addr & 0xffffff; + sd.sd_hibase = (ldt_info.base_addr >> 24) & 0xff; + sd.sd_lolimit = ldt_info.limit & 0xffff; + sd.sd_hilimit = (ldt_info.limit >> 16) & 0xf; + sd.sd_type = + 16 | (ldt_info.contents << 2) | (!ldt_info.read_exec_only << 1); + sd.sd_dpl = SEL_UPL; + sd.sd_p = !ldt_info.seg_not_present; + sd.sd_def32 = ldt_info.seg_32bit; + sd.sd_gran = ldt_info.limit_in_pages; + + sl.start = ldt_info.entry_number; + sl.desc = stackgap_alloc(&sg, sizeof(sd)); + sl.num = 1; + + printf("linux_write_ldt: idx=%d, base=%x, limit=%x\n", + ldt_info.entry_number, ldt_info.base_addr, ldt_info.limit); + + parms = stackgap_alloc(&sg, sizeof(sl)); + + if (error = copyout(&sd, sl.desc, sizeof(sd))) + return (error); + if (error = copyout(&sl, parms, sizeof(sl))) + return (error); + + if (error = i386_set_ldt(p, parms, retval)) + return (error); + + *retval = 0; + return (0); +} + +#endif /* USER_LDT */ + int linux_modify_ldt(p, uap, retval) struct proc *p; @@ -254,10 +363,14 @@ linux_modify_ldt(p, uap, retval) { switch (SCARG(uap, func)) { +#ifdef USER_LDT case 0: - /* read */ + return (linux_read_ldt(p, uap, retval)); + case 1: - /* write */ + return (linux_write_ldt(p, uap, retval)); +#endif /* USER_LDT */ + default: return (ENOSYS); } diff --git a/sys/arch/i386/include/linux_machdep.h b/sys/arch/i386/include/linux_machdep.h index 9fc9bc1bbba3..eb1becf514c1 100644 --- a/sys/arch/i386/include/linux_machdep.h +++ b/sys/arch/i386/include/linux_machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.h,v 1.2 1995/04/22 20:27:03 christos Exp $ */ +/* $NetBSD: linux_machdep.h,v 1.3 1995/05/07 02:59:34 mycroft Exp $ */ /* * Copyright (c) 1995 Frank van der Linden @@ -39,27 +39,28 @@ */ struct linux_sigcontext { - int lsc_gs; - int lsc_fs; - int lsc_es; - int lsc_ds; - int lsc_edi; - int lsc_esi; - int lsc_ebp; - int lsc_ebx; - int lsc_edx; - int lsc_ecx; - int lsc_eax; - int lsc_trapno; - int lsc_err; - int lsc_eip; - int lsc_cs; - int lsc_eflags; - int lsc_esp; - int lsc_ss; - int lsc_387; - int lsc_mask; - int lsc_cr2; + int sc_gs; + int sc_fs; + int sc_es; + int sc_ds; + int sc_edi; + int sc_esi; + int sc_ebp; + int sc_esp; + int sc_ebx; + int sc_edx; + int sc_ecx; + int sc_eax; + int sc_trapno; + int sc_err; + int sc_eip; + int sc_cs; + int sc_eflags; + int sc_esp_at_signal; + int sc_ss; + int sc_387; + int sc_mask; + int sc_cr2; }; /* @@ -70,9 +71,9 @@ struct linux_sigcontext { */ struct linux_sigframe { - int ls_sig; - struct linux_sigcontext ls_sc; - sig_t ls_handler; + int sf_sig; + struct linux_sigcontext sf_sc; + sig_t sf_handler; }; void linux_sendsig __P((sig_t, int, int, u_long)); diff --git a/sys/compat/linux/arch/i386/linux_machdep.c b/sys/compat/linux/arch/i386/linux_machdep.c index b252d2806908..4d9bf5800031 100644 --- a/sys/compat/linux/arch/i386/linux_machdep.c +++ b/sys/compat/linux/arch/i386/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.6 1995/05/06 18:17:15 mycroft Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.7 1995/05/07 02:59:32 mycroft Exp $ */ /* * Copyright (c) 1995 Frank van der Linden @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -52,14 +51,18 @@ #include #include #include + #include #include +#include #include #include #include #include +#include #include +#include #include /* @@ -107,42 +110,42 @@ linux_sendsig(catcher, sig, mask, code) fp = (struct linux_sigframe *)tf->tf_esp - 1; } - frame.ls_handler = catcher; - frame.ls_sig = bsd_to_linux_sig(sig); + frame.sf_handler = catcher; + frame.sf_sig = bsd_to_linux_sig(sig); /* * Build the signal context to be used by sigreturn. */ - frame.ls_sc.lsc_mask = mask; + frame.sf_sc.sc_mask = mask; #ifdef VM86 if (tf->tf_eflags & PSL_VM) { - frame.ls_sc.lsc_gs = tf->tf_vm86_gs; - frame.ls_sc.lsc_fs = tf->tf_vm86_fs; - frame.ls_sc.lsc_es = tf->tf_vm86_es; - frame.ls_sc.lsc_ds = tf->tf_vm86_ds; + frame.sf_sc.sc_gs = tf->tf_vm86_gs; + frame.sf_sc.sc_fs = tf->tf_vm86_fs; + frame.sf_sc.sc_es = tf->tf_vm86_es; + frame.sf_sc.sc_ds = tf->tf_vm86_ds; } else #else { - __asm("movl %%gs,%w0" : "=r" (frame.ls_sc.lsc_gs)); - __asm("movl %%fs,%w0" : "=r" (frame.ls_sc.lsc_fs)); - frame.ls_sc.lsc_es = tf->tf_es; - frame.ls_sc.lsc_ds = tf->tf_ds; + __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs)); + __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs)); + frame.sf_sc.sc_es = tf->tf_es; + frame.sf_sc.sc_ds = tf->tf_ds; } #endif - frame.ls_sc.lsc_edi = tf->tf_edi; - frame.ls_sc.lsc_esi = tf->tf_esi; - frame.ls_sc.lsc_ebp = tf->tf_ebp; - frame.ls_sc.lsc_ebx = tf->tf_ebx; - frame.ls_sc.lsc_edx = tf->tf_edx; - frame.ls_sc.lsc_ecx = tf->tf_ecx; - frame.ls_sc.lsc_eax = tf->tf_eax; - frame.ls_sc.lsc_eip = tf->tf_eip; - frame.ls_sc.lsc_cs = tf->tf_cs; - frame.ls_sc.lsc_eflags = tf->tf_eflags; - frame.ls_sc.lsc_esp = tf->tf_esp; - frame.ls_sc.lsc_ss = tf->tf_ss; - frame.ls_sc.lsc_err = tf->tf_err; - frame.ls_sc.lsc_trapno = tf->tf_trapno; + frame.sf_sc.sc_edi = tf->tf_edi; + frame.sf_sc.sc_esi = tf->tf_esi; + frame.sf_sc.sc_ebp = tf->tf_ebp; + frame.sf_sc.sc_ebx = tf->tf_ebx; + frame.sf_sc.sc_edx = tf->tf_edx; + frame.sf_sc.sc_ecx = tf->tf_ecx; + frame.sf_sc.sc_eax = tf->tf_eax; + frame.sf_sc.sc_eip = tf->tf_eip; + frame.sf_sc.sc_cs = tf->tf_cs; + frame.sf_sc.sc_eflags = tf->tf_eflags; + frame.sf_sc.sc_esp_at_signal = tf->tf_esp; + frame.sf_sc.sc_ss = tf->tf_ss; + frame.sf_sc.sc_err = tf->tf_err; + frame.sf_sc.sc_trapno = tf->tf_trapno; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* @@ -203,45 +206,151 @@ linux_sigreturn(p, uap, retval) /* * Check for security violations. */ - if (((context.lsc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || - ISPL(context.lsc_cs) != SEL_UPL) + if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || + ISPL(context.sc_cs) != SEL_UPL) return (EINVAL); p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; - p->p_sigmask = context.lsc_mask & ~sigcantmask; + p->p_sigmask = context.sc_mask & ~sigcantmask; /* * Restore signal context. */ #ifdef VM86 - if (context.lsc_eflags & PSL_VM) { - tf->tf_vm86_gs = context.lsc_gs; - tf->tf_vm86_fs = context.lsc_fs; - tf->tf_vm86_es = context.lsc_es; - tf->tf_vm86_ds = context.lsc_ds; + if (context.sc_eflags & PSL_VM) { + tf->tf_vm86_gs = context.sc_gs; + tf->tf_vm86_fs = context.sc_fs; + tf->tf_vm86_es = context.sc_es; + tf->tf_vm86_ds = context.sc_ds; } else #endif { /* %fs and %gs were restored by the trampoline. */ - tf->tf_es = context.lsc_es; - tf->tf_ds = context.lsc_ds; + tf->tf_es = context.sc_es; + tf->tf_ds = context.sc_ds; } - tf->tf_edi = context.lsc_edi; - tf->tf_esi = context.lsc_esi; - tf->tf_ebp = context.lsc_ebp; - tf->tf_ebx = context.lsc_ebx; - tf->tf_edx = context.lsc_edx; - tf->tf_ecx = context.lsc_ecx; - tf->tf_eax = context.lsc_eax; - tf->tf_eip = context.lsc_eip; - tf->tf_cs = context.lsc_cs; - tf->tf_eflags = context.lsc_eflags; - tf->tf_esp = context.lsc_esp; - tf->tf_ss = context.lsc_ss; + tf->tf_edi = context.sc_edi; + tf->tf_esi = context.sc_esi; + tf->tf_ebp = context.sc_ebp; + tf->tf_ebx = context.sc_ebx; + tf->tf_edx = context.sc_edx; + tf->tf_ecx = context.sc_ecx; + tf->tf_eax = context.sc_eax; + tf->tf_eip = context.sc_eip; + tf->tf_cs = context.sc_cs; + tf->tf_eflags = context.sc_eflags; + tf->tf_esp = context.sc_esp_at_signal; + tf->tf_ss = context.sc_ss; return (EJUSTRETURN); } +#ifdef USER_LDT + +int +linux_read_ldt(p, uap, retval) + struct proc *p; + struct linux_modify_ldt_args /* { + syscallarg(int) func; + syscallarg(void *) ptr; + syscallarg(size_t) bytecount; + } */ *uap; + register_t *retval; +{ + struct i386_get_ldt_args gl; + int error; + caddr_t sg; + char *parms; + + sg = stackgap_init(); + + gl.start = 0; + gl.desc = SCARG(uap, ptr); + gl.num = SCARG(uap, bytecount) / sizeof(union descriptor); + + parms = stackgap_alloc(&sg, sizeof(gl)); + + if (error = copyout(&gl, parms, sizeof(gl))) + return (error); + + if (error = i386_get_ldt(p, parms, retval)) + return (error); + + *retval *= sizeof(union descriptor); + return (0); +} + +struct linux_ldt_info { + u_int entry_number; + u_long base_addr; + u_int limit; + u_int seg_32bit:1; + u_int contents:2; + u_int read_exec_only:1; + u_int limit_in_pages:1; + u_int seg_not_present:1; +}; + +int +linux_write_ldt(p, uap, retval) + struct proc *p; + struct linux_modify_ldt_args /* { + syscallarg(int) func; + syscallarg(void *) ptr; + syscallarg(size_t) bytecount; + } */ *uap; + register_t *retval; +{ + struct linux_ldt_info ldt_info; + struct segment_descriptor sd; + struct i386_set_ldt_args sl; + int error; + caddr_t sg; + char *parms; + + if (SCARG(uap, bytecount) != sizeof(ldt_info)) + return (EINVAL); + if (error = copyin(SCARG(uap, ptr), &ldt_info, sizeof(ldt_info))) + return error; + if (ldt_info.contents == 3) + return (EINVAL); + + sg = stackgap_init(); + + sd.sd_lobase = ldt_info.base_addr & 0xffffff; + sd.sd_hibase = (ldt_info.base_addr >> 24) & 0xff; + sd.sd_lolimit = ldt_info.limit & 0xffff; + sd.sd_hilimit = (ldt_info.limit >> 16) & 0xf; + sd.sd_type = + 16 | (ldt_info.contents << 2) | (!ldt_info.read_exec_only << 1); + sd.sd_dpl = SEL_UPL; + sd.sd_p = !ldt_info.seg_not_present; + sd.sd_def32 = ldt_info.seg_32bit; + sd.sd_gran = ldt_info.limit_in_pages; + + sl.start = ldt_info.entry_number; + sl.desc = stackgap_alloc(&sg, sizeof(sd)); + sl.num = 1; + + printf("linux_write_ldt: idx=%d, base=%x, limit=%x\n", + ldt_info.entry_number, ldt_info.base_addr, ldt_info.limit); + + parms = stackgap_alloc(&sg, sizeof(sl)); + + if (error = copyout(&sd, sl.desc, sizeof(sd))) + return (error); + if (error = copyout(&sl, parms, sizeof(sl))) + return (error); + + if (error = i386_set_ldt(p, parms, retval)) + return (error); + + *retval = 0; + return (0); +} + +#endif /* USER_LDT */ + int linux_modify_ldt(p, uap, retval) struct proc *p; @@ -254,10 +363,14 @@ linux_modify_ldt(p, uap, retval) { switch (SCARG(uap, func)) { +#ifdef USER_LDT case 0: - /* read */ + return (linux_read_ldt(p, uap, retval)); + case 1: - /* write */ + return (linux_write_ldt(p, uap, retval)); +#endif /* USER_LDT */ + default: return (ENOSYS); } diff --git a/sys/compat/linux/arch/i386/linux_machdep.h b/sys/compat/linux/arch/i386/linux_machdep.h index 9fc9bc1bbba3..eb1becf514c1 100644 --- a/sys/compat/linux/arch/i386/linux_machdep.h +++ b/sys/compat/linux/arch/i386/linux_machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.h,v 1.2 1995/04/22 20:27:03 christos Exp $ */ +/* $NetBSD: linux_machdep.h,v 1.3 1995/05/07 02:59:34 mycroft Exp $ */ /* * Copyright (c) 1995 Frank van der Linden @@ -39,27 +39,28 @@ */ struct linux_sigcontext { - int lsc_gs; - int lsc_fs; - int lsc_es; - int lsc_ds; - int lsc_edi; - int lsc_esi; - int lsc_ebp; - int lsc_ebx; - int lsc_edx; - int lsc_ecx; - int lsc_eax; - int lsc_trapno; - int lsc_err; - int lsc_eip; - int lsc_cs; - int lsc_eflags; - int lsc_esp; - int lsc_ss; - int lsc_387; - int lsc_mask; - int lsc_cr2; + int sc_gs; + int sc_fs; + int sc_es; + int sc_ds; + int sc_edi; + int sc_esi; + int sc_ebp; + int sc_esp; + int sc_ebx; + int sc_edx; + int sc_ecx; + int sc_eax; + int sc_trapno; + int sc_err; + int sc_eip; + int sc_cs; + int sc_eflags; + int sc_esp_at_signal; + int sc_ss; + int sc_387; + int sc_mask; + int sc_cr2; }; /* @@ -70,9 +71,9 @@ struct linux_sigcontext { */ struct linux_sigframe { - int ls_sig; - struct linux_sigcontext ls_sc; - sig_t ls_handler; + int sf_sig; + struct linux_sigcontext sf_sc; + sig_t sf_handler; }; void linux_sendsig __P((sig_t, int, int, u_long)); diff --git a/sys/compat/linux/i386/linux_machdep.c b/sys/compat/linux/i386/linux_machdep.c index b252d2806908..4d9bf5800031 100644 --- a/sys/compat/linux/i386/linux_machdep.c +++ b/sys/compat/linux/i386/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.6 1995/05/06 18:17:15 mycroft Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.7 1995/05/07 02:59:32 mycroft Exp $ */ /* * Copyright (c) 1995 Frank van der Linden @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -52,14 +51,18 @@ #include #include #include + #include #include +#include #include #include #include #include +#include #include +#include #include /* @@ -107,42 +110,42 @@ linux_sendsig(catcher, sig, mask, code) fp = (struct linux_sigframe *)tf->tf_esp - 1; } - frame.ls_handler = catcher; - frame.ls_sig = bsd_to_linux_sig(sig); + frame.sf_handler = catcher; + frame.sf_sig = bsd_to_linux_sig(sig); /* * Build the signal context to be used by sigreturn. */ - frame.ls_sc.lsc_mask = mask; + frame.sf_sc.sc_mask = mask; #ifdef VM86 if (tf->tf_eflags & PSL_VM) { - frame.ls_sc.lsc_gs = tf->tf_vm86_gs; - frame.ls_sc.lsc_fs = tf->tf_vm86_fs; - frame.ls_sc.lsc_es = tf->tf_vm86_es; - frame.ls_sc.lsc_ds = tf->tf_vm86_ds; + frame.sf_sc.sc_gs = tf->tf_vm86_gs; + frame.sf_sc.sc_fs = tf->tf_vm86_fs; + frame.sf_sc.sc_es = tf->tf_vm86_es; + frame.sf_sc.sc_ds = tf->tf_vm86_ds; } else #else { - __asm("movl %%gs,%w0" : "=r" (frame.ls_sc.lsc_gs)); - __asm("movl %%fs,%w0" : "=r" (frame.ls_sc.lsc_fs)); - frame.ls_sc.lsc_es = tf->tf_es; - frame.ls_sc.lsc_ds = tf->tf_ds; + __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs)); + __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs)); + frame.sf_sc.sc_es = tf->tf_es; + frame.sf_sc.sc_ds = tf->tf_ds; } #endif - frame.ls_sc.lsc_edi = tf->tf_edi; - frame.ls_sc.lsc_esi = tf->tf_esi; - frame.ls_sc.lsc_ebp = tf->tf_ebp; - frame.ls_sc.lsc_ebx = tf->tf_ebx; - frame.ls_sc.lsc_edx = tf->tf_edx; - frame.ls_sc.lsc_ecx = tf->tf_ecx; - frame.ls_sc.lsc_eax = tf->tf_eax; - frame.ls_sc.lsc_eip = tf->tf_eip; - frame.ls_sc.lsc_cs = tf->tf_cs; - frame.ls_sc.lsc_eflags = tf->tf_eflags; - frame.ls_sc.lsc_esp = tf->tf_esp; - frame.ls_sc.lsc_ss = tf->tf_ss; - frame.ls_sc.lsc_err = tf->tf_err; - frame.ls_sc.lsc_trapno = tf->tf_trapno; + frame.sf_sc.sc_edi = tf->tf_edi; + frame.sf_sc.sc_esi = tf->tf_esi; + frame.sf_sc.sc_ebp = tf->tf_ebp; + frame.sf_sc.sc_ebx = tf->tf_ebx; + frame.sf_sc.sc_edx = tf->tf_edx; + frame.sf_sc.sc_ecx = tf->tf_ecx; + frame.sf_sc.sc_eax = tf->tf_eax; + frame.sf_sc.sc_eip = tf->tf_eip; + frame.sf_sc.sc_cs = tf->tf_cs; + frame.sf_sc.sc_eflags = tf->tf_eflags; + frame.sf_sc.sc_esp_at_signal = tf->tf_esp; + frame.sf_sc.sc_ss = tf->tf_ss; + frame.sf_sc.sc_err = tf->tf_err; + frame.sf_sc.sc_trapno = tf->tf_trapno; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* @@ -203,45 +206,151 @@ linux_sigreturn(p, uap, retval) /* * Check for security violations. */ - if (((context.lsc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || - ISPL(context.lsc_cs) != SEL_UPL) + if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || + ISPL(context.sc_cs) != SEL_UPL) return (EINVAL); p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; - p->p_sigmask = context.lsc_mask & ~sigcantmask; + p->p_sigmask = context.sc_mask & ~sigcantmask; /* * Restore signal context. */ #ifdef VM86 - if (context.lsc_eflags & PSL_VM) { - tf->tf_vm86_gs = context.lsc_gs; - tf->tf_vm86_fs = context.lsc_fs; - tf->tf_vm86_es = context.lsc_es; - tf->tf_vm86_ds = context.lsc_ds; + if (context.sc_eflags & PSL_VM) { + tf->tf_vm86_gs = context.sc_gs; + tf->tf_vm86_fs = context.sc_fs; + tf->tf_vm86_es = context.sc_es; + tf->tf_vm86_ds = context.sc_ds; } else #endif { /* %fs and %gs were restored by the trampoline. */ - tf->tf_es = context.lsc_es; - tf->tf_ds = context.lsc_ds; + tf->tf_es = context.sc_es; + tf->tf_ds = context.sc_ds; } - tf->tf_edi = context.lsc_edi; - tf->tf_esi = context.lsc_esi; - tf->tf_ebp = context.lsc_ebp; - tf->tf_ebx = context.lsc_ebx; - tf->tf_edx = context.lsc_edx; - tf->tf_ecx = context.lsc_ecx; - tf->tf_eax = context.lsc_eax; - tf->tf_eip = context.lsc_eip; - tf->tf_cs = context.lsc_cs; - tf->tf_eflags = context.lsc_eflags; - tf->tf_esp = context.lsc_esp; - tf->tf_ss = context.lsc_ss; + tf->tf_edi = context.sc_edi; + tf->tf_esi = context.sc_esi; + tf->tf_ebp = context.sc_ebp; + tf->tf_ebx = context.sc_ebx; + tf->tf_edx = context.sc_edx; + tf->tf_ecx = context.sc_ecx; + tf->tf_eax = context.sc_eax; + tf->tf_eip = context.sc_eip; + tf->tf_cs = context.sc_cs; + tf->tf_eflags = context.sc_eflags; + tf->tf_esp = context.sc_esp_at_signal; + tf->tf_ss = context.sc_ss; return (EJUSTRETURN); } +#ifdef USER_LDT + +int +linux_read_ldt(p, uap, retval) + struct proc *p; + struct linux_modify_ldt_args /* { + syscallarg(int) func; + syscallarg(void *) ptr; + syscallarg(size_t) bytecount; + } */ *uap; + register_t *retval; +{ + struct i386_get_ldt_args gl; + int error; + caddr_t sg; + char *parms; + + sg = stackgap_init(); + + gl.start = 0; + gl.desc = SCARG(uap, ptr); + gl.num = SCARG(uap, bytecount) / sizeof(union descriptor); + + parms = stackgap_alloc(&sg, sizeof(gl)); + + if (error = copyout(&gl, parms, sizeof(gl))) + return (error); + + if (error = i386_get_ldt(p, parms, retval)) + return (error); + + *retval *= sizeof(union descriptor); + return (0); +} + +struct linux_ldt_info { + u_int entry_number; + u_long base_addr; + u_int limit; + u_int seg_32bit:1; + u_int contents:2; + u_int read_exec_only:1; + u_int limit_in_pages:1; + u_int seg_not_present:1; +}; + +int +linux_write_ldt(p, uap, retval) + struct proc *p; + struct linux_modify_ldt_args /* { + syscallarg(int) func; + syscallarg(void *) ptr; + syscallarg(size_t) bytecount; + } */ *uap; + register_t *retval; +{ + struct linux_ldt_info ldt_info; + struct segment_descriptor sd; + struct i386_set_ldt_args sl; + int error; + caddr_t sg; + char *parms; + + if (SCARG(uap, bytecount) != sizeof(ldt_info)) + return (EINVAL); + if (error = copyin(SCARG(uap, ptr), &ldt_info, sizeof(ldt_info))) + return error; + if (ldt_info.contents == 3) + return (EINVAL); + + sg = stackgap_init(); + + sd.sd_lobase = ldt_info.base_addr & 0xffffff; + sd.sd_hibase = (ldt_info.base_addr >> 24) & 0xff; + sd.sd_lolimit = ldt_info.limit & 0xffff; + sd.sd_hilimit = (ldt_info.limit >> 16) & 0xf; + sd.sd_type = + 16 | (ldt_info.contents << 2) | (!ldt_info.read_exec_only << 1); + sd.sd_dpl = SEL_UPL; + sd.sd_p = !ldt_info.seg_not_present; + sd.sd_def32 = ldt_info.seg_32bit; + sd.sd_gran = ldt_info.limit_in_pages; + + sl.start = ldt_info.entry_number; + sl.desc = stackgap_alloc(&sg, sizeof(sd)); + sl.num = 1; + + printf("linux_write_ldt: idx=%d, base=%x, limit=%x\n", + ldt_info.entry_number, ldt_info.base_addr, ldt_info.limit); + + parms = stackgap_alloc(&sg, sizeof(sl)); + + if (error = copyout(&sd, sl.desc, sizeof(sd))) + return (error); + if (error = copyout(&sl, parms, sizeof(sl))) + return (error); + + if (error = i386_set_ldt(p, parms, retval)) + return (error); + + *retval = 0; + return (0); +} + +#endif /* USER_LDT */ + int linux_modify_ldt(p, uap, retval) struct proc *p; @@ -254,10 +363,14 @@ linux_modify_ldt(p, uap, retval) { switch (SCARG(uap, func)) { +#ifdef USER_LDT case 0: - /* read */ + return (linux_read_ldt(p, uap, retval)); + case 1: - /* write */ + return (linux_write_ldt(p, uap, retval)); +#endif /* USER_LDT */ + default: return (ENOSYS); } diff --git a/sys/compat/linux/i386/linux_machdep.h b/sys/compat/linux/i386/linux_machdep.h index 9fc9bc1bbba3..eb1becf514c1 100644 --- a/sys/compat/linux/i386/linux_machdep.h +++ b/sys/compat/linux/i386/linux_machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.h,v 1.2 1995/04/22 20:27:03 christos Exp $ */ +/* $NetBSD: linux_machdep.h,v 1.3 1995/05/07 02:59:34 mycroft Exp $ */ /* * Copyright (c) 1995 Frank van der Linden @@ -39,27 +39,28 @@ */ struct linux_sigcontext { - int lsc_gs; - int lsc_fs; - int lsc_es; - int lsc_ds; - int lsc_edi; - int lsc_esi; - int lsc_ebp; - int lsc_ebx; - int lsc_edx; - int lsc_ecx; - int lsc_eax; - int lsc_trapno; - int lsc_err; - int lsc_eip; - int lsc_cs; - int lsc_eflags; - int lsc_esp; - int lsc_ss; - int lsc_387; - int lsc_mask; - int lsc_cr2; + int sc_gs; + int sc_fs; + int sc_es; + int sc_ds; + int sc_edi; + int sc_esi; + int sc_ebp; + int sc_esp; + int sc_ebx; + int sc_edx; + int sc_ecx; + int sc_eax; + int sc_trapno; + int sc_err; + int sc_eip; + int sc_cs; + int sc_eflags; + int sc_esp_at_signal; + int sc_ss; + int sc_387; + int sc_mask; + int sc_cr2; }; /* @@ -70,9 +71,9 @@ struct linux_sigcontext { */ struct linux_sigframe { - int ls_sig; - struct linux_sigcontext ls_sc; - sig_t ls_handler; + int sf_sig; + struct linux_sigcontext sf_sc; + sig_t sf_handler; }; void linux_sendsig __P((sig_t, int, int, u_long));