Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 14 Sep 2000 15:31:45 -0400
From:      "Sean O'Connell" <sean@stat.Duke.EDU>
To:        FreeBSD emulation <freebsd-emulation@FreeBSD.ORG>
Subject:   Quick and Dirty MFC of Andrew Gallatin's Java patches
Message-ID:  <20000914153145.V4542@stat.Duke.EDU>

next in thread | raw e-mail | index | archive | help

--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 <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 */

--o0ZfoUVt4BxPQnbU--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-emulation" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000914153145.V4542>