lkml.org 
[lkml]   [1998]   [Jun]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: patch for sigaltstack
On Sun, Jun 07, 1998 at 09:00:23PM -0700, Richard Henderson wrote:
> Revert the patch and I'll give you another with this corrected.

As promised.


r~


diff -rup 2.1.105/arch/alpha/kernel/entry.S 2.1.105-rth/arch/alpha/kernel/entry.S
--- 2.1.105/arch/alpha/kernel/entry.S Mon Jun 8 00:29:53 1998
+++ 2.1.105-rth/arch/alpha/kernel/entry.S Sun Jun 7 21:53:50 1998
@@ -924,7 +924,7 @@ sys_call_table:
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 110 */
.quad sys_sigsuspend
- .quad sys_ni_syscall
+ .quad osf_sigstack
.quad sys_recvmsg
.quad sys_sendmsg
.quad alpha_ni_syscall /* 115 */
@@ -1047,7 +1047,7 @@ sys_call_table:
.quad alpha_ni_syscall
.quad sys_getpgid
.quad sys_getsid
- .quad alpha_ni_syscall /* 235 */
+ .quad sys_sigaltstack /* 235 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
diff -rup 2.1.105/arch/alpha/kernel/osf_sys.c 2.1.105-rth/arch/alpha/kernel/osf_sys.c
--- 2.1.105/arch/alpha/kernel/osf_sys.c Thu Apr 9 03:56:55 1998
+++ 2.1.105-rth/arch/alpha/kernel/osf_sys.c Mon Jun 8 10:35:15 1998
@@ -743,6 +743,50 @@ asmlinkage long osf_proplist_syscall(enu
return error;
}

+asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
+{
+ unsigned long usp = rdusp();
+ unsigned long oss_sp, oss_os;
+ int error;
+
+ if (uoss) {
+ oss_sp = current->sas_ss_sp + current->sas_ss_size;
+ oss_os = on_sig_stack(usp);
+ }
+
+ if (uss) {
+ unsigned long ss_sp;
+
+ error = -EFAULT;
+ if (get_user(ss_sp, &uss->ss_sp))
+ goto out;
+
+ /* If the current stack was set with sigaltstack, don't
+ swap stacks while we are on it. */
+ error = -EPERM;
+ if (current->sas_ss_sp && on_sig_stack(usp))
+ goto out;
+
+ /* Since we don't know the extent of the stack, and we don't
+ track onstack-ness, but rather calculate it, we must
+ presume a size. Ho hum this interface is lossy. */
+ current->sas_ss_sp = ss_sp - SIGSTKSZ;
+ current->sas_ss_size = SIGSTKSZ;
+ }
+
+ if (uoss) {
+ error = -EFAULT;
+ if (! access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))
+ || __put_user(oss_sp, &uoss->ss_sp)
+ || __put_user(oss_os, &uoss->ss_onstack))
+ goto out;
+ }
+
+ error = 0;
+out:
+ return error;
+}
+
/*
* The Linux kernel isn't good at returning values that look
* like negative longs (they are mistaken as error values).
diff -rup 2.1.105/arch/alpha/kernel/signal.c 2.1.105-rth/arch/alpha/kernel/signal.c
--- 2.1.105/arch/alpha/kernel/signal.c Thu Feb 5 14:39:40 1998
+++ 2.1.105-rth/arch/alpha/kernel/signal.c Mon Jun 8 12:01:29 1998
@@ -203,6 +203,12 @@ do_rt_sigsuspend(sigset_t *uset, size_t
}
}

+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+ return do_sigaltstack(uss, uoss, rdusp());
+}
+
/*
* Do a signal return; undo the signal stack.
*/
@@ -225,67 +231,65 @@ struct rt_sigframe
#define INSN_LDI_R0 0x201f0000
#define INSN_CALLSYS 0x00000083

