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: