From owner-freebsd-emulation Thu Sep 14 12:32: 7 2000 Delivered-To: freebsd-emulation@freebsd.org Received: from isds.duke.edu (davinci.isds.duke.edu [152.3.22.1]) by hub.freebsd.org (Postfix) with ESMTP id 3C9AD37B424 for ; Thu, 14 Sep 2000 12:31:48 -0700 (PDT) Received: from feta.isds.duke.edu (feta.isds.duke.edu [152.3.22.76]) by isds.duke.edu (8.8.8/8.8.8) with ESMTP id PAA07114 for ; Thu, 14 Sep 2000 15:31:46 -0400 (EDT) Received: (from sto@localhost) by feta.isds.duke.edu (8.11.0/8.9.3) id e8EJVjW06091 for freebsd-emulation@FreeBSD.ORG; Thu, 14 Sep 2000 15:31:45 -0400 (EDT) (envelope-from sto) Date: Thu, 14 Sep 2000 15:31:45 -0400 From: "Sean O'Connell" To: FreeBSD emulation Subject: Quick and Dirty MFC of Andrew Gallatin's Java patches Message-ID: <20000914153145.V4542@stat.Duke.EDU> Reply-To: "Sean O'Connell" Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="o0ZfoUVt4BxPQnbU" Content-Disposition: inline User-Agent: Mutt/1.2.5i X-Organization: Institute of Statistics and Decision Sciences Sender: owner-freebsd-emulation@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org --o0ZfoUVt4BxPQnbU Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi All- I did a Quick&Dirty MFC of Andrew Gallatin's work on getting the IBM Java SDK to work. I was able to run the appletviewer on one of the demos and it worked. I cannot say much more than that. The patches are all relative to /usr/src (or / since they are all in sys ) The majority of the patches are for files in /sys/i386/linux. You should be able to apply the patch; cd to /sys/modules/linux; type make; kldunload linux; type make install; and kldload linux There is an additonal change which sets the MINSIGSTKSZ to 2048 in sys/sys/signal.h .. this will require a kernel rebuild to take effect. I am sending the patch as an attachment to prevent it from getting munged. If there is an overwhelming demand, I could make it available via http. HTH, Sean --o0ZfoUVt4BxPQnbU Content-Type: text/plain; charset=us-ascii Content-Description: MFC attempt of Drew's JDK patches Content-Disposition: attachment; filename="linux.patch2" --- sys/i386/linux/linux.h.orig Tue Sep 12 10:14:29 2000 +++ sys/i386/linux/linux.h Thu Sep 14 12:28:12 2000 @@ -33,6 +33,8 @@ #include +#include /* for sigval union */ + #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_LINUX); #endif @@ -157,6 +159,15 @@ #define LINUX_SIGISMEMBER(set, sig) SIGISMEMBER(set, sig) #define LINUX_SIGADDSET(set, sig) SIGADDSET(set, sig) +/* sigaltstack */ +#define LINUX_MINSIGSTKSZ 2048 +#define LINUX_SS_ONSTACK 1 +#define LINUX_SS_DISABLE 2 +#define LINUX_SS_DISABLE_BC 0 /* backwards compat SS_DISABLE */ + +void linux_to_bsd_sigaltstack(int *lsa, int *bsa); +void bsd_to_linux_sigaltstack(int *bsa, int *lsa); + typedef void (*linux_handler_t)(int); typedef u_long linux_osigset_t; @@ -210,6 +221,72 @@ int sc_cr2; }; + +struct linux_ucontext { + unsigned long uc_flags; + void *uc_link; + linux_stack_t uc_stack; + struct linux_sigcontext uc_mcontext; + linux_sigset_t uc_sigmask; +}; + +#define LINUX_SI_MAX_SIZE 128 +#define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE/sizeof(int)) - 3) + +typedef struct siginfo { + int lsi_signo; + int lsi_errno; + int lsi_code; + + union { + int _pad[LINUX_SI_PAD_SIZE]; + struct { + linux_pid_t _pid; + linux_uid_t _uid; + } _kill; + + struct { + unsigned int _timer1; + unsigned int _timer2; + } _timer; + + struct { + linux_pid_t _pid; /* sender's pid */ + linux_uid_t _uid; /* sender's uid */ + union sigval _sigval; + } _rt; + + struct { + linux_pid_t _pid; /* which child */ + linux_uid_t _uid; /* sender's uid */ + int _status; /* exit code */ + linux_clock_t _utime; + linux_clock_t _stime; + } _sigchld; + + struct { + void *_addr; /* faulting insn/memory ref. */ + } _sigfault; + + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} linux_siginfo_t; + +#define lsi_pid _sifields._kill._pid +#define lsi_uid _sifields._kill._uid +#define lsi_status _sifields._sigchld._status +#define lsi_utime _sifields._sigchld._utime +#define lsi_stime _sifields._sigchld._stime +#define lsi_value _sifields._rt._sigval +#define lsi_int _sifields._rt._sigval.sival_int +#define lsi_ptr _sifields._rt._sigval.sival_ptr +#define lsi_addr _sifields._sigfault._addr +#define lsi_band _sifields._sigpoll._band +#define lsi_fd _sifields._sigpoll._fd + /* * We make the stack look like Linux expects it when calling a signal * handler, but use the BSD way of calling the handler and sigreturn(). @@ -219,13 +296,28 @@ struct linux_sigframe { int sf_sig; struct linux_sigcontext sf_sc; + int pad[41]; /* pad it out so we can use the same + * trampoline code for both types of + * sigframes + */ + linux_handler_t sf_handler; }; +struct linux_rt_sigframe { + int sf_sig; + linux_siginfo_t *sf_siginfo; + struct linux_ucontext *sf_ucontext; /* points to sf_uc */ + linux_siginfo_t sf_si; + struct linux_ucontext sf_sc; /* = *sf_ucontext */ + linux_handler_t sf_handler; +}; + extern int bsd_to_linux_signal[]; extern int linux_to_bsd_signal[]; extern struct sysentvec linux_sysvec; extern struct sysentvec elf_linux_sysvec; +void bsd_to_linux_sigset(sigset_t *bss, linux_sigset_t *lss); /* * Pluggable ioctl handlers --- sys/i386/linux/linux_dummy.c.orig Thu Sep 14 10:37:48 2000 +++ sys/i386/linux/linux_dummy.c Thu Sep 14 10:38:06 2000 @@ -94,7 +94,6 @@ DUMMY(nfsservctl); DUMMY(getresgid); DUMMY(prctl); -DUMMY(rt_sigreturn); DUMMY(rt_sigpending); DUMMY(rt_sigtimedwait); DUMMY(rt_sigqueueinfo); --- sys/i386/linux/linux_file.c.orig Fri Nov 26 05:20:09 1999 +++ sys/i386/linux/linux_file.c Thu Jul 20 15:29:37 2000 @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/i386/linux/linux_file.c,v 1.38 1999/11/26 10:20:09 marcel Exp $ + * $FreeBSD: src/sys/i386/linux/linux_file.c,v 1.38.2.2 2000/07/19 21:12:39 marcel Exp $ */ #include "opt_compat.h" @@ -199,14 +199,7 @@ } */ fcntl_args; struct linux_flock linux_flock; struct flock *bsd_flock; - struct filedesc *fdp; - struct file *fp; - struct vnode *vp; - long pgid; - struct pgrp *pgrp; - struct tty *tp; caddr_t sg; - dev_t dev; sg = stackgap_init(); bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock)); @@ -287,49 +280,14 @@ fcntl_args.arg = (int)bsd_flock; return fcntl(p, &fcntl_args); - case LINUX_F_SETOWN: case LINUX_F_GETOWN: - /* - * We need to route around the normal fcntl() for these calls, - * since it uses TIOC{G,S}PGRP, which is too restrictive for - * Linux F_{G,S}ETOWN semantics. For sockets, this problem - * does not exist. - */ - fdp = p->p_fd; - if ((u_int)args->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[args->fd]) == NULL) - return EBADF; - if (fp->f_type == DTYPE_SOCKET) { - fcntl_args.cmd = args->cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; - fcntl_args.arg = args->arg; - return fcntl(p, &fcntl_args); - } - vp = (struct vnode *)fp->f_data; - dev = vn_todev(vp); - if (dev == NODEV) - return EINVAL; - if (!(devsw(dev)->d_flags & D_TTY)) - return EINVAL; - tp = dev->si_tty; - if (!tp) - return EINVAL; - if (args->cmd == LINUX_F_GETOWN) { - p->p_retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; - return 0; - } - if ((long)args->arg <= 0) { - pgid = -(long)args->arg; - } else { - struct proc *p1 = pfind((long)args->arg); - if (p1 == 0) - return (ESRCH); - pgid = (long)p1->p_pgrp->pg_id; - } - pgrp = pgfind(pgid); - if (pgrp == NULL || pgrp->pg_session != p->p_session) - return EPERM; - tp->t_pgrp = pgrp; - return 0; + fcntl_args.cmd = F_GETOWN; + return fcntl(p, &fcntl_args); + + case LINUX_F_SETOWN: + fcntl_args.cmd = F_SETOWN; + fcntl_args.arg = args->arg; + return fcntl(p, &fcntl_args); } return EINVAL; } @@ -890,4 +848,32 @@ bsd.fd = uap->fd; return fsync(p, &bsd); +} + +int +linux_pread(p, uap) + struct proc *p; + struct linux_pread_args *uap; +{ + struct pread_args bsd; + + bsd.fd = uap->fd; + bsd.buf = uap->buf; + bsd.nbyte = uap->nbyte; + bsd.offset = uap->offset; + return pread(p, &bsd); +} + +int +linux_pwrite(p, uap) + struct proc *p; + struct linux_pwrite_args *uap; +{ + struct pwrite_args bsd; + + bsd.fd = uap->fd; + bsd.buf = uap->buf; + bsd.nbyte = uap->nbyte; + bsd.offset = uap->offset; + return pwrite(p, &bsd); } --- sys/i386/linux/linux_genassym.c.orig Thu Sep 14 10:38:18 2000 +++ sys/i386/linux/linux_genassym.c Thu Sep 14 10:38:39 2000 @@ -11,3 +11,5 @@ ASSYM(LINUX_SIGF_SC, offsetof(struct linux_sigframe, sf_sc)); ASSYM(LINUX_SC_GS, offsetof(struct linux_sigcontext, sc_gs)); ASSYM(LINUX_SC_EFLAGS, offsetof(struct linux_sigcontext, sc_eflags)); +ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct linux_rt_sigframe, sf_handler)); +ASSYM(LINUX_RT_SIGF_UC, offsetof(struct linux_rt_sigframe, sf_sc)); --- sys/i386/linux/linux_locore.s.orig Thu Sep 14 10:39:04 2000 +++ sys/i386/linux/linux_locore.s Thu Sep 14 10:43:01 2000 @@ -14,11 +14,24 @@ int $0x80 /* enter kernel with args */ 0: jmp 0b ALIGN_TEXT +/* XXXXX */ + +_linux_rt_sigcode: + call *LINUX_RT_SIGF_HANDLER(%esp) + leal LINUX_RT_SIGF_UC(%esp),%ebx /* linux ucp */ + movl LINUX_SC_GS(%ebx),%gs + push %eax /* fake ret addr */ + movl $LINUX_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */ + int $0x80 /* enter kernel with args */ +0: jmp 0b + ALIGN_TEXT +/* XXXXX */ _linux_esigcode: .data - .globl _linux_szsigcode + .globl _linux_szsigcode, _linux_sznonrtsigcode _linux_szsigcode: .long _linux_esigcode-_linux_sigcode - +_linux_sznonrtsigcode: + .long _linux_rt_sigcode-_linux_sigcode .text --- sys/i386/linux/linux_misc.c.orig Thu Sep 14 10:48:54 2000 +++ sys/i386/linux/linux_misc.c Thu Sep 14 10:53:16 2000 @@ -619,9 +619,9 @@ if (args->flags & CLONE_PID) printf("linux_clone(%ld): CLONE_PID not yet supported\n", (long)p->p_pid); - printf("linux_clone(%ld): invoked with flags %x and stack %x\n", + printf("linux_clone(%ld): invoked with flags 0x%x and stack 0x%lx\n", (long)p->p_pid, (unsigned int)args->flags, - (unsigned int)args->stack); + (unsigned long int)args->stack); #endif if (!args->stack) @@ -696,7 +696,7 @@ sizeof(linux_args)))) return error; #ifdef DEBUG - printf("Linux-emul(%ld): mmap(%p, %d, %d, 0x%08x, %d, %d)", + printf("Linux-emul(%ld): mmap(%p, %d, %d, 0x%08x, %d, %d)\n", (long)p->p_pid, (void *)linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, linux_args.pos); #endif @@ -710,7 +710,7 @@ if (linux_args.flags & LINUX_MAP_ANON) bsd_args.flags |= MAP_ANON; if (linux_args.flags & LINUX_MAP_GROWSDOWN) { - bsd_args.flags |= MAP_STACK; + bsd_args.flags |= /* MAP_STACK; */ MAP_ANON; /*XXXXXXX gallatin*/ /* The linux MAP_GROWSDOWN option does not limit auto * growth of the region. Linux mmap with this option --- sys/i386/linux/linux_proto.h.orig Thu Sep 14 11:32:26 2000 +++ sys/i386/linux/linux_proto.h Thu Sep 14 11:33:35 2000 @@ -452,7 +452,7 @@ register_t dummy; }; struct linux_rt_sigreturn_args { - register_t dummy; + struct linux_ucontext * ucp; char ucp_[PAD_(struct linux_ucontext *)]; }; struct linux_rt_sigaction_args { int sig; char sig_[PAD_(int)]; --- sys/i386/linux/linux_signal.c.orig Tue Sep 12 10:15:54 2000 +++ sys/i386/linux/linux_signal.c Thu Sep 14 11:31:39 2000 @@ -55,7 +55,7 @@ } } -static void +void bsd_to_linux_sigset(sigset_t *bss, linux_sigset_t *lss) { int b, l; @@ -527,15 +527,25 @@ (long)p->p_pid, uap->uss, uap->uoss); #endif - error = copyin(uap->uss, &lss, sizeof(linux_stack_t)); - if (error) - return (error); + if (uap->uss == 0) { + ss = NULL; + } else { + error = copyin(uap->uss, &lss, sizeof(linux_stack_t)); + if (error) + return (error); - ss = stackgap_alloc(&sg, sizeof(stack_t)); - ss->ss_sp = lss.ss_sp; - ss->ss_size = lss.ss_size; - ss->ss_flags = lss.ss_flags; + ss = stackgap_alloc(&sg, sizeof(stack_t)); + ss->ss_sp = lss.ss_sp; + ss->ss_size = (lss.ss_size >= LINUX_MINSIGSTKSZ && + lss.ss_size < MINSIGSTKSZ) ? MINSIGSTKSZ : lss.ss_size; + ss->ss_flags = lss.ss_flags; +#ifdef DEBUG + uprintf("Linux-emul(%ld): sigaltstack flags = 0x%x, sp = %p, oldsp = %p\n", + (long)p->p_pid, ss->ss_flags, lss.ss_sp, p->p_sigstk.ss_sp); +#endif + linux_to_bsd_sigaltstack(&lss.ss_flags, &ss->ss_flags); + } oss = (uap->uoss != NULL) ? stackgap_alloc(&sg, sizeof(stack_t)) : NULL; @@ -547,9 +557,31 @@ if (!error && oss != NULL) { lss.ss_sp = oss->ss_sp; lss.ss_size = oss->ss_size; - lss.ss_flags = oss->ss_flags; + linux_to_bsd_sigaltstack(&oss->ss_flags, &lss.ss_flags); error = copyout(&lss, uap->uoss, sizeof(linux_stack_t)); } return (error); +} + +void +linux_to_bsd_sigaltstack(int *lsa, int *bsa) +{ + *bsa = 0; + if (*lsa & LINUX_SS_DISABLE) + *bsa |= SS_DISABLE; + if (*lsa & LINUX_SS_DISABLE_BC) + *bsa |= SS_DISABLE; + if (*lsa & LINUX_SS_ONSTACK) + *bsa |= SS_ONSTACK; +} + +void +bsd_to_linux_sigaltstack(int *bsa, int *lsa) +{ + *lsa = 0; + if (*bsa & SS_DISABLE) + *lsa |= LINUX_SS_DISABLE; + if (*bsa & SS_ONSTACK) + *lsa |= LINUX_SS_ONSTACK; } --- sys/i386/linux/linux_sysent.c.orig Thu Sep 14 11:34:00 2000 +++ sys/i386/linux/linux_sysent.c Thu Sep 14 11:35:11 2000 @@ -190,7 +190,7 @@ { AS(setresgid_args), (sy_call_t *)setresgid }, /* 170 = setresgid */ { AS(linux_getresgid_args), (sy_call_t *)linux_getresgid }, /* 171 = linux_getresgid */ { 0, (sy_call_t *)linux_prctl }, /* 172 = linux_prctl */ - { 0, (sy_call_t *)linux_rt_sigreturn }, /* 173 = linux_rt_sigreturn */ + { AS(linux_rt_sigreturn_args), (sy_call_t *)linux_rt_sigreturn }, /* 173 = linux_rt_sigreturn */ { AS(linux_rt_sigaction_args), (sy_call_t *)linux_rt_sigaction }, /* 174 = linux_rt_sigaction */ { AS(linux_rt_sigprocmask_args), (sy_call_t *)linux_rt_sigprocmask }, /* 175 = linux_rt_sigprocmask */ { 0, (sy_call_t *)linux_rt_sigpending }, /* 176 = linux_rt_sigpending */ --- sys/i386/linux/linux_sysvec.c.orig Thu Sep 14 11:43:28 2000 +++ sys/i386/linux/linux_sysvec.c Thu Sep 14 12:19:38 2000 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -190,6 +191,137 @@ } extern int _ucodesel, _udatasel; +extern unsigned long _linux_sznonrtsigcode; + + +static void +linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +{ + register struct proc *p = curproc; + register struct trapframe *regs; + struct linux_rt_sigframe *fp, frame; + struct sigacts *psp = p->p_sigacts; + int oonstack; + + regs = p->p_md.md_regs; + oonstack = p->p_sigstk.ss_flags & SS_ONSTACK; + +#ifdef DEBUG + printf("Linux-emul(%ld): linux_rt_sendsig(%p, %d, %p, %lu)\n", + (long)p->p_pid, catcher, sig, (void*)mask, code); +#endif + /* + * Allocate space for the signal handler context. + */ + if ((p->p_flag & P_ALTSTACK) && !oonstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + fp = (struct linux_rt_sigframe *)(p->p_sigstk.ss_sp + + p->p_sigstk.ss_size - sizeof(struct linux_rt_sigframe)); + p->p_sigstk.ss_flags |= SS_ONSTACK; + } else { + fp = (struct linux_rt_sigframe *)regs->tf_esp - 1; + } + + /* + * grow() will return FALSE if the fp will not fit inside the stack + * and the stack can not be grown. useracc will return FALSE + * if access is denied. + */ + if ((grow_stack (p, (int)fp) == FALSE) || + !useracc((caddr_t)fp, sizeof (struct linux_rt_sigframe), + VM_PROT_WRITE)) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + SIGACTION(p, SIGILL) = SIG_DFL; + SIGDELSET(p->p_sigignore, SIGILL); + SIGDELSET(p->p_sigcatch, SIGILL); + SIGDELSET(p->p_sigmask, SIGILL); +#ifdef DEBUG + printf("Linux-emul(%ld): linux_rt_sendsig -- bad stack %p, SS_ONSTACK: 0x%x ", + (long)p->p_pid, fp, p->p_sigstk.ss_flags & SS_ONSTACK); +#endif + psignal(p, SIGILL); + return; + } + + /* + * Build the argument list for the signal handler. + */ + if (p->p_sysent->sv_sigtbl) + if (sig <= p->p_sysent->sv_sigsize) + sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; + + frame.sf_handler = catcher; + frame.sf_sig = sig; + + frame.sf_siginfo = &fp->sf_si; + frame.sf_ucontext = &fp->sf_sc; + /* Fill siginfo structure. */ + frame.sf_si.lsi_signo = sig; + frame.sf_si.lsi_code = code; + frame.sf_si.lsi_addr = (void *)regs->tf_err; + /* + * Build the signal context to be used by sigreturn. + */ + frame.sf_sc.uc_mcontext.sc_mask = mask->__bits[0]; + frame.sf_sc.uc_mcontext.sc_gs = rgs(); + frame.sf_sc.uc_mcontext.sc_fs = regs->tf_fs; + frame.sf_sc.uc_mcontext.sc_es = regs->tf_es; + frame.sf_sc.uc_mcontext.sc_ds = regs->tf_ds; + frame.sf_sc.uc_mcontext.sc_edi = regs->tf_edi; + frame.sf_sc.uc_mcontext.sc_esi = regs->tf_esi; + frame.sf_sc.uc_mcontext.sc_ebp = regs->tf_ebp; + frame.sf_sc.uc_mcontext.sc_ebx = regs->tf_ebx; + frame.sf_sc.uc_mcontext.sc_edx = regs->tf_edx; + frame.sf_sc.uc_mcontext.sc_ecx = regs->tf_ecx; + frame.sf_sc.uc_mcontext.sc_eax = regs->tf_eax; + frame.sf_sc.uc_mcontext.sc_eip = regs->tf_eip; + frame.sf_sc.uc_mcontext.sc_cs = regs->tf_cs; + frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_eflags; + frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_esp; + frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss; + frame.sf_sc.uc_mcontext.sc_err = regs->tf_err; + frame.sf_sc.uc_mcontext.sc_trapno = code; /* XXX ???? */ + + /* + * Build the remainder of the ucontext struct to be used by sigreturn. + */ + frame.sf_sc.uc_flags = 0; /* XXX ??? */ + frame.sf_sc.uc_link = NULL; /* XXX ??? */ + frame.sf_sc.uc_stack.ss_sp = p->p_sigstk.ss_sp; + bsd_to_linux_sigaltstack(&p->p_sigstk.ss_flags, &frame.sf_sc.uc_stack.ss_flags); + frame.sf_sc.uc_stack.ss_size = p->p_sigstk.ss_size; +#ifdef DEBUG + printf("Linux-emul(%ld): rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x\n", + (long)p->p_pid, frame.sf_sc.uc_stack.ss_flags, p->p_sigstk.ss_sp, + p->p_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask); +#endif + bsd_to_linux_sigset(&p->p_sigmask, &frame.sf_sc.uc_sigmask); + + if (copyout(&frame, fp, sizeof(frame)) != 0) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + sigexit(p, SIGILL); + /* NOTREACHED */ + } + + /* + * Build context to run handler in. + */ + regs->tf_esp = (int)fp; + regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode) + _linux_sznonrtsigcode; + regs->tf_eflags &= ~PSL_VM; + regs->tf_cs = _ucodesel; + regs->tf_ds = _udatasel; + regs->tf_es = _udatasel; + regs->tf_fs = _udatasel; + load_gs(_udatasel); + regs->tf_ss = _udatasel; +} /* * Send an interrupt to process. @@ -215,9 +347,16 @@ oonstack = p->p_sigstk.ss_flags & SS_ONSTACK; #ifdef DEBUG - printf("Linux-emul(%ld): linux_sendsig(%p, %d, %p, %lu)\n", + printf("Linux-emul(%ld): linux_sendsig(%p, %d, %p, %lu)", (long)p->p_pid, catcher, sig, (void*)mask, code); #endif + + if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + /* Signal handler installed with SA_SIGINFO. */ + linux_rt_sendsig(catcher, sig, mask, code); + return; + } + /* * Allocate space for the signal handler context. */ @@ -397,6 +536,120 @@ return (EJUSTRETURN); } + +/* + * System call to cleanup state after a signal + * has been taken. Reset signal mask and + * stack state from context left by sendsig (above). + * Return to previous pc and psl as specified by + * context left by sendsig. Check carefully to + * make sure that the user has not modified the + * psl to gain improper privileges or to cause + * a machine fault. + */ +int +linux_rt_sigreturn(p, args) + struct proc *p; + struct linux_rt_sigreturn_args *args; +{ + struct sigaltstack_args sasargs; + struct linux_ucontext uc; + struct linux_sigcontext *context; + linux_stack_t *lss; + stack_t *ss; + register struct trapframe *regs; + int eflags; + caddr_t sg = stackgap_init(); + + regs = p->p_md.md_regs; + +#ifdef DEBUG + printf("Linux-emul(%ld): linux_rt_sigreturn(%p)\n", + (long)p->p_pid, (void *)args->ucp); +#endif + /* + * The trampoline code hands us the u_context. + * It is unsafe to keep track of it ourselves, in the event that a + * program jumps out of a signal handler. + */ + if (copyin((caddr_t)args->ucp, &uc, sizeof(uc)) != 0) + return (EFAULT); + + context = &uc.uc_mcontext; + + /* + * Check for security violations. + */ +#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) + eflags = context->sc_eflags; + /* + * XXX do allow users to change the privileged flag PSL_RF. The + * cpu sets PSL_RF in tf_eflags for faults. Debuggers should + * sometimes set it there too. tf_eflags is kept in the signal + * context during signal handling and there is no other place + * to remember it, so the PSL_RF bit may be corrupted by the + * signal handler without us knowing. Corruption of the PSL_RF + * bit at worst causes one more or one less debugger trap, so + * allowing it is fairly harmless. + */ + if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { + return(EINVAL); + } + + /* + * Don't allow users to load a valid privileged %cs. Let the + * hardware check for invalid selectors, excess privilege in + * other selectors, invalid %eip's and invalid %esp's. + */ +#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) + if (!CS_SECURE(context->sc_cs)) { + trapsignal(p, SIGBUS, T_PROTFLT); + return(EINVAL); + } + + p->p_sigstk.ss_flags &= ~SS_ONSTACK; + SIGSETOLD(p->p_sigmask, context->sc_mask); + SIG_CANTMASK(p->p_sigmask); + + /* + * Restore signal context-> + */ + /* %gs was restored by the trampoline. */ + regs->tf_fs = context->sc_fs; + regs->tf_es = context->sc_es; + regs->tf_ds = context->sc_ds; + regs->tf_edi = context->sc_edi; + regs->tf_esi = context->sc_esi; + regs->tf_ebp = context->sc_ebp; + regs->tf_ebx = context->sc_ebx; + regs->tf_edx = context->sc_edx; + regs->tf_ecx = context->sc_ecx; + regs->tf_eax = context->sc_eax; + regs->tf_eip = context->sc_eip; + regs->tf_cs = context->sc_cs; + regs->tf_eflags = eflags; + regs->tf_esp = context->sc_esp_at_signal; + regs->tf_ss = context->sc_ss; + + /* + * call sigaltstack & ignore results.. + */ + ss = stackgap_alloc(&sg, sizeof(stack_t)); + lss = &uc.uc_stack; + ss->ss_sp = lss->ss_sp; + ss->ss_size = (lss->ss_size >= LINUX_MINSIGSTKSZ && + lss->ss_size < MINSIGSTKSZ) ? MINSIGSTKSZ : lss->ss_size; + linux_to_bsd_sigaltstack(&lss->ss_flags, &ss->ss_flags); +#ifdef DEBUG + printf("Linux-emul(%ld): rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x\n", + (long)p->p_pid, ss->ss_flags, ss->ss_sp, ss->ss_size, context->sc_mask); +#endif + sasargs.ss = ss; + sasargs.oss = NULL; + (void) sigaltstack(p, &sasargs); + + return (EJUSTRETURN); +} static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) { --- sys/i386/linux/syscalls.master.orig Thu Sep 14 12:20:10 2000 +++ sys/i386/linux/syscalls.master Thu Sep 14 12:20:30 2000 @@ -253,7 +253,7 @@ 171 STD LINUX { int linux_getresgid(linux_gid_t *rgid, \ linux_gid_t *egid, linux_gid_t *sgid); } 172 STD LINUX { int linux_prctl(void); } -173 STD LINUX { int linux_rt_sigreturn(void); } +173 STD LINUX { int linux_rt_sigreturn(struct linux_ucontext *ucp); } 174 STD LINUX { int linux_rt_sigaction(int sig, \ linux_sigaction_t *act, \ linux_sigaction_t *oact, \ --- sys/sys/signal.h.orig Tue Sep 12 10:29:38 2000 +++ sys/sys/signal.h Thu Sep 14 15:22:56 2000 @@ -238,7 +238,7 @@ #define SS_ONSTACK 0x0001 /* take signal on alternate stack */ #define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ -#define MINSIGSTKSZ 8192 /* minimum allowable stack */ +#define MINSIGSTKSZ 2048 /* minimum allowable stack */ #define SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended stack size */ /* Have enough typedefs for this now. XXX */ --o0ZfoUVt4BxPQnbU-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-emulation" in the body of the message