-
-static void
+static long
restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
struct switch_stack *sw)
{
unsigned long usp;
- int i;
+ long i, err = 0;

- __get_user(regs->pc, &sc->sc_pc);
+ err |= __get_user(regs->pc, &sc->sc_pc);
sw->r26 = (unsigned long) ret_from_sys_call;

- __get_user(regs->r0, sc->sc_regs+0);
- __get_user(regs->r1, sc->sc_regs+1);
- __get_user(regs->r2, sc->sc_regs+2);
- __get_user(regs->r3, sc->sc_regs+3);
- __get_user(regs->r4, sc->sc_regs+4);
- __get_user(regs->r5, sc->sc_regs+5);
- __get_user(regs->r6, sc->sc_regs+6);
- __get_user(regs->r7, sc->sc_regs+7);
- __get_user(regs->r8, sc->sc_regs+8);
- __get_user(sw->r9, sc->sc_regs+9);
- __get_user(sw->r10, sc->sc_regs+10);
- __get_user(sw->r11, sc->sc_regs+11);
- __get_user(sw->r12, sc->sc_regs+12);
- __get_user(sw->r13, sc->sc_regs+13);
- __get_user(sw->r14, sc->sc_regs+14);
- __get_user(sw->r15, sc->sc_regs+15);
- __get_user(regs->r16, sc->sc_regs+16);
- __get_user(regs->r17, sc->sc_regs+17);
- __get_user(regs->r18, sc->sc_regs+18);
- __get_user(regs->r19, sc->sc_regs+19);
- __get_user(regs->r20, sc->sc_regs+20);
- __get_user(regs->r21, sc->sc_regs+21);
- __get_user(regs->r22, sc->sc_regs+22);
- __get_user(regs->r23, sc->sc_regs+23);
- __get_user(regs->r24, sc->sc_regs+24);
- __get_user(regs->r25, sc->sc_regs+25);
- __get_user(regs->r26, sc->sc_regs+26);
- __get_user(regs->r27, sc->sc_regs+27);
- __get_user(regs->r28, sc->sc_regs+28);
- __get_user(regs->gp, sc->sc_regs+29);
- __get_user(usp, sc->sc_regs+30);
+ err |= __get_user(regs->r0, sc->sc_regs+0);
+ err |= __get_user(regs->r1, sc->sc_regs+1);
+ err |= __get_user(regs->r2, sc->sc_regs+2);
+ err |= __get_user(regs->r3, sc->sc_regs+3);
+ err |= __get_user(regs->r4, sc->sc_regs+4);
+ err |= __get_user(regs->r5, sc->sc_regs+5);
+ err |= __get_user(regs->r6, sc->sc_regs+6);
+ err |= __get_user(regs->r7, sc->sc_regs+7);
+ err |= __get_user(regs->r8, sc->sc_regs+8);
+ err |= __get_user(sw->r9, sc->sc_regs+9);
+ err |= __get_user(sw->r10, sc->sc_regs+10);
+ err |= __get_user(sw->r11, sc->sc_regs+11);
+ err |= __get_user(sw->r12, sc->sc_regs+12);
+ err |= __get_user(sw->r13, sc->sc_regs+13);
+ err |= __get_user(sw->r14, sc->sc_regs+14);
+ err |= __get_user(sw->r15, sc->sc_regs+15);
+ err |= __get_user(regs->r16, sc->sc_regs+16);
+ err |= __get_user(regs->r17, sc->sc_regs+17);
+ err |= __get_user(regs->r18, sc->sc_regs+18);
+ err |= __get_user(regs->r19, sc->sc_regs+19);
+ err |= __get_user(regs->r20, sc->sc_regs+20);
+ err |= __get_user(regs->r21, sc->sc_regs+21);
+ err |= __get_user(regs->r22, sc->sc_regs+22);
+ err |= __get_user(regs->r23, sc->sc_regs+23);
+ err |= __get_user(regs->r24, sc->sc_regs+24);
+ err |= __get_user(regs->r25, sc->sc_regs+25);
+ err |= __get_user(regs->r26, sc->sc_regs+26);
+ err |= __get_user(regs->r27, sc->sc_regs+27);
+ err |= __get_user(regs->r28, sc->sc_regs+28);
+ err |= __get_user(regs->gp, sc->sc_regs+29);
+ err |= __get_user(usp, sc->sc_regs+30);
wrusp(usp);

for (i = 0; i < 31; i++)
- __get_user(sw->fp[i], sc->sc_fpregs+i);
- __get_user(sw->fp[31], &sc->sc_fpcr);
+ err |= __get_user(sw->fp[i], sc->sc_fpregs+i);
+ err |= __get_user(sw->fp[31], &sc->sc_fpcr);
+
+ return err;
}

