[Bug libc/2007] New: mmap seg faults on marginally improper arguments

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] New: mmap seg faults on marginally improper arguments

fche at redhat dot com
mmap does not seem to like both MAP_ANONYMOUS and MAP_SHARED being set, but
instead of returning ((void*)-1)/EINVAL, it seg faults.  It should just ignore
the MAP_SHARED bit, but if it must pay attention, then it should not fault.

--
           Summary: mmap seg faults on marginally improper arguments
           Product: glibc
           Version: unspecified
            Status: NEW
          Severity: critical
          Priority: P3
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: bkorb at gnu dot org
                CC: glibc-bugs at sources dot redhat dot com
  GCC host triplet: Linux/alpha 2.6.19


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com

------- Additional Comments From decimal at us dot ibm dot com  2005-12-12 19:14 -------
Do you happen to have a simple testcase you can attach to this bug?

--


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From bkorb at gnu dot org  2005-12-12 19:57 -------
Subject: Re:  mmap seg faults on marginally improper arguments

decimal at us dot ibm dot com wrote:
> ------- Additional Comments From decimal at us dot ibm dot com  2005-12-12 19:14 -------
> Do you happen to have a simple testcase you can attach to this bug?

Not really.  Attached is a small library of text_mmap and text_munmap
that allows you to mmap a text file and always know you will not seg
fault looking for a terminating NUL byte.  Lines 162 thru 166 read:

         pNuls = mmap(
                 (void*)(((char*)pMI->txt_data) + pMI->txt_size),
                 pgsz,
                 PROT_READ|PROT_WRITE,
                 MAP_ANONYMOUS|MAP_FIXED, 0, 0 );

Add "MAP_SHARED" to the collection of flag bits and invoke text_mmap()
with the first argument naming a file that is a multiple of a page size.
The fourth struct argument points to this:

typedef struct {
     void*       txt_data;      /* text file data   */
     size_t      txt_size;      /* actual file size */
     size_t      txt_full_size; /* mmaped mem size  */
     int         txt_fd;        /* file descriptor  */
     int         txt_zero_fd;   /* fd for /dev/zero */
     int         txt_errno;     /* warning code     */
     int         txt_prot;      /* "prot" flags     */
     int         txt_flags;     /* mapping type     */
     int         txt_alloc;     /* if we malloced memory */
} tmap_info_t;

Do not initialize it before the call.  text_mmap opens the file with
the open mode being a function of the flags and protection bits.
This should be sufficient (on the few failing platforms), as long
as the file size is a multiple of the page size:

int main(int argc, char** argv) {
    tmap_info_t map_info;
    void* ptr = text_mmap(argv[1],PROT_READ|PROT_WRITE,MAP_PRIVATE,&map_info);
    text_munmap( &map_info );
    return 0;
}

========= my original email (sorry it was not included in the original bug
report) ====================

An issue in my code reveals a bug in mmap():
/lib/libc.so.6.1 Linux/alpha 2.6.13.2

 > My mapping descriptor structure shows this:
 >
 > (gdb) print *pMI
 > $2 = {txt_data = 0x2000001c000, txt_size = 8192, txt_full_size = 16384,
 >  txt_fd = 7, txt_zero_fd = -1, txt_errno = 0, txt_prot = 0, txt_flags = 0,
 >  txt_alloc = 0}
 >
 > Immediately before this call:
 >
 >        pNuls = mmap(
 >                (void*)(((char*)pMI->txt_data) + pMI->txt_size), pgsz,
 >                PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, 0, 0 );
 >
 > The address passed is:
 >
 > (gdb) print 0x2000001c000+8192
 > $5 = 0x2000001e000
 >
 > It seg faults instead of returning ((void*)-1).

So, the "|MAP_SHARED" dinkleberry is left over from the copied text
where I am mapping a real file.  Anyway, this call should either work
or return ((void*)-1).  Not seg fault.  Handling a seg fault is
painful.  This could be a kernel issue, of course, but libc is
between my code and there, so I am reporting it to you....Thanks - Bruce
/*
 * $Id: text_mmap.c,v 4.8 2005/12/08 17:54:39 bkorb Exp $
 *
 * Time-stamp:      "2005-12-05 13:40:56 bkorb"
 */

