Package: libc6 Version: 2.11.1-1 Severity: normal Tags: patch upstream Some system calls, such as mmap, take 6 arguments. Unfortunatelly, the syscall function as provided by the glibc doesn't fill the 6th argument, and actually, the system call ends up being called with the 5th argument copied in 6th position (technically, that's not what happens, as the args are shifted at the end, but well).
The attached patch /should/ work. (untested). I'm also attaching a testcase that fails on alpha because of this bug and should work once the bug is fixed. Cheers Mike -- System Information: Debian Release: squeeze/sid APT prefers unstable APT policy: (500, 'unstable'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 2.6.31-1-amd64 (SMP w/2 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages libc6 depends on: ii libc-bin 2.11.1-1 Embedded GNU C Library: Binaries ii libgcc1 1:4.5.0-4 GCC support library libc6 recommends no packages. Versions of packages libc6 suggests: ii debconf [debconf-2.0] 1.5.32 Debian configuration management sy pn glibc-doc <none> (no description available) ii locales 2.11.1-1 Embedded GNU C Library: National L -- debconf information excluded
--- ./ports/sysdeps/unix/sysv/linux/alpha/syscall.S 2008-11-26 09:02:02.000000000 +0100 +++ /tmp/syscall.S 2010-05-31 16:09:54.952364393 +0200 @@ -31,13 +31,13 @@ * * Usage: * - * long syscall(syscall_number, arg1, arg2, arg3, arg4, arg5) + * long syscall(syscall_number, arg1, arg2, arg3, arg4, arg5, arg6) * * syscall_number = the index of the system call we're invoking - * arg1-arg5 = up to 5 integer arguments to the system call + * arg1-arg6 = up to 6 integer arguments to the system call * * We need to do some arg shifting: the kernel expects the - * syscall number in v0 and the first five args in a0-a4. + * syscall number in v0 and the first six args in a0-a5. * */ @@ -60,6 +60,7 @@ mov a3, a2 mov a4, a3 mov a5, a4 + ldq a5,0(sp) /* arg6 -> a5 */ call_pal PAL_callsys /* Invoke system call */ bne a3, $error
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/syscall.h> #include <fcntl.h> static int pagesize; #if defined(SYS_mmap) || defined(SYS_mmap2) static inline void *_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { #ifdef SYS_mmap2 return (caddr_t) syscall(SYS_mmap2, addr, length, prot, flags, fd, offset / 4096); #warning mmap2 #else return (caddr_t) syscall(SYS_mmap, addr, length, prot, flags, fd, offset); #warning mmap #endif } #define mmap _mmap #endif int main(void) { char *buf; int i, fd, ret = 0; pagesize = sysconf(_SC_PAGESIZE); fd = open("/tmp/testmmap", O_CREAT | O_RDWR, 0644); ftruncate(fd, pagesize * 2); buf = mmap((void *)0, pagesize, PROT_WRITE, MAP_SHARED, fd, pagesize); if (buf == MAP_FAILED) { perror("plop"); ret = 1; goto end; } for (i = 0; i < pagesize; i++) buf[i] = (char) i; munmap(buf, pagesize); close(fd); buf = malloc(pagesize); fd = open("/tmp/testmmap", O_RDONLY); lseek(fd, pagesize, SEEK_SET); read(fd, buf, pagesize); for (i = 0; i < pagesize; i++) if (buf[i] != (char) i) { ret = 1; break; } end: close(fd); unlink("/tmp/testmmap"); printf("%s\n", ret == 0 ? "ok" : "fail"); return 0; }