asmlinkage void
do_sigreturn(struct sigframe *frame, struct pt_regs *regs,
struct switch_stack *sw)
{
- unsigned long ps;
sigset_t set;

/* Verify that it's a good sigcontext before using it */
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto give_sigsegv;
- if (__get_user(ps, &frame->sc.sc_ps) || ps != 8)
- goto give_sigsegv;
if (__get_user(set.sig[0], &frame->sc.sc_mask)
|| (_NSIG_WORDS > 1
&& __copy_from_user(&set.sig[1], &frame->extramask,
@@ -298,7 +302,8 @@ do_sigreturn(struct sigframe *frame, str
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);

- restore_sigcontext(&frame->sc, regs, sw);
+ if (restore_sigcontext(&frame->sc, regs, sw))
+ goto give_sigsegv;

/* Send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current))
@@ -306,22 +311,19 @@ do_sigreturn(struct sigframe *frame, str
return;

give_sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
+ send_sig(SIGSEGV, current, 1);
}

asmlinkage void
do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs,
struct switch_stack *sw)
{
- unsigned long ps;
sigset_t set;
+ stack_t st;

/* Verify that it's a good sigcontext before using it */
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto give_sigsegv;
- if (__get_user(ps, &frame->uc.uc_mcontext.sc_ps) || ps != 8)
- goto give_sigsegv;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto give_sigsegv;

@@ -331,7 +333,14 @@ do_rt_sigreturn(struct rt_sigframe *fram
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);

- restore_sigcontext(&frame->uc.uc_mcontext, regs, sw);
+ if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
+ goto give_sigsegv;
+
+ if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ goto give_sigsegv;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, rdusp());

/* Send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current))
@@ -339,8 +348,7 @@ do_rt_sigreturn(struct rt_sigframe *fram
return;

give_sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
+ send_sig(SIGSEGV, current, 1);
}


@@ -348,99 +356,113 @@ give_sigsegv:
* Set up a signal frame.
*/

-static void
+static inline void *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *)((sp - frame_size) & -32ul);
+}
+
+static long
setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
struct switch_stack *sw, unsigned long mask, unsigned long sp)
{
- long i;
+ long i, err = 0;

- __put_user(0, &sc->sc_onstack);
- __put_user(mask, &sc->sc_mask);
- __put_user(regs->pc, &sc->sc_pc);
- __put_user(8, &sc->sc_ps);
-
- __put_user(regs->r0 , sc->sc_regs+0);
- __put_user(regs->r1 , sc->sc_regs+1);
- __put_user(regs->r2 , sc->sc_regs+2);
- __put_user(regs->r3 , sc->sc_regs+3);
- __put_user(regs->r4 , sc->sc_regs+4);
- __put_user(regs->r5 , sc->sc_regs+5);
- __put_user(regs->r6 , sc->sc_regs+6);
- __put_user(regs->r7 , sc->sc_regs+7);
- __put_user(regs->r8 , sc->sc_regs+8);
- __put_user(sw->r9 , sc->sc_regs+9);
- __put_user(sw->r10 , sc->sc_regs+10);
- __put_user(sw->r11 , sc->sc_regs+11);
- __put_user(sw->r12 , sc->sc_regs+12);
- __put_user(sw->r13 , sc->sc_regs+13);
- __put_user(sw->r14 , sc->sc_regs+14);
- __put_user(sw->r15 , sc->sc_regs+15);
- __put_user(regs->r16, sc->sc_regs+16);
- __put_user(regs->r17, sc->sc_regs+17);
- __put_user(regs->r18, sc->sc_regs+18);
- __put_user(regs->r19, sc->sc_regs+19);
- __put_user(regs->r20, sc->sc_regs+20);
- __put_user(regs->r21, sc->sc_regs+21);
- __put_user(regs->r22, sc->sc_regs+22);
- __put_user(regs->r23, sc->sc_regs+23);
- __put_user(regs->r24, sc->sc_regs+24);
- __put_user(regs->r25, sc->sc_regs+25);
- __put_user(regs->r26, sc->sc_regs+26);
- __put_user(regs->r27, sc->sc_regs+27);
- __put_user(regs->r28, sc->sc_regs+28);
- __put_user(regs->gp , sc->sc_regs+29);
- __put_user(sp, sc->sc_regs+30);
- __put_user(0, sc->sc_regs+31);
+ err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
+ err |= __put_user(mask, &sc->sc_mask);
+ err |= __put_user(regs->pc, &sc->sc_pc);
+ err |= __put_user(8, &sc->sc_ps);
+
+ err |= __put_user(regs->r0 , sc->sc_regs+0);
+ err |= __put_user(regs->r1 , sc->sc_regs+1);
+ err |= __put_user(regs->r2 , sc->sc_regs+2);
+ err |= __put_user(regs->r3 , sc->sc_regs+3);
+ err |= __put_user(regs->r4 , sc->sc_regs+4);
+ err |= __put_user(regs->r5 , sc->sc_regs+5);
+ err |= __put_user(regs->r6 , sc->sc_regs+6);
+ err |= __put_user(regs->r7 , sc->sc_regs+7);
+ err |= __put_user(regs->r8 , sc->sc_regs+8);
+ err |= __put_user(sw->r9 , sc->sc_regs+9);
+ err |= __put_user(sw->r10 , sc->sc_regs+10);
+ err |= __put_user(sw->r11 , sc->sc_regs+11);
+ err |= __put_user(sw->r12 , sc->sc_regs+12);
+ err |= __put_user(sw->r13 , sc->sc_regs+13);
+ err |= __put_user(sw->r14 , sc->sc_regs+14);
+ err |= __put_user(sw->r15 , sc->sc_regs+15);
+ err |= __put_user(regs->r16, sc->sc_regs+16);
+ err |= __put_user(regs->r17, sc->sc_regs+17);
+ err |= __put_user(regs->r18, sc->sc_regs+18);
+ err |= __put_user(regs->r19, sc->sc_regs+19);
+ err |= __put_user(regs->r20, sc->sc_regs+20);
+ err |= __put_user(regs->r21, sc->sc_regs+21);
+ err |= __put_user(regs->r22, sc->sc_regs+22);
+ err |= __put_user(regs->r23, sc->sc_regs+23);
+ err |= __put_user(regs->r24, sc->sc_regs+24);
+ err |= __put_user(regs->r25, sc->sc_regs+25);
+ err |= __put_user(regs->r26, sc->sc_regs+26);
+ err |= __put_user(regs->r27, sc->sc_regs+27);
+ err |= __put_user(regs->r28, sc->sc_regs+28);
+ err |= __put_user(regs->gp , sc->sc_regs+29);
+ err |= __put_user(sp, sc->sc_regs+30);
+ err |= __put_user(0, sc->sc_regs+31);

for (i = 0; i < 31; i++)
- __put_user(sw->fp[i], sc->sc_fpregs+i);
- __put_user(0, sc->sc_fpregs+31);
- __put_user(sw->fp[31], &sc->sc_fpcr);
-
- __put_user(regs->trap_a0, &sc->sc_traparg_a0);
- __put_user(regs->trap_a1, &sc->sc_traparg_a1);
- __put_user(regs->trap_a2, &sc->sc_traparg_a2);
+ err |= __put_user(sw->fp[i], sc->sc_fpregs+i);
+ err |= __put_user(0, sc->sc_fpregs+31);
+ err |= __put_user(sw->fp[31], &sc->sc_fpcr);
+
+ err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0);
+ err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1);
+ err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2);
+
+ return err;
}

static void
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
struct pt_regs *regs, struct switch_stack * sw)
{
- unsigned long oldsp;
+ unsigned long oldsp, r26, err = 0;
struct sigframe *frame;

oldsp = rdusp();
- frame = (struct sigframe *)((oldsp - sizeof(*frame)) & -32);
-
- /* XXX: Check here if we would need to switch stacks.. */
+ frame = get_sigframe(ka, oldsp, sizeof(*frame));
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;

- setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
+ err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
if (_NSIG_WORDS > 1) {
- __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
+ err |= __copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
}

/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->ka_restorer) {
- regs->r26 = (unsigned long) ka->ka_restorer;
+ r26 = (unsigned long) ka->ka_restorer;
} else {
- __put_user(INSN_MOV_R30_R16, frame->retcode+0);
- __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
- __put_user(INSN_CALLSYS, frame->retcode+2);
+ err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
+ err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
+ err |= __put_user(INSN_CALLSYS, frame->retcode+2);
imb();
- regs->r26 = (unsigned long) frame->retcode;
+ r26 = (unsigned long) frame->retcode;
}