#define FILE_WRITABLE(_prt,_flg) \
        ((_prt & PROT_WRITE) && (_flg & (MAP_SHARED|MAP_PRIVATE) == MAP_SHARED))
#define MAP_FAILED_PTR ((void*)MAP_FAILED)

/*=export_func  text_mmap
 * private:
 *
 * what:  map a text file with terminating NUL
 *
 * arg:   const char*,  pzFile,  name of the file to map
 * arg:   int,          prot,    mmap protections (see mmap(2))
 * arg:   int,          flags,   mmap flags (see mmap(2))
 * arg:   tmap_info_t*, mapinfo, returned info about the mapping
 *
 * ret-type:   void*
 * ret-desc:   The mmaped data address
 *
 * doc:
 *
 * This routine will mmap a file into memory ensuring that there is at least
 * one @file{NUL} character following the file data.  It will return the
 * address where the file contents have been mapped into memory.  If there is a
 * problem, then it will return @code{MAP_FAILED} and set @file{errno}
 * appropriately.
 *
 * The named file does not exist, @code{stat(2)} will set @file{errno} as it
 * will.  If the file is not a regular file, @file{errno} will be
 * @code{EINVAL}.  At that point, @code{open(2)} is attempted with the access
 * bits set appropriately for the requested @code{mmap(2)} protections and flag
 * bits.  On failure, @file{errno} will be set according to the documentation
 * for @code{open(2)}.  If @code{mmap(2)} fails, @file{errno} will be set as
 * that routine sets it.  If @code{text_mmap} works to this point, a valid
 * address will be returned, but there may still be ``issues''.
 *
 * If the file size is not an even multiple of the system page size, then
 * @code{text_map} will return at this point and @file{errno} will be zero.
 * Otherwise, an anonymous map is attempted.  If not available, then an attempt
 * is made to @code{mmap(2)} @file{/dev/zero}.  If any of these fail, the
 * address of the file's data is returned, bug @code{no} @file{NUL} characters
 * are mapped after the end of the data.
 *
 * see: mmap(2), open(2), stat(2)
 *
 * err: Any error code issued by mmap(2), open(2), stat(2) is possible.
 *      Additionally, if the specified file is not a regular file, then
 *      errno will be set to @code{EINVAL}.
 *
 * example:
 * #include <mylib.h>
 * tmap_info_t mi;
 * int no_nul;
 * void* data = text_mmap( "file", PROT_WRITE, MAP_PRIVATE, &mi );
 * if (data == MAP_FAILED) return;
 * no_nul = (mi.txt_size == mi.txt_full_size);
 * << use the data >>
 * text_munmap( &mi );
=*/
void*
text_mmap( const char* pzFile, int prot, int flags, tmap_info_t* pMI )
{
    memset( pMI, 0, sizeof(*pMI) );
#ifdef HAVE_MMAP
    pMI->txt_zero_fd = -1;
#endif
    pMI->txt_fd = -1;

    /*
     *  Make sure we can stat the regular file.  Save the file size.
     */
    {
        struct stat sb;
        if (stat( pzFile, &sb ) != 0) {
            pMI->txt_errno = errno;
            return MAP_FAILED_PTR;
        }

        if (! S_ISREG( sb.st_mode )) {
            pMI->txt_errno = errno = EINVAL;
            return MAP_FAILED_PTR;
        }

        pMI->txt_size = sb.st_size;
    }

    /*
     *  Map mmap flags and protections into open flags and do the open.
     */
    {
        int o_flag;
        /*
         *  See if we will be updating the file.  If we can alter the memory
         *  and if we share the data and we are *not* copy-on-writing the data,
         *  then our updates will show in the file, so we must open with
         *  write access.
         */
        if (FILE_WRITABLE(prot,flags))
            o_flag = O_RDWR;
        else
            o_flag = O_RDONLY;

        /*
         *  If you're not sharing the file and you are writing to it,
         *  then don't let anyone else have access to the file.
         */
        if (((flags & MAP_SHARED) == 0) && (prot & PROT_WRITE))
            o_flag |= O_EXCL;

        pMI->txt_fd = open( pzFile, o_flag );
    }

    if (pMI->txt_fd < 0) {
        pMI->txt_errno = errno;
        return MAP_FAILED_PTR;
    }

#ifdef HAVE_MMAP /* * * * * WITH MMAP * * * * * */
    /*
     *  do the mmap.  If we fail, then preserve errno, close the file and
     *  return the failure.
     */
    pMI->txt_data = mmap( NULL, pMI->txt_size, prot, flags, pMI->txt_fd, 0 );
    if (pMI->txt_data == MAP_FAILED_PTR) {
        pMI->txt_errno = errno;
        goto fail_return;
    }

    /*
     *  Most likely, everything will turn out fine now.  The only difficult
     *  part at this point is coping with files with sizes that are a multiple
     *  of the page size.  Handling that is what this whole thing is about.
     */
    pMI->txt_zero_fd = -1;
    pMI->txt_errno   = 0;

    {
        void* pNuls;
#ifdef _SC_PAGESIZE
        size_t pgsz = sysconf(_SC_PAGESIZE);
#else
        size_t pgsz = getpagesize();
#endif
        /*
         *  Compute the pagesize rounded mapped memory size.
         *  IF this is not the same as the file size, then there are NUL's
         *  at the end of the file mapping and all is okay.
         */
        pMI->txt_full_size = (pMI->txt_size + (pgsz - 1)) & ~(pgsz - 1);
        if (pMI->txt_size != pMI->txt_full_size)
            return pMI->txt_data;

        /*
         *  Still here?  We have to append a page of NUL's
         */
        pMI->txt_full_size += pgsz;
#if defined(MAP_ANONYMOUS)
        pNuls = mmap(
                (void*)(((char*)pMI->txt_data) + pMI->txt_size),
                pgsz,
                PROT_READ|PROT_WRITE,
                MAP_ANONYMOUS|MAP_FIXED, 0, 0 );

        if (pNuls != MAP_FAILED_PTR)
            return pMI->txt_data;

        pMI->txt_errno = errno;
#endif

#if defined(HAVE_DEV_ZERO)
        pMI->txt_zero_fd = open( "/dev/zero", O_RDONLY );

        if (pMI->txt_zero_fd < 0) {
            pMI->txt_errno = errno;

        } else {
            pNuls = mmap(
                    (void*)(((char*)pMI->txt_data) + pMI->txt_size), pgsz,
                    PROT_READ, MAP_PRIVATE|MAP_FIXED, pMI->txt_zero_fd, 0 );

            if (pNuls != MAP_FAILED_PTR)
                return pMI->txt_data;

            pMI->txt_errno = errno;
            close( pMI->txt_zero_fd );
            pMI->txt_zero_fd = -1;
        }
#endif

        pMI->txt_full_size = pMI->txt_size;
    }

    {
        void* p = AGALOC( pMI->txt_size+1, "file text" );
        if (pMI->txt_data == NULL) {
            pMI->txt_errno = ENOMEM;
            goto fail_return;
        }
        memcpy( p, pMI->txt_data, pMI->txt_size );
        ((char*)p)[pMI->txt_size] = NUL;
        munmap(pMI->txt_data, pMI->txt_size );
        pMI->txt_data = p;
    }
    pMI->txt_alloc = 1;
    return pMI->txt_data;

#else /* * * * * * no HAVE_MMAP * * * * * */

    pMI->txt_data = AGALOC( pMI->txt_size+1, "file text" );
    if (pMI->txt_data == NULL) {
        pMI->txt_errno = ENOMEM;
        goto fail_return;
    }

    {
        size_t sz = pMI->txt_size;
        char*  pz = pMI->txt_data;

        while (sz > 0) {
            ssize_t rdct = read( pMI->txt_fd, pz, sz );
            if (rdct <= 0) {
                pMI->txt_errno = errno;
                fprintf( stderr, zFSErrReadFile,
                         errno, strerror( errno ), pzFile );
                free( pMI->txt_data );
                goto fail_return;
            }

            pz += rdct;
            sz -= rdct;
        }

        *pz = NUL;
    }

    /*
     *  We never need a dummy page mapped in
     */
    pMI->txt_zero_fd = -1;
    pMI->txt_errno   = 0;

    return pMI->txt_data;

#endif /* * * * * * no HAVE_MMAP * * * * * */

 fail_return:
    if (pMI->txt_fd >= 0) {
        close( pMI->txt_fd );
        pMI->txt_fd = -1;
    }
    errno = pMI->txt_errno;
    pMI->txt_data = MAP_FAILED_PTR;
    return pMI->txt_data;
}


