[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#159633: strncpy on alpha/libc broken



package: libc6.1
version: 2.2.5-11.1
severity: serious

On lully, I have a repeatable segfault being caused by strncpy(which calls
__stxncpy).

dpkg calls strncpy to copy data from it's mmap'd buffer, into a tmp var, for
moving around.  mmap on alpha aligns the end of the data segment with a page
boundary.  Depending on the alignment of the source address passed to strncpy,
a segfault will occur inside the above function.

My guess is this is due to an optimization, trying to copy ints/words around,
instead of pure bytes.

Substituting memcpy or a for loop, allows the dpkg code to work.  This shows
that the addresses and the length are both valid, and don't step into unknown
memory.

I have dpkg compiled on lully, and it doesn't require root to see the
bug(--admindir is enough).  If you need help reproducing this, then just
respond.

In fact, here's a c program that shows the bug.  Compile with CFLAGS=-g(of
course).

==
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define LENGTH 12
#define TRAILING 2
int main(int argc, char **argv) {
        int i, fd, pagesize;
        char *data, *buf;
        pagesize = getpagesize();
        fd = open( "/dev/zero", O_RDONLY );
        if ( fd == -1 ) {
                perror( "open" );
                exit( 1 );
        }
        data = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0 );
        if ( data == MAP_FAILED ) {
                perror( "mmap" );
                exit( 1 );
        }
        buf = (char *)malloc( LENGTH );
        if ( buf == NULL ) {
                perror( "malloc" );
                exit( 1 );
        }
        for ( i = 0; i < pagesize; i++ )
                data[ i ] = i % 256;
        for ( i = 0; i < pagesize - LENGTH - TRAILING; i++ )
                memcpy( buf, data + i, LENGTH );
        for ( i = 0; i < pagesize - LENGTH - TRAILING; i++ )
                strncpy( buf, data + i, LENGTH );
        return 0;
}
==

The memcpy loop completes as expected.  The strncpy loop segfaults.  Here's
the gdb session info:

==
..
Program terminated with signal 11, Segmentation fault.
..
(gdb) bt
#0  0x200000e21e0 in __stxncpy () from /lib/libc.so.6.1
#1  0x120000a78 in main (argc=1, argv=0x11ffffc88) at bug.c:36
(gdb) f 1
#1  0x120000a78 in main (argc=1, argv=0x11ffffc88) at bug.c:36
36                      strncpy( buf, data + i, LENGTH );
(gdb) p i
$1 = 8177
==





Reply to: