Patch for s390 kernel bug in arch/s390/kernel/signal.c: rt_sigreturn()

From: Ross Patterson (ROSSP@SS1.Reston.VMD.Sterling.COM)
Date: Tue Jul 18 2000 - 16:20:12 EST


The following note was sent to the Linux-390 list last week, identifying
a platform-specific bug in the IBM S/390 Linux port. A patch to
arch/s390/kernel/signal.c is enclosed at the bottom. Since that time,
the patch has been verified by several sites, and by the IBM S/390
kernel porting group. The patch applies to the 2.2.15 kernel, although
the problem should also exist at 2.2.14 and 2.2.16 (and the patch may
very well fit).

Can we please get this out as a 2.2.15 patch?

I'd also appreciate it if someone more familiar with the i386 kernel
memory model could confirm the reason why this same code works on that
platform. I believe it's due to having both kernel and user space
visible from within the kernel, but the code still seems wrong for the
i386 case to me.

Ross Patterson
Computer Associates, Inc. (formerly Sterling Software, Inc.)
-----Original Message-----
From: Ross Patterson
Date: Thu, July 13, 2000 18:48:00 EDT PM
To: Linux/390 Discussion List (E-mail)
Subject: Kernel bug in rt_sigreturn() syscall

Neale Ferguson and I believe we have discovered a bug in the handling of
the rt_sigreturn() syscall, present at 2.2.15 and probably all other
s390 levels. It doesn't pose any kind of security risk, but it does
result in improper behavior of some programs and (VERY) frequent
VM_GROWSDOWN ... error messages. The program that led us to this is
the open source Java implementation, Kaffe.

After much kernel diving, both source and PER tracing (God, I'd HATE to
have had to track this down on an Intel platform!), we believe the
routine sys_rt_sigreturn() in arch/s390/kernel/signal.c is in error.
Specifically, passing the address of an automatic variable ("&st") to
the do_sigaltstack() routine is incorrect, as do_sigaltstack() expects
to receive an address in user space, not kernel space. We believe the
enclosed patch will rectify the situation, although we have not yet
built a kernel with it (it DOES compile :-) ). (By judicious use of the
CP STORE command the code has been zapped and appears to work.)

The reason for posting so soon is that we'd really like the IBM kernel
folks to take a look at the code as well. It's pretty arcane - I've
been chasing this bug for two weeks now, and it only really came
together in the last few hours. The other reason is that it's a very
old bug, present in the i386 version of the same module, from which the
s390 code was cloned. I have a hard time believing it's never been
encountered over there. There is, however, an alternate routine
sys_sigreturn(), which perhaps the i386 kernel uses more heavily than
the s390 kernel. Also, with i386 the kernel and user spaces are
implemented significantly differently to s390 which means the problem
never manifests itself.

In any case, tomorrow's work will be to build a kernel with the patch
and give it (and Kaffe) a shot.

Ross Patterson
Computer Associates, Inc. (formerly Sterling Software, Inc.)

P.S. Note to kernel hackers: The signal in question is SIGVTALRM, which
     Kaffe uses to decide when an internal-thread's timeslice has
     expired. strace proved invaluable in locating the general area of
     the problem (I'd have never looked at the realtime signal code, as
     SIGVTALRM is below SIGRTMIN), but PERing the kernel in fault.c and
     signal.c was what made everything clear. RAP
------------------ Start of included file SIGNAL DIFF A1 ------------------
*** linux-2.2.15/arch/s390/kernel/signal.c.ORIG Thu Jun 22 13:45:02 2000
--- linux-2.2.15/arch/s390/kernel/signal.c Thu Jul 13 17:06:48 2000
***************
*** 235,245 ****

          if (sigreturn_common(regs,sizeof(rt_sigframe)))
                          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->gprs[15]);
          return regs->gprs[2];

  badframe:
--- 235,243 ----

          if (sigreturn_common(regs,sizeof(rt_sigframe)))
                          goto badframe;
          /* It is more difficult to avoid calling this function than to
             call it and ignore errors. */
! do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
          return regs->gprs[2];

  badframe:
------------------ End of included file SIGNAL DIFF A1 ------------------
--------------------- Note End -------------------

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Jul 23 2000 - 21:00:11 EST