+ /* Check that everything was written properly. */
+ if (err)
+ goto give_sigsegv;
+
/* "Return" to the handler */
+ regs->r26 = r26;
regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
regs->r16 = sig; /* a0: signal number */
regs->r17 = 0; /* a1: exception code */
regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
wrusp((unsigned long) frame);
-
+
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
current->comm, current->pid, frame, regs->pc, regs->r26);
@@ -449,47 +471,55 @@ setup_frame(int sig, struct k_sigaction
return;

give_sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
+ if (sig == SIGSEGV)
+ force_sig(SIGSEGV, current);
+ else
+ send_sig(SIGSEGV, current, 1);
}

static void
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
{
- unsigned long oldsp;
+ unsigned long oldsp, r26, err = 0;
struct rt_sigframe *frame;

oldsp = rdusp();
- frame = (struct rt_sigframe *)((oldsp - sizeof(*frame)) & -32);
-
- /* XXX: Check here if we would need to switch stacks.. */
+ frame = get_sigframe(ka, oldsp, sizeof(*frame));
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;

- __copy_to_user(&frame->info, info, sizeof(siginfo_t));
+ err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t));

- /* Zero all bits of the ucontext besides the sigcontext. */
- __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
-
- /* Copy in the bits we actually use. */
- __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
- setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, set->sig[0], oldsp);
- __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
+ err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
+ set->sig[0], oldsp);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));

/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->ka_restorer) {
- regs->r26 = (unsigned long) ka->ka_restorer;
+ r26 = (unsigned long) ka->ka_restorer;
} else {
- __put_user(INSN_MOV_R30_R16, frame->retcode+0);
- __put_user(INSN_LDI_R0+__NR_rt_sigreturn, frame->retcode+1);
- __put_user(INSN_CALLSYS, frame->retcode+2);
+ err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
+ err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
+ frame->retcode+1);
+ err |= __put_user(INSN_CALLSYS, frame->retcode+2);
imb();
- regs->r26 = (unsigned long) frame->retcode;
+ r26 = (unsigned long) frame->retcode;
}

+ if (err)
+ goto give_sigsegv;
+
/* "Return" to the handler */
+ regs->r26 = r26;
regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
regs->r16 = sig; /* a0: signal number */
regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
@@ -504,8 +534,10 @@ setup_rt_frame(int sig, struct k_sigacti
return;

give_sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
+ if (sig == SIGSEGV)
+ force_sig(SIGSEGV, current);
+ else
+ send_sig(SIGSEGV, current, 1);
}


diff -rup 2.1.105/arch/i386/kernel/entry.S 2.1.105-rth/arch/i386/kernel/entry.S
--- 2.1.105/arch/i386/kernel/entry.S Thu Jun 4 23:45:07 1998
+++ 2.1.105-rth/arch/i386/kernel/entry.S Sun Jun 7 21:53:50 1998
@@ -546,7 +546,8 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_getcwd)
.long SYMBOL_NAME(sys_capget)
.long SYMBOL_NAME(sys_capset) /* 185 */
+ .long SYMBOL_NAME(sys_sigaltstack)

- .rept NR_syscalls-185
+ .rept NR_syscalls-186
.long SYMBOL_NAME(sys_ni_syscall)
.endr
diff -rup 2.1.105/arch/i386/kernel/signal.c 2.1.105-rth/arch/i386/kernel/signal.c
--- 2.1.105/arch/i386/kernel/signal.c Thu Apr 9 03:57:56 1998
+++ 2.1.105-rth/arch/i386/kernel/signal.c Mon Jun 8 11:59:18 1998
@@ -116,6 +116,13 @@ sys_sigaction(int sig, const struct old_
return ret;
}

+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+ struct pt_regs *regs = (struct pt_regs *) &uss;
+ return do_sigaltstack(uss, uoss, regs->esp);
+}
+