/*=export_func  text_munmap
 * private:
 *
 * what:  unmap the data mapped in by text_mmap
 *
 * arg:   tmap_info_t*, mapinfo, info about the mapping
 *
 * ret-type:   int
 * ret-desc:   -1 or 0.  @file{errno} will have the error code.
 *
 * doc:
 *
 * This routine will unmap the data mapped in with @code{text_mmap} and close
 * the associated file descriptors opened by that function.
 *
 * see: munmap(2), close(2)
 *
 * err: Any error code issued by munmap(2) or close(2) is possible.
=*/
int
text_munmap( tmap_info_t* pMI )
{
#ifdef HAVE_MMAP
    int res = 0;
    if (pMI->txt_alloc) {
        /*
         *  IF the user has write permission and the text is not mapped private,
         *  then write back any changes.  Hopefully, nobody else has modified
         *  the file in the mean time.
         */
        if (   ((pMI->txt_prot & PROT_WRITE) != 0)
            && ((pMI->txt_flags & MAP_PRIVATE) == 0))  {

            if (lseek( pMI->txt_fd, 0, SEEK_SET) != 0)
                goto error_return;

            res = (write( pMI->txt_fd, pMI->txt_data, pMI->txt_size ) < 0)
                ? errno : 0;
        }

        AGFREE( pMI->txt_data );
        errno = res;
    } else {
        res = munmap( pMI->txt_data, pMI->txt_full_size );
    }
    if (res != 0)
        goto error_return;

    res = close( pMI->txt_fd );
    if (res != 0)
        goto error_return;

    pMI->txt_fd = -1;
    errno = 0;
    if (pMI->txt_zero_fd != -1) {
        res = close( pMI->txt_zero_fd );
        pMI->txt_zero_fd = -1;
    }

 error_return:
    pMI->txt_errno = errno;
    return res;
#else  /* HAVE_MMAP */

    errno = 0;
    /*
     *  IF the memory is writable *AND* it is not private (copy-on-write)
     *     *AND* the memory is "sharable" (seen by other processes)
     *  THEN rewrite the data.
     */
    if (   FILE_WRITABLE(pMI->txt_prot, pMI->txt_flags)
        && (lseek( pMI->txt_fd, 0, SEEK_SET ) >= 0) ) {
        write( pMI->txt_fd, pMI->txt_data, pMI->txt_size );
    }

    close( pMI->txt_fd );
    pMI->txt_fd = -1;
    pMI->txt_errno = errno;
    free( pMI->txt_data );

    return pMI->txt_errno;
#endif /* HAVE_MMAP */
}

