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:
Embargoed:

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.