Note: This is a beta release of Red Hat Bugzilla 5.0. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Also email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback here.

Bug 5820

Summary: kernel does not supply address of SIGSEGV signal in si_addr field.
Product: [Retired] Red Hat Linux Reporter: geocaris
Component: kernelAssignee: David Miller <davem>
Status: CLOSED DEFERRED QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: 6.1CC: alan
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 1999-10-11 19:30:20 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description geocaris 1999-10-11 06:24:30 UTC
The kernel does not pass the memory address which caused a
SIGSEGV signal to the signal handler. The si_addr field in
the siginfo_t structure. The field is always zero. This
mechanism is used inconjunction with mmap to detect
reads/writes to regions of memory by a process. For example,

the following program should print "hello world", but it
exits in the signal handler because the kernel passes in
the si_addr field, instead of the address which was returned
by mmap() in main().

Tom Geocaris

/////////////////////// code ///////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <signal.h>

void segv_handler( int sig, siginfo_t *info, void
*user_context );

void install_signal_handlers();

static struct sigaction old_sigsegv;

void install_signal_handlers()
{
    struct sigaction action;

    sigaction( SIGSEGV, NULL, &old_sigsegv );

    action = old_sigsegv;
    action.sa_sigaction = segv_handler;
    sigemptyset( &action.sa_mask );
    action.sa_flags |= SA_SIGINFO;
    sigaction( SIGSEGV, &action, NULL );
}

void
segv_handler( int sig, siginfo_t *info, void *user_context )
{
   printf("SEGV at %x with type %d\n", info->si_addr,
info->si_code );

   if ( info->si_addr )
       mprotect( info->si_addr, 4096, PROT_WRITE );
   else
       exit(1);
}

main()
{
    int fd;
    install_signal_handlers();

    fd = open( "/dev/zero", O_RDWR );

    if ( fd <= 0 )
    {
        printf("Cannot open zero\n");
        exit(1);
    }

    caddr_t b;

    b = (caddr_t) mmap( 0, 8192, PROT_NONE,
MAP_PRIVATE|MAP_NORESERVE|MAP_ANON, fd, 0 );

    close(fd);

    if ( b == (void *) -1 )
    {
        printf("Cannot create mapping \n" );
        exit(1);
    }

    *b = 1;
    printf( "hello world\n");
}

Comment 1 Alan Cox 2000-08-08 13:40:34 UTC
This feature should be in the 2.4 kernel.