/*
 * Local Variables:
 * mode: C
 * c-file-style: "stroustrup"
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 * end of autoopts/text_mmap.c */


--


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From drepper at redhat dot com  2005-12-23 04:31 -------
That's no test case.  Send a self-contained piece of code which can be executed.

There is no indicated whatsoever that anything is wrong in glibc.  mmap is
nothing but a simple syscall wrapper.  I'll close the bug unless we get a test
case which shows the problem.

--
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |WAITING


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From bkorb at gnu dot org  2005-12-24 16:32 -------
I do not have an Alpha platform and the problem does not exist
on my Linux/i386 platform.  I was pretty sure at the time that
I wrote this report that the cause was more likely to be in the
kernel than in glibc.  Leastwise, I was guessing that the mmap
code for Linux/Alpha was not going to be much different from
any other platform.  If that code is not any different, then some
variation in kernel behavior triggered the fault.  Is that a
kernel problem or a glibc problem?  I don't know.  I don't want
to be in the middle.



#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>

#include <stdio.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>

typedef struct {
    void*       txt_data;      /* text file data   */
    size_t      txt_size;      /* actual file size */
    size_t      txt_full_size; /* mmaped mem size  */
    int         txt_fd;        /* file descriptor  */
    int         txt_zero_fd;   /* fd for /dev/zero */
    int         txt_errno;     /* warning code     */
    int         txt_prot;      /* "prot" flags     */
    int         txt_flags;     /* mapping type     */
    int         txt_alloc;     /* if we malloced memory */
} tmap_info_t;