/*
* Do a signal return; undo the signal stack.
@@ -144,7 +151,7 @@ struct rt_sigframe
};


-static inline void restore_i387_hard(struct _fpstate *buf)
+static inline int restore_i387_hard(struct _fpstate *buf)
{
#ifdef __SMP__
if (current->flags & PF_USEDFPU) {
@@ -157,31 +164,33 @@ static inline void restore_i387_hard(str
}
#endif
current->flags &= ~PF_USEDFPU;
- __copy_from_user(&current->tss.i387.hard, buf, sizeof(*buf));
+ return __copy_from_user(&current->tss.i387.hard, buf, sizeof(*buf));
}

-static inline void restore_i387(struct _fpstate *buf)
+static inline int restore_i387(struct _fpstate *buf)
{
+ int err;
#ifndef CONFIG_MATH_EMULATION
- restore_i387_hard(buf);
+ err = restore_i387_hard(buf);
#else
if (boot_cpu_data.hard_math)
- restore_i387_hard(buf);
+ err = restore_i387_hard(buf);
else
- restore_i387_soft(&current->tss.i387.soft, buf);
+ err = restore_i387_soft(&current->tss.i387.soft, buf);
#endif
current->used_math = 1;
+ return err;
}

static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *peax)
{
- unsigned int tmp;
+ unsigned int tmp, err = 0;

-#define COPY(x) __get_user(regs->x, &sc->x)
+#define COPY(x) err |= __get_user(regs->x, &sc->x)

#define COPY_SEG(seg) \
- { __get_user(tmp, &sc->seg); \
+ { err |= __get_user(tmp, &sc->seg); \
if ((tmp & 0xfffc) /* not a NULL selectors */ \
&& (tmp & 0x4) != 0x4 /* not a LDT selector */ \
&& (tmp & 3) != 3) /* not a RPL3 GDT selector */ \
@@ -189,12 +198,12 @@ restore_sigcontext(struct pt_regs *regs,
regs->x##seg = tmp; }

#define COPY_SEG_STRICT(seg) \
- { __get_user(tmp, &sc->seg); \
+ { err |= __get_user(tmp, &sc->seg); \
if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \
regs->x##seg = tmp; }

#define GET_SEG(seg) \
- { __get_user(tmp, &sc->seg); \
+ { err |= __get_user(tmp, &sc->seg); \
if ((tmp & 0xfffc) /* not a NULL selectors */ \
&& (tmp & 0x4) != 0x4 /* not a LDT selector */ \
&& (tmp & 3) != 3) /* not a RPL3 GDT selector */ \
@@ -216,24 +225,23 @@ restore_sigcontext(struct pt_regs *regs,
COPY_SEG_STRICT(cs);
COPY_SEG_STRICT(ss);

- __get_user(tmp, &sc->eflags);
+ err |= __get_user(tmp, &sc->eflags);
regs->eflags = (regs->eflags & ~0x40DD5) | (tmp & 0x40DD5);
regs->orig_eax = -1; /* disable syscall checks */

- __get_user(tmp, (unsigned long *)&sc->fpstate);
+ err |= __get_user(tmp, (unsigned long *)&sc->fpstate);
if (tmp) {
struct _fpstate * buf = (struct _fpstate *) tmp;
if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
- restore_i387(buf);
+ err |= restore_i387(buf);
}

- __get_user(tmp, &sc->eax);
- return tmp;
+ err |= __get_user(*peax, &sc->eax);
+ return err;

badframe:
- lock_kernel();
- do_exit(SIGSEGV);
+ return 1;
}

asmlinkage int sys_sigreturn(unsigned long __unused)
@@ -241,6 +249,7 @@ asmlinkage int sys_sigreturn(unsigned lo
struct pt_regs *regs = (struct pt_regs *) &__unused;
struct sigframe *frame = (struct sigframe *)(regs->esp - 8);
sigset_t set;
+ int eax;

if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@@ -256,11 +265,13 @@ asmlinkage int sys_sigreturn(unsigned lo
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);

- return restore_sigcontext(regs, &frame->sc);
+ if (restore_sigcontext(regs, &frame->sc, &eax))
+ goto badframe;
+ return eax;

badframe:
- lock_kernel();
- do_exit(SIGSEGV);
+ send_sig(SIGSEGV, current, 1);
+ return 0;
}

asmlinkage int sys_rt_sigreturn(unsigned long __unused)
@@ -268,6 +279,8 @@ asmlinkage int sys_rt_sigreturn(unsigned
struct pt_regs *regs = (struct pt_regs *) &__unused;
struct rt_sigframe *frame = (struct rt_sigframe *)(regs->esp - 4);
sigset_t set;
+ stack_t st;
+ int eax;

if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@@ -280,18 +293,27 @@ asmlinkage int sys_rt_sigreturn(unsigned
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);

- return restore_sigcontext(regs, &frame->uc.uc_mcontext);
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax))
+ goto badframe;
+
+ if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs->esp);
+
+ return eax;

badframe:
- lock_kernel();
- do_exit(SIGSEGV);
+ send_sig(SIGSEGV, current, 1);
+ return 0;
}

/*
* Set up a signal frame.
*/

-static inline struct _fpstate * save_i387_hard(struct _fpstate * buf)
+static inline int save_i387_hard(struct _fpstate * buf)
{
#ifdef __SMP__
if (current->flags & PF_USEDFPU) {
@@ -308,14 +330,15 @@ static inline struct _fpstate * save_i38
}
#endif
current->tss.i387.hard.status = current->tss.i387.hard.swd;
- copy_to_user(buf, &current->tss.i387.hard, sizeof(*buf));
- return buf;
+ if (__copy_to_user(buf, &current->tss.i387.hard, sizeof(*buf)))
+ return -1;
+ return 1;
}

-static struct _fpstate * save_i387(struct _fpstate *buf)
+static int save_i387(struct _fpstate *buf)
{
if (!current->used_math)
- return NULL;
+ return 0;

/* This will cause a "finit" to be triggered by the next
attempted FPU operation by the 'current' process.
@@ -330,98 +353,116 @@ static struct _fpstate * save_i387(struc
#endif
}

-static void
+static int
setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate,
struct pt_regs *regs, unsigned long mask)
{
- unsigned int tmp;
+ int tmp, err = 0;

tmp = 0;
__asm__("movl %%gs,%w0" : "=r"(tmp): "0"(tmp));
- __put_user(tmp, (unsigned int *)&sc->gs);
+ err |= __put_user(tmp, (unsigned int *)&sc->gs);
__asm__("movl %%fs,%w0" : "=r"(tmp): "0"(tmp));
- __put_user(tmp, (unsigned int *)&sc->fs);
-
- __put_user(regs->xes, (unsigned int *)&sc->es);
- __put_user(regs->xds, (unsigned int *)&sc->ds);
- __put_user(regs->edi, &sc->edi);
- __put_user(regs->esi, &sc->esi);
- __put_user(regs->ebp, &sc->ebp);
- __put_user(regs->esp, &sc->esp);
- __put_user(regs->ebx, &sc->ebx);
- __put_user(regs->edx, &sc->edx);
- __put_user(regs->ecx, &sc->ecx);
- __put_user(regs->eax, &sc->eax);
- __put_user(current->tss.trap_no, &sc->trapno);
- __put_user(current->tss.error_code, &sc->err);
- __put_user(regs->eip, &sc->eip);
- __put_user(regs->xcs, (unsigned int *)&sc->cs);
- __put_user(regs->eflags, &sc->eflags);
- __put_user(regs->esp, &sc->esp_at_signal);
- __put_user(regs->xss, (unsigned int *)&sc->ss);
+ err |= __put_user(tmp, (unsigned int *)&sc->fs);

- __put_user(save_i387(fpstate), &sc->fpstate);
+ err |= __put_user(regs->xes, (unsigned int *)&sc->es);
+ err |= __put_user(regs->xds, (unsigned int *)&sc->ds);
+ err |= __put_user(regs->edi, &sc->edi);
+ err |= __put_user(regs->esi, &sc->esi);
+ err |= __put_user(regs->ebp, &sc->ebp);
+ err |= __put_user(regs->esp, &sc->esp);
+ err |= __put_user(regs->ebx, &sc->ebx);
+ err |= __put_user(regs->edx, &sc->edx);
+ err |= __put_user(regs->ecx, &sc->ecx);
+ err |= __put_user(regs->eax, &sc->eax);
+ err |= __put_user(current->tss.trap_no, &sc->trapno);
+ err |= __put_user(current->tss.error_code, &sc->err);
+ err |= __put_user(regs->eip, &sc->eip);
+ err |= __put_user(regs->xcs, (unsigned int *)&sc->cs);
+ err |= __put_user(regs->eflags, &sc->eflags);
+ err |= __put_user(regs->esp, &sc->esp_at_signal);
+ err |= __put_user(regs->xss, (unsigned int *)&sc->ss);
+
+ tmp = save_i387(fpstate);
+ if (tmp < 0)
+ err = 1;
+ else
+ err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);

/* non-iBCS2 extensions.. */
- __put_user(mask, &sc->oldmask);
- __put_user(current->tss.cr2, &sc->cr2);
+ err |= __put_user(mask, &sc->oldmask);
+ err |= __put_user(current->tss.cr2, &sc->cr2);
+
+ return err;
}

/*
* Determine which stack to use..
*/
-static inline unsigned long sigstack_esp(struct k_sigaction *ka, struct pt_regs * regs)
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
{
unsigned long esp;

/* Default to using normal stack */
esp = regs->esp;

+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (! on_sig_stack(esp))
+ esp = current->sas_ss_sp + current->sas_ss_size;
+ }
+
/* This is the legacy signal stack switching. */
- if ((regs->xss & 0xffff) != __USER_DS &&
- !(ka->sa.sa_flags & SA_RESTORER) &&
- ka->sa.sa_restorer)
+ else if ((regs->xss & 0xffff) != __USER_DS &&
+ !(ka->sa.sa_flags & SA_RESTORER) &&
+ ka->sa.sa_restorer) {
esp = (unsigned long) ka->sa.sa_restorer;
+ }

- return esp;
+ return (void *)((esp - frame_size) & -8ul);
}

static void setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs * regs)
{
struct sigframe *frame;
+ int err = 0;

- frame = (struct sigframe *)((sigstack_esp(ka, regs) - sizeof(*frame)) & -8);
+ frame = get_sigframe(ka, regs, sizeof(*frame));

if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto segv_and_exit;
+ goto give_sigsegv;

- __put_user((current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
+ err |= __put_user((current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32
+ ? current->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);

- setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
+ err |= setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);

if (_NSIG_WORDS > 1) {
- __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
+ err |= __copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
}

/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
- __put_user(ka->sa.sa_restorer, &frame->pretcode);
+ err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
} else {
- __put_user(frame->retcode, &frame->pretcode);
+ err |= __put_user(frame->retcode, &frame->pretcode);
/* This is popl %eax ; movl $,%eax ; int $0x80 */
- __put_user(0xb858, (short *)(frame->retcode+0));
- __put_user(__NR_sigreturn, (int *)(frame->retcode+2));
- __put_user(0x80cd, (short *)(frame->retcode+6));
+ err |= __put_user(0xb858, (short *)(frame->retcode+0));
+ err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2));
+ err |= __put_user(0x80cd, (short *)(frame->retcode+6));
}

