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>