int
main(int argc, char** argv)
{
    {
        int  fd = open( "/tmp/FOO", O_CREAT | O_WRONLY, 0666 );
        long sz = sysconf( _SC_PAGESIZE );
        char z[ 16 ];

        if (fd < 0) exit(1);
        while (sz > 0) {
            sprintf( z, "0x%4X..", sz );
            write( fd, z, 8 );
            sz -= 8;
        }
        close(fd);
    }

    {
        tmap_info_t mi;
        void* ptr =
            text_mmap( "/tmp/FOO", PROT_READ|PROT_WRITE, MAP_PRIVATE, &mi );
        fputs( "This platform does not fail\n", stdout );
        text_munmap( &mi );
    }

    return 1;
}

--


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

Re: [Bug libc/2007] mmap seg faults on marginally improper arguments

mykii
We don't know how your text_mmap() does to work.

On Dec 24, 2005, at 8::32::56GMT+04:00, bkorb at gnu dot org wrote:

>
> ------- Additional Comments From bkorb at gnu dot org  2005-12-24  
> 16:32 -------
> I do not have an Alpha platform and the problem does not exist
> on my Linux/i386 platform.  I was pretty sure at the time that
> I wrote this report that the cause was more likely to be in the
> kernel than in glibc.  Leastwise, I was guessing that the mmap
> code for Linux/Alpha was not going to be much different from
> any other platform.  If that code is not any different, then some
> variation in kernel behavior triggered the fault.  Is that a
> kernel problem or a glibc problem?  I don't know.  I don't want
> to be in the middle.
>
>
>
> #include <sys/types.h>
> #include <sys/mman.h>
> #include <sys/stat.h>
>
> #include <stdio.h>
> #include <fcntl.h>
> #include <stdint.h>
> #include <unistd.h>
>
> typedef struct {
>     void*       txt_data;      /* text file data   */
>     size_t      txt_size;      /* actual file size */
>     size_t      txt_full_size; /* mmaped mem size  */
>     int         txt_fd;        /* file descriptor  */
>     int         txt_zero_fd;   /* fd for /dev/zero */
>     int         txt_errno;     /* warning code     */
>     int         txt_prot;      /* "prot" flags     */
>     int         txt_flags;     /* mapping type     */
>     int         txt_alloc;     /* if we malloced memory */
> } tmap_info_t;
>
> int
> main(int argc, char** argv)
> {
>     {
> int  fd = open( "/tmp/FOO", O_CREAT | O_WRONLY, 0666 );
>         long sz = sysconf( _SC_PAGESIZE );
> char z[ 16 ];
>
> if (fd < 0) exit(1);
> while (sz > 0) {
>    sprintf( z, "0x%4X..", sz );
>    write( fd, z, 8 );
>    sz -= 8;
> }
> close(fd);
>     }
>
>     {
> tmap_info_t mi;
> void* ptr =
>    text_mmap( "/tmp/FOO", PROT_READ|PROT_WRITE, MAP_PRIVATE, &mi );
> fputs( "This platform does not fail\n", stdout );
> text_munmap( &mi );
>     }
>
>     return 1;
> }
>
> --
>
>
> http://sourceware.org/bugzilla/show_bug.cgi?id=2007
>
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug, or are watching someone who is.


Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From mv at binarysec dot com  2005-12-25 17:52 -------
Subject: Re:  mmap seg faults on marginally improper arguments

We don't know how your text_mmap() does to work.

