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

Bug#583911: libc6: syscall() doesn't support 6 args system calls on alpha



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;
}

Reply to: