hi, there!

On Wed, 20 Sep 2000, Antony T Curtis wrote:

> Are there any known issues with the Linux ABI on STABLE-20000828 ?
> 
> I have found that the Sun JVM 1.3 can cause FreeBSD to panic or worse,
> crash solid so that a hardware reboot is required.
> 
> Does anyone have any experiences with different Java environments on
> FreeBSD? IBM's latest completely fails to run.

Andrew Gallatin ([EMAIL PROTECTED]) has made some initial work to make
IBM JDK work under 4.0-RELEASE. You can get his patches at
http://www.cs.duke.edu/~gallatin/linux/sa_siginfo/4.0-release.diff
http://www.cs.duke.edu/~gallatin/linux/sa_siginfo/diff
(this is for -current)

Sean O'Connell ([EMAIL PROTECTED]() has made quick-and-dirty port
to -stable. I have attached his diffs.

/fjoe
--- 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 <i386/linux/linux_syscall.h>
 
+#include <sys/signal.h> /* 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 <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
+#include <sys/sysproto.h>
 #include <sys/sysent.h>
 #include <sys/imgact.h>
 #include <sys/imgact_aout.h>
@@ -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 */

Reply via email to