On Dec 24, 2005, at 8::32::56GMT+04:00, bkorb at gnu dot org wrote:

>
> ------- Additional Comments From bkorb at gnu dot org  2005-12-24  
> 16:32 -------
> I do not have an Alpha platform and the problem does not exist
> on my Linux/i386 platform.  I was pretty sure at the time that
> I wrote this report that the cause was more likely to be in the
> kernel than in glibc.  Leastwise, I was guessing that the mmap
> code for Linux/Alpha was not going to be much different from
> any other platform.  If that code is not any different, then some
> variation in kernel behavior triggered the fault.  Is that a
> kernel problem or a glibc problem?  I don't know.  I don't want
> to be in the middle.
>
>
>
> #include <sys/types.h>
> #include <sys/mman.h>
> #include <sys/stat.h>
>
> #include <stdio.h>
> #include <fcntl.h>
> #include <stdint.h>
> #include <unistd.h>
>
> typedef struct {
>     void*       txt_data;      /* text file data   */
>     size_t      txt_size;      /* actual file size */
>     size_t      txt_full_size; /* mmaped mem size  */
>     int         txt_fd;        /* file descriptor  */
>     int         txt_zero_fd;   /* fd for /dev/zero */
>     int         txt_errno;     /* warning code     */
>     int         txt_prot;      /* "prot" flags     */
>     int         txt_flags;     /* mapping type     */
>     int         txt_alloc;     /* if we malloced memory */
> } tmap_info_t;
>
> int
> main(int argc, char** argv)
> {
>     {
> int  fd = open( "/tmp/FOO", O_CREAT | O_WRONLY, 0666 );
>         long sz = sysconf( _SC_PAGESIZE );
> char z[ 16 ];
>
> if (fd < 0) exit(1);
> while (sz > 0) {
>    sprintf( z, "0x%4X..", sz );
>    write( fd, z, 8 );
>    sz -= 8;
> }
> close(fd);
>     }
>
>     {
> tmap_info_t mi;
> void* ptr =
>    text_mmap( "/tmp/FOO", PROT_READ|PROT_WRITE, MAP_PRIVATE, &mi );
> fputs( "This platform does not fail\n", stdout );
> text_munmap( &mi );
>     }
>
>     return 1;
> }
>
> --
>
>
> http://sourceware.org/bugzilla/show_bug.cgi?id=2007
>
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug, or are watching someone who is.




--


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From bkorb at gnu dot org  2005-12-25 18:17 -------
Subject: Re:  mmap seg faults on marginally improper arguments

The function was included in a previous message.
Fundamentally, it mmaps a given file.  If that file size is a
multiple of a page size, then it does a one page anonymous
map for the next page, thus assuring that the str*() functions
won't seg fault looking for the terminating NUL byte.
The original anonymous mapping call:

          pNuls = mmap(
                  (void*)(((char*)pMI->txt_data) + pMI->txt_size),
                  pgsz,
                  PROT_READ|PROT_WRITE,
                  MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, 0, 0 );

works fine on most all platforms.  On Linux/Alpha it seg faults.
OK responses are either successful or (void*)-1 (i.e. MAP_FAILED).
The latter is okay because anonymous and shared conflict.  So, I've
modified the code below to simply make the two calls instead
of using the library I provided before.  Be forwarned: I've only tested
the failure using my "text_mmap" function, not the following code.
"It ought to behave the same."  YMMV.

mv at binarysec dot com wrote:
> ------- Additional Comments From mv at binarysec dot com  2005-12-25 17:52 -------