+ if (err)
+ goto give_sigsegv;
+
/* Set up registers for signal handler */
regs->esp = (unsigned long) frame;
regs->eip = (unsigned long) ka->sa.sa_handler;
@@ -443,50 +484,60 @@ static void setup_frame(int sig, struct

return;

-segv_and_exit:
- lock_kernel();
- do_exit(SIGSEGV);
+give_sigsegv:
+ if (sig == SIGSEGV)
+ force_sig(SIGSEGV, current);
+ else
+ send_sig(SIGSEGV, current, 1);
}

static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
struct rt_sigframe *frame;
+ int err = 0;

- frame = (struct rt_sigframe *)((sigstack_esp(ka, regs) - sizeof(*frame)) & -8);
+ frame = get_sigframe(ka, regs, sizeof(*frame));

if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto segv_and_exit;
+ goto give_sigsegv;

- __put_user((current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
- __put_user(&frame->info, &frame->pinfo);
- __put_user(&frame->uc, &frame->puc);
- __copy_to_user(&frame->info, info, sizeof(*info));
-
- /* Clear all the bits of the ucontext we don't use. */
- __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
-
- setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
- regs, set->sig[0]);
- __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ err |= __put_user((current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32
+ ? current->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
+ err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->uc, &frame->puc);
+ err |= __copy_to_user(&frame->info, info, sizeof(*info));
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->esp),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
+ regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));

/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
- __put_user(ka->sa.sa_restorer, &frame->pretcode);
+ err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
} else {
- __put_user(frame->retcode, &frame->pretcode);
+ err |= __put_user(frame->retcode, &frame->pretcode);
/* This is movl $,%eax ; int $0x80 */
- __put_user(0xb8, (char *)(frame->retcode+0));
- __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1));
- __put_user(0x80cd, (short *)(frame->retcode+5));
+ err |= __put_user(0xb8, (char *)(frame->retcode+0));
+ err |= __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1));
+ err |= __put_user(0x80cd, (short *)(frame->retcode+5));
}

+ if (err)
+ goto give_sigsegv;
+
/* Set up registers for signal handler */
regs->esp = (unsigned long) frame;
regs->eip = (unsigned long) ka->sa.sa_handler;
@@ -508,9 +559,11 @@ static void setup_rt_frame(int sig, stru

return;

-segv_and_exit:
- lock_kernel();
- do_exit(SIGSEGV);
+give_sigsegv:
+ if (sig == SIGSEGV)
+ force_sig(SIGSEGV, current);
+ else
+ send_sig(SIGSEGV, current, 1);
}

