Re: sigaction.sa_restorer problem / new signal handling / WINE

Linus Torvalds (torvalds@transmeta.com)
Wed, 4 Feb 1998 11:39:50 -0800 (PST)


On Wed, 4 Feb 1998, Marcus Meissner wrote:
>
> While debugging a strange memorycorruption under WINE I noticed that the new
> signal handling code seems to have changed the semantics of the (well,
> obsolete, but neithertheless used by WINE) sigaction.sa_restorer field.

Ok, fixed, I think. Can some wine person test that my patch actually works
for you?

Richard, the sa_restorer overloading is dangerous, maybe we should make
sure that new-style signal handling uses a separate field after all?

Linus

-----
--- v2.1.85/linux/arch/i386/kernel/signal.c Tue Dec 30 07:58:00 1997
+++ linux/arch/i386/kernel/signal.c Wed Feb 4 11:34:29 1998
@@ -365,21 +365,33 @@
/* non-iBCS2 extensions.. */
__put_user(mask, &sc->oldmask);
__put_user(current->tss.cr2, &sc->cr2);
-}
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline unsigned long sigstack_esp(struct k_sigaction *ka, struct pt_regs * regs)
+{
+ unsigned long esp;
+
+ /* Default to using normal stack */
+ esp = regs->esp;
+
+ /* This is the legacy signal stack switching. */
+ 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;
+}

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

- frame = (struct sigframe *)((regs->esp - sizeof(*frame)) & -8);
-
- /* XXX: Check here if we need to switch stacks.. */
-
- /* This is legacy signal stack switching. */
- if ((regs->xss & 0xffff) != __USER_DS
- && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer)
- frame = (struct sigframe *) ka->sa.sa_restorer;
+ frame = (struct sigframe *)((sigstack_esp(ka, regs) - sizeof(*frame)) & -8);

if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto segv_and_exit;
@@ -441,14 +453,7 @@
{
struct rt_sigframe *frame;

- frame = (struct rt_sigframe *)((regs->esp - sizeof(*frame)) & -8);
-
- /* XXX: Check here if we need to switch stacks.. */
-
- /* This is legacy signal stack switching. */
- if ((regs->xss & 0xffff) != __USER_DS
- && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer)
- frame = (struct rt_sigframe *) ka->sa.sa_restorer;
+ frame = (struct rt_sigframe *)((sigstack_esp(ka, regs) - sizeof(*frame)) & -8);

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

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