>>#include <sys/types.h>
>>#include <sys/mman.h>
>>#include <sys/stat.h>
>>
>>#include <stdio.h>
>>#include <fcntl.h>
>>#include <stdint.h>
>>#include <unistd.h>
>>
>>int
>>main(int argc, char** argv)
>>{
>>    long sz = sysconf( _SC_PAGESIZE );
>>    {
>> int  fd = open( "/tmp/FOO", O_CREAT | O_WRONLY, 0666 );
>> char z[ 16 ];
>>
>> if (fd < 0) exit(1);
>> while (sz > 0) {
>>    sprintf( z, "0x%4X..", sz );
>>    write( fd, z, 8 );
>>    sz -= 8;
>> }
>> close(fd);
>>    }
>>
>>    {
 >>      int fd = open( "/tmp/FOO", O_RDONLY );
>> void* ptr = mmap( NULL, sz, fd, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0 );
 >>      (void)mmap( (void*)(((long)ptr) + sz), sz, -1,
>>                 PROT_READ|PROT_WRITE,
>>                 MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, 0, 0 );
>> fputs( "This platform does not fail\n", stdout );
>>    }
>>
>>    return 1;
>>}


--


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From mv at binarysec dot com  2005-12-25 19:01 -------
I think you have a programming error.
You can't use MAP_ANON with MAP_PRIVATE or MAP_SHARED.
MAP_ANON, MAP_PRIVATE or MAP_SHARED *must* be used distinctly.

MAP_ANON : No file
MAP_PRIVATE : Read sync
MAP_SHARED : Read sync + write sync (when you write datas in the mem map the kernel will sync asap
the mem content into the file... You can force the write operation with sync()).

When i see MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED i say to me that you miss understanding the
mmap() behavior (no offence).

And as Ulrich Drepper said mmap() is just a syscall wrapper so the return value is handled by kernel
devels so you may ask the kernel ml.

I suggest to you to make this bug INVALID.

mv-

--


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From bkorb at gnu dot org  2005-12-27 01:21 -------
Subject: Re:  mmap seg faults on marginally improper arguments

mv at binarysec dot com wrote:

> When i see MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED i say to me that you miss understanding the
> mmap() behavior (no offence).

When I see this response, it seems like the bug report was not carefully read.
I completely acknowledge the fact that the input flags are inconsistent.
The issue is whether or not it is appropriate for mmap to segfault because
of that, or if it should return ((void*)-1).  Segfaults with often incomprehensible
stack traces are much harder to figure out than an EINVAL error return.
I've fixed my code and I promise I will never make another cut-n-paste
error ever again.  ;-)  Meanwhile, it would be nice to future typo-prone
users to make the error response more friendly than a seg fault.
Thanks - Bruce


--


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From mv at binarysec dot com  2005-12-27 13:33 -------
Okay i get you. As i said a small kernel patch can be done to fix the return value. The problem is that
many free software use MAP_ANON with MAP_PRIVATE or with MAP_SHARED (Apache for example). Thus
the patch risk to prevent the good behavior of these software.
So the patch have to wait maybe the version 2.7 or 2.8 of the linux kernel.
You may ask kernel devels.

--


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From aj at suse dot de  2005-12-30 09:36 -------
Please report this to the Linux kernel folks.  Since glibc has just a wrapper,
we cannot do anything here.

--
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|WAITING                     |RESOLVED
         Resolution|                            |INVALID


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From bkorb at gnu dot org  2006-01-27 14:23 -------
I am reopening the bug for reconsideration.  It may be the case that invalid
args were not the trigger for the fault.  Consider this profile for mmap in glibc:

extern void *mmap (void *__addr, size_t __len, int __prot,
                   int __flags, int __fd, __off_t __offset) __THROW;

against this implementation (from Linux sources for alpha):

asmlinkage unsigned long
osf_mmap(unsigned long addr, unsigned long len, unsigned long prot,
         unsigned long flags, unsigned long fd, unsigned long off)

I do not know if the arguments wind up getting placed correctly anyway, but they
certainly do not match for the alpha platform.  There should be an
alpha-specific profile for the function that matches the implementation.  I
would like to know if this could be the cause of continued seg faults, even with
corrected calling flag values.  Thanks!

--
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/2007] mmap seg faults on marginally improper arguments

fche at redhat dot com
In reply to this post by fche at redhat dot com

------- Additional Comments From drepper at redhat dot com  2006-02-03 21:58 -------
THe parameter types used in the kernel are almost always different.  By design.

--
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |RESOLVED
         Resolution|                            |INVALID


http://sourceware.org/bugzilla/show_bug.cgi?id=2007

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.