/*
diff -rup 2.1.105/arch/i386/math-emu/fpu_entry.c 2.1.105-rth/arch/i386/math-emu/fpu_entry.c
--- 2.1.105/arch/i386/math-emu/fpu_entry.c Thu Feb 5 14:39:41 1998
+++ 2.1.105-rth/arch/i386/math-emu/fpu_entry.c Sun Jun 7 21:53:50 1998
@@ -677,14 +677,15 @@ void math_abort(struct info * info, unsi
#define sstatus_word() \
((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))

-void restore_i387_soft(void *s387, struct _fpstate *buf)
+int restore_i387_soft(void *s387, struct _fpstate *buf)
{
u_char *d = (u_char *)buf;
int offset, other, i, tags, regnr, tag, newtop;

RE_ENTRANT_CHECK_OFF;
FPU_verify_area(VERIFY_READ, d, 7*4 + 8*10);
- __copy_from_user(&S387->cwd, d, 7*4);
+ if (__copy_from_user(&S387->cwd, d, 7*4))
+ return -1;
RE_ENTRANT_CHECK_ON;

d += 7*4;
@@ -695,9 +696,11 @@ void restore_i387_soft(void *s387, struc

RE_ENTRANT_CHECK_OFF;
/* Copy all registers in stack order. */
- __copy_from_user(((u_char *)&S387->st_space)+offset, d, other);
+ if (__copy_from_user(((u_char *)&S387->st_space)+offset, d, other))
+ return -1;
if ( offset )
- __copy_from_user((u_char *)&S387->st_space, d+other, offset);
+ if (__copy_from_user((u_char *)&S387->st_space, d+other, offset))
+ return -1;
RE_ENTRANT_CHECK_ON;

/* The tags may need to be corrected now. */
@@ -716,10 +719,11 @@ void restore_i387_soft(void *s387, struc
}
S387->twd = tags;

+ return 0;
}


