Bug 836508 - Segmentation fault after receiving SIGHUP signal in i386 compatible mode
Summary: Segmentation fault after receiving SIGHUP signal in i386 compatible mode
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Red Hat Enterprise Linux 5
Classification: Red Hat
Component: kernel
Version: 5.8
Hardware: x86_64
OS: Linux
unspecified
urgent
Target Milestone: rc
: ---
Assignee: Red Hat Kernel Manager
QA Contact: Red Hat Kernel QE team
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2012-06-29 10:07 UTC by bolt liu
Modified: 2012-06-29 12:18 UTC (History)
0 users

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2012-06-29 12:18:35 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
segfault.c (674 bytes, application/octet-stream)
2012-06-29 10:07 UTC, bolt liu
no flags Details

Description bolt liu 2012-06-29 10:07:11 UTC
Created attachment 595249 [details]
segfault.c

Description of problem:

I have a simple program(see it in attachment) which installs a signal handler for SIGHUP, however, it will get segmentation fault after receiving SIGHUP signal. the program is compiled for i386, and the OS is x86-64.

it will not fail if the array size is 2048.


Version-Release number of selected component (if applicable):
2.6.18-308.1.1

How reproducible:
100%


Steps to Reproduce:
1. compile the segfault.c using 32-bit gcc (gcc version 4.1.2 20071124 (Red Hat 4.1.2-42))
2. run the program in the 64-bit Linux kernel 2.6.18-308.1.1
3. send the SIGNUP signal to the process
  
Actual results:
get Segmentation fault, dmesg shows:
bad[3487]: segfault at 0000000000000003 rip 0000000000000003 rsp 00000000ffd3b8b0 error 14

Expected results:
the process continue to run

Additional info:
1. all the other applications, libs are 32-bit, only the kernel is 64-bit,
   the kernel is installed with --ignorearch

Comment 1 Jes Sorensen 2012-06-29 12:18:35 UTC
I doubt the kernel is at fault here.

The man page for sigaction has the following snippet:

       The sigaction structure is defined as something like:

           struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };

       On  some  architectures  a  union  is  involved:  do not assign to both
       sa_handler and sa_sigaction.

While your code does this:

  int main(int argc, char **argv)
  {
  #ifdef GOOD
      char large[2048];
  #else
      char large[2000];
  #endif
      struct sigaction sig_action;
      sig_action.sa_handler = signalHandler;
      sigemptyset(&sig_action.sa_mask);

Since you allocate the struct sigaction on the stack and you only clear
sa_handler and sa_flags in the setup, you end up with whatever was previous
in memory for sa_sigaction, sa_mask, and sa_restorer.

Changing the size of the array just moves things arround so you probably
end up hitting memory that was zeroed out by chance.

Try memset()'ing the struct sig_action first - that ought to fix it.

Regards,
Jes


Note You need to log in before you can comment on or make changes to this bug.