-struct _fpstate * save_i387_soft(void *s387, struct _fpstate * buf)
+int save_i387_soft(void *s387, struct _fpstate * buf)
{
u_char *d = (u_char *)buf;
int offset = (S387->ftop & 7) * 10, other = 80 - offset;
@@ -742,10 +746,12 @@ struct _fpstate * save_i387_soft(void *s

RE_ENTRANT_CHECK_OFF;
/* Copy all registers in stack order. */
- __copy_to_user(d, ((u_char *)&S387->st_space)+offset, other);
+ if (__copy_to_user(d, ((u_char *)&S387->st_space)+offset, other))
+ return -1;
if ( offset )
- __copy_to_user(d+other, (u_char *)&S387->st_space, offset);
+ if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
+ return -1
RE_ENTRANT_CHECK_ON;

- return buf;
+ return 1;
}
diff -rup 2.1.105/include/asm-alpha/signal.h 2.1.105-rth/include/asm-alpha/signal.h
--- 2.1.105/include/asm-alpha/signal.h Sat Feb 28 17:04:01 1998
+++ 2.1.105-rth/include/asm-alpha/signal.h Sun Jun 7 22:33:32 1998
@@ -76,7 +76,7 @@ typedef unsigned long sigset_t;
/*
* SA_FLAGS values:
*
- * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
+ * SA_ONSTACK indicates that a registered stack_t will be used.
* SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
* SA_RESTART flag to get restarting signals (which were the default long ago)
* SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
@@ -100,6 +100,16 @@ typedef unsigned long sigset_t;
#define SA_NOMASK SA_NODEFER
#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */

+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 4096
+#define SIGSTKSZ 16384
+
+
#ifdef __KERNEL__
/*
* These values of sa_flags are used only by the kernel as part of the
@@ -163,6 +173,15 @@ typedef struct sigaltstack {
int ss_flags;
size_t ss_size;
} stack_t;
+
+/* sigstack(2) is deprecated, and will be withdrawn in a future version
+ of the X/Open CAE Specification. Use sigaltstack instead. It is only
+ implemented here for OSF/1 compatability. */
+
+struct sigstack {
+ void *ss_sp;
+ int ss_onstack;
+};

#ifdef __KERNEL__
#include <asm/sigcontext.h>
diff -rup 2.1.105/include/asm-alpha/unistd.h 2.1.105-rth/include/asm-alpha/unistd.h
--- 2.1.105/include/asm-alpha/unistd.h Mon Jun 8 00:30:04 1998
+++ 2.1.105-rth/include/asm-alpha/unistd.h Sun Jun 7 22:33:33 1998
@@ -113,7 +113,7 @@
#define __NR_osf_old_sigblock 109 /* not implemented */
#define __NR_osf_old_sigsetmask 110 /* not implemented */
#define __NR_sigsuspend 111
-#define __NR_osf_sigstack 112 /* not implemented */
+#define __NR_osf_sigstack 112
#define __NR_recvmsg 113
#define __NR_sendmsg 114
#define __NR_osf_old_vtrace 115 /* not implemented */
@@ -205,7 +205,7 @@

#define __NR_getpgid 233
#define __NR_getsid 234
-#define __NR_osf_sigaltstack 235 /* not implemented */
+#define __NR_sigaltstack 235
#define __NR_osf_waitid 236 /* not implemented */
#define __NR_osf_priocntlset 237 /* not implemented */
#define __NR_osf_sigsendset 238 /* not implemented */
diff -rup 2.1.105/include/asm-i386/math_emu.h 2.1.105-rth/include/asm-i386/math_emu.h
--- 2.1.105/include/asm-i386/math_emu.h Sun Dec 21 03:46:06 1997
+++ 2.1.105-rth/include/asm-i386/math_emu.h Sun Jun 7 21:53:50 1998
@@ -3,8 +3,8 @@

#include <asm/sigcontext.h>

-void restore_i387_soft(void *s387, struct _fpstate *buf);
-struct _fpstate * save_i387_soft(void *s387, struct _fpstate * buf);
+int restore_i387_soft(void *s387, struct _fpstate *buf);
+int save_i387_soft(void *s387, struct _fpstate * buf);

/* This structure matches the layout of the data saved to the stack
following a device-not-present interrupt, part of it saved
diff -rup 2.1.105/include/asm-i386/signal.h 2.1.105-rth/include/asm-i386/signal.h
--- 2.1.105/include/asm-i386/signal.h Sat Feb 28 17:04:01 1998
+++ 2.1.105-rth/include/asm-i386/signal.h Sun Jun 7 21:53:50 1998
@@ -72,7 +72,7 @@ typedef unsigned long sigset_t;
/*
* SA_FLAGS values:
*
- * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
+ * SA_ONSTACK indicates that a registered stack_t will be used.
* SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
* SA_RESTART flag to get restarting signals (which were the default long ago)
* SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
@@ -96,6 +96,15 @@ typedef unsigned long sigset_t;
#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */

#define SA_RESTORER 0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192

#ifdef __KERNEL__

diff -rup 2.1.105/include/asm-i386/unistd.h 2.1.105-rth/include/asm-i386/unistd.h
--- 2.1.105/include/asm-i386/unistd.h Thu Jun 4 23:43:30 1998
+++ 2.1.105-rth/include/asm-i386/unistd.h Sun Jun 7 21:53:50 1998
@@ -191,6 +191,7 @@
#define __NR_getcwd 183
#define __NR_capget 184
#define __NR_capset 185
+#define __NR_sigaltstack 186

/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */

Only in 2.1.105/include/linux: modules
diff -rup 2.1.105/include/linux/sched.h 2.1.105-rth/include/linux/sched.h
--- 2.1.105/include/linux/sched.h Mon Jun 8 00:30:05 1998
+++ 2.1.105-rth/include/linux/sched.h Sun Jun 7 23:01:31 1998
@@ -284,6 +284,8 @@ struct task_struct {
struct signal_struct *sig;
sigset_t signal, blocked;
struct signal_queue *sigqueue, **sigqueue_tail;
+ unsigned long sas_ss_sp;
+ size_t sas_ss_size;
/* SMP state */
int has_cpu;
int processor;
@@ -365,6 +367,7 @@ struct task_struct {
/* files */ &init_files, \
/* mm */ &init_mm, \
/* signals */ &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, \
+ 0, 0, \
/* SMP */ 0,0,0,0, \
/* locks */ INIT_LOCKS \
}
@@ -480,6 +483,7 @@ extern int kill_sl(pid_t, int, int);
extern int kill_proc(pid_t, int, int);
extern int do_sigaction(int sig, const struct k_sigaction *act,
struct k_sigaction *oact);
+extern int do_sigaltstack(stack_t *ss, stack_t *oss, unsigned long sp);

extern inline int signal_pending(struct task_struct *p)
{
@@ -517,6 +521,19 @@ static inline void recalc_sigpending(str
t->sigpending = (ready != 0);
}

+/* True if we are on the alternate signal stack. */
+
+static inline int on_sig_stack(unsigned long sp)
+{
+ return (sp >= current->sas_ss_sp
+ && sp < current->sas_ss_sp + current->sas_ss_size);
+}
+
+static inline int sas_ss_flags(unsigned long sp)
+{
+ return (current->sas_ss_size == 0 ? SS_DISABLE
+ : on_sig_stack(sp) ? SS_ONSTACK : 0);
+}

extern int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
diff -rup 2.1.105/kernel/signal.c 2.1.105-rth/kernel/signal.c
--- 2.1.105/kernel/signal.c Thu Jun 4 23:43:33 1998
+++ 2.1.105-rth/kernel/signal.c Mon Jun 8 10:38:51 1998
@@ -840,6 +840,62 @@ do_sigaction(int sig, const struct k_sig
return 0;
}

+int
+do_sigaltstack (stack_t *uss, stack_t *uoss, unsigned long sp)
+{
+ stack_t oss;
+ int error;
+
+ if (uoss) {
+ oss.ss_sp = (void *) current->sas_ss_sp;
+ oss.ss_size = current->sas_ss_size;
+ oss.ss_flags = sas_ss_flags(sp);
+ }
+
+ if (uss) {
+ void *ss_sp;
+ size_t ss_size;
+ int ss_flags;
+
+ error = -EFAULT;
+ if (verify_area(VERIFY_READ, uss, sizeof(*uss))
+ || __get_user(ss_sp, &uss->ss_sp)
+ || __get_user(ss_flags, &uss->ss_flags)
+ || __get_user(ss_size, &uss->ss_size))
+ goto out;
+
+ error = -EPERM;
+ if (on_sig_stack (sp))
+ goto out;
+
+ error = -EINVAL;
+ if (ss_flags & ~SS_DISABLE)
+ goto out;
+
+ if (ss_flags & SS_DISABLE) {
+ ss_size = 0;
+ ss_sp = NULL;
+ } else {
+ error = -ENOMEM;
+ if (ss_size < MINSIGSTKSZ)
+ goto out;
+ }
+
+ current->sas_ss_sp = (unsigned long) ss_sp;
+ current->sas_ss_size = ss_size;
+ }
+
+ if (uoss) {
+ error = -EFAULT;
+ if (copy_to_user(uoss, &oss, sizeof(oss)))
+ goto out;
+ }
+
+ error = 0;
+out:
+ return error;
+}
+
#if !defined(__alpha__)
/* Alpha has its own versions with special arguments. */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu

\
 
 \ /
  Last update: 2005-03-22 13:43    [W:0.100 / U:25.628 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site