about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/unix/sysv/linux/i386/setegid.c28
-rw-r--r--sysdeps/unix/sysv/linux/i386/seteuid.c28
-rw-r--r--sysdeps/unix/sysv/linux/i386/setgid.c33
-rw-r--r--sysdeps/unix/sysv/linux/i386/setregid.c32
-rw-r--r--sysdeps/unix/sysv/linux/i386/setresgid.c34
-rw-r--r--sysdeps/unix/sysv/linux/i386/setresuid.c34
-rw-r--r--sysdeps/unix/sysv/linux/i386/setreuid.c32
-rw-r--r--sysdeps/unix/sysv/linux/i386/setuid.c33
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h42
-rw-r--r--sysdeps/unix/sysv/linux/ia64/sysdep.h46
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h30
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h30
-rw-r--r--sysdeps/unix/sysv/linux/setegid.c28
-rw-r--r--sysdeps/unix/sysv/linux/seteuid.c30
-rw-r--r--sysdeps/unix/sysv/linux/setgid.c53
-rw-r--r--sysdeps/unix/sysv/linux/setregid.c53
-rw-r--r--sysdeps/unix/sysv/linux/setresgid.c54
-rw-r--r--sysdeps/unix/sysv/linux/setresuid.c54
-rw-r--r--sysdeps/unix/sysv/linux/setreuid.c53
-rw-r--r--sysdeps/unix/sysv/linux/setuid.c52
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c55
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c57
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/sysdep.h9
26 files changed, 689 insertions, 215 deletions
diff --git a/sysdeps/unix/sysv/linux/i386/setegid.c b/sysdeps/unix/sysv/linux/i386/setegid.c
index fcd6cf1827..b8682e3681 100644
--- a/sysdeps/unix/sysv/linux/i386/setegid.c
+++ b/sysdeps/unix/sysv/linux/i386/setegid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1995-1998,2000,2002,2003,2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -22,6 +22,7 @@
 
 #include <sysdep.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
 
 
 #ifdef __NR_setresgid
@@ -32,10 +33,17 @@ int
 setegid (gid)
      gid_t gid;
 {
+  int result;
+
+  if (gid == (gid_t) ~0)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
 #if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (setresgid32, 3, -1, gid, -1);
+  result = INLINE_SYSCALL (setresgid32, 3, -1, gid, -1);
 #else
-  int result;
   /* First try the syscall.  */
 # ifdef __NR_setresgid
   result = __setresgid (-1, gid, -1);
@@ -49,8 +57,20 @@ setegid (gid)
        equal to the real user ID, making it impossible to switch back.  */
 # endif
     result = __setregid (-1, gid);
+#endif
 
-  return result;
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setresgid32;
+      cmd.id[0] = -1;
+      cmd.id[1] = gid;
+      cmd.id[2] = -1;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
 #endif
+
+  return result;
 }
 libc_hidden_def (setegid)
diff --git a/sysdeps/unix/sysv/linux/i386/seteuid.c b/sysdeps/unix/sysv/linux/i386/seteuid.c
index 87e348a646..0abdac832f 100644
--- a/sysdeps/unix/sysv/linux/i386/seteuid.c
+++ b/sysdeps/unix/sysv/linux/i386/seteuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -22,6 +22,7 @@
 
 #include <sysdep.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
 
 
 #ifdef __NR_setresuid
@@ -31,10 +32,17 @@ extern int __setresuid (uid_t ruid, uid_t euid, uid_t suid);
 int
 seteuid (uid_t uid)
 {
+  int result;
+
+  if (uid == (uid_t) ~0)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
 #if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (setresuid32, 3, -1, uid, -1);
+  result = INLINE_SYSCALL (setresuid32, 3, -1, uid, -1);
 #else
-  int result;
   /* First try the syscall.  */
 # ifdef __NR_setresuid
   result = __setresuid (-1, uid, -1);
@@ -48,8 +56,20 @@ seteuid (uid_t uid)
        equal to the real user ID, making it impossible to switch back.  */
 # endif
     result = __setreuid (-1, uid);
+#endif
 
-  return result;
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setresuid32;
+      cmd.id[0] = -1;
+      cmd.id[1] = uid;
+      cmd.id[2] = -1;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
 #endif
+
+  return result;
 }
 libc_hidden_def (seteuid)
diff --git a/sysdeps/unix/sysv/linux/i386/setgid.c b/sysdeps/unix/sysv/linux/i386/setgid.c
index 1fdca94064..17bfc3e58a 100644
--- a/sysdeps/unix/sysv/linux/i386/setgid.c
+++ b/sysdeps/unix/sysv/linux/i386/setgid.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2003, 2004
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -26,6 +27,8 @@
 #include <linux/posix_types.h>
 
 #include "kernel-features.h"
+#include <pthread-functions.h>
+
 
 #ifdef __NR_setgid32
 # if __ASSUME_32BITUIDS == 0
@@ -38,18 +41,21 @@ extern int __libc_missing_32bit_uids;
 int
 __setgid (gid_t gid)
 {
+  int result;
+
 #if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (setgid32, 1, gid);
+  result = INLINE_SYSCALL (setgid32, 1, gid);
 #else
 # ifdef __NR_setgid32
   if (__libc_missing_32bit_uids <= 0)
     {
-      int result;
       int saved_errno = errno;
 
       result = INLINE_SYSCALL (setgid32, 1, gid);
 
-      if (result == 0 || errno != ENOSYS)
+      if (result == 0)
+	goto out;
+      if (errno != ENOSYS)
 	return result;
 
       __set_errno (saved_errno);
@@ -64,7 +70,24 @@ __setgid (gid_t gid)
       return -1;
     }
 
-  return INLINE_SYSCALL (setgid, 1, gid);
+  result = INLINE_SYSCALL (setgid, 1, gid);
+# ifdef __NR_setgid32
+ out:
+# endif
+#endif
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setgid32;
+      cmd.id[0] = gid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
 #endif
+
+  return result;
 }
+#ifndef __setgid
 weak_alias (__setgid, setgid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/setregid.c b/sysdeps/unix/sysv/linux/i386/setregid.c
index be1d73cb99..f883497fae 100644
--- a/sysdeps/unix/sysv/linux/i386/setregid.c
+++ b/sysdeps/unix/sysv/linux/i386/setregid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,7 @@
 
 #include <linux/posix_types.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
 
 
 #ifdef __NR_setregid32
@@ -38,18 +39,21 @@ extern int __libc_missing_32bit_uids;
 int
 __setregid (gid_t rgid, gid_t egid)
 {
+  int result;
+
 #if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (setregid32, 2, rgid, egid);
+  result = INLINE_SYSCALL (setregid32, 2, rgid, egid);
 #else
 # ifdef __NR_setregid32
   if (__libc_missing_32bit_uids <= 0)
     {
-      int result;
       int saved_errno = errno;
 
       result = INLINE_SYSCALL (setregid32, 2, rgid, egid);
 
-      if (result == 0 || errno != ENOSYS)
+      if (result == 0)
+	goto out;
+      if (errno != ENOSYS)
 	return result;
 
       __set_errno (saved_errno);
@@ -63,7 +67,25 @@ __setregid (gid_t rgid, gid_t egid)
       return -1;
     }
 
-  return INLINE_SYSCALL (setregid, 2, rgid, egid);
+  result = INLINE_SYSCALL (setregid, 2, rgid, egid);
+# ifdef __NR_setregid32
+ out:
+# endif
 #endif
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setregid32;
+      cmd.id[0] = rgid;
+      cmd.id[1] = egid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
 }
+#ifndef __setregid
 weak_alias (__setregid, setregid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/setresgid.c b/sysdeps/unix/sysv/linux/i386/setresgid.c
index 414a58b07e..ee782e49f3 100644
--- a/sysdeps/unix/sysv/linux/i386/setresgid.c
+++ b/sysdeps/unix/sysv/linux/i386/setresgid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
+
 
 #ifdef __NR_setresgid
 
@@ -39,17 +41,20 @@ extern int __libc_missing_32bit_uids;
 int
 __setresgid (gid_t rgid, gid_t egid, gid_t sgid)
 {
+  int result;
+
 # if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid);
+  result = INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid);
 # else
 #  ifdef __NR_setresgid32
   if (__libc_missing_32bit_uids <= 0)
     {
-      int result;
       int saved_errno = errno;
 
       result = INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid);
-      if (result == 0 || errno != ENOSYS)
+      if (result == 0)
+	goto out;
+      if (errno != ENOSYS)
 	return result;
 
       __set_errno (saved_errno);
@@ -65,11 +70,30 @@ __setresgid (gid_t rgid, gid_t egid, gid_t sgid)
       return -1;
     }
 
-  return INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid);
+  result = INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid);
+#  ifdef __NR_setresgid32
+ out:
+#  endif
 # endif
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setresgid32;
+      cmd.id[0] = rgid;
+      cmd.id[1] = egid;
+      cmd.id[2] = sgid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
 }
 libc_hidden_def (__setresgid)
+#ifndef __setresgid
 weak_alias (__setresgid, setresgid)
+#endif
 
 #else
 
diff --git a/sysdeps/unix/sysv/linux/i386/setresuid.c b/sysdeps/unix/sysv/linux/i386/setresuid.c
index 537fb7995b..66e5a1c0c1 100644
--- a/sysdeps/unix/sysv/linux/i386/setresuid.c
+++ b/sysdeps/unix/sysv/linux/i386/setresuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
+
 
 #ifdef __NR_setresuid
 
@@ -39,17 +41,20 @@ extern int __libc_missing_32bit_uids;
 int
 __setresuid (uid_t ruid, uid_t euid, uid_t suid)
 {
+  int result;
+
 # if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid);
+  result = INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid);
 # else
 #  ifdef __NR_setresuid32
   if (__libc_missing_32bit_uids <= 0)
     {
-      int result;
       int saved_errno = errno;
 
       result = INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid);
-      if (result == 0 || errno != ENOSYS)
+      if (result == 0)
+	goto out;
+      if (errno != ENOSYS)
 	return result;
 
       __set_errno (saved_errno);
@@ -65,11 +70,30 @@ __setresuid (uid_t ruid, uid_t euid, uid_t suid)
       return -1;
     }
 
-  return INLINE_SYSCALL (setresuid, 3, ruid, euid, suid);
+  result = INLINE_SYSCALL (setresuid, 3, ruid, euid, suid);
+#  ifdef __NR_setresuid32
+ out:
+#  endif
 # endif
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setresuid32;
+      cmd.id[0] = ruid;
+      cmd.id[1] = euid;
+      cmd.id[2] = suid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
 }
 libc_hidden_def (__setresuid)
+#ifndef __setresuid
 weak_alias (__setresuid, setresuid)
+#endif
 
 #else
 
diff --git a/sysdeps/unix/sysv/linux/i386/setreuid.c b/sysdeps/unix/sysv/linux/i386/setreuid.c
index 2aadf7437f..1e1bfcf0d4 100644
--- a/sysdeps/unix/sysv/linux/i386/setreuid.c
+++ b/sysdeps/unix/sysv/linux/i386/setreuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,7 @@
 
 #include <linux/posix_types.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
 
 
 #ifdef __NR_setreuid32
@@ -38,18 +39,21 @@ extern int __libc_missing_32bit_uids;
 int
 __setreuid (uid_t ruid, uid_t euid)
 {
+  int result;
+
 #if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (setreuid32, 2, ruid, euid);
+  result = INLINE_SYSCALL (setreuid32, 2, ruid, euid);
 #else
 # ifdef __NR_setreuid32
   if (__libc_missing_32bit_uids <= 0)
     {
-      int result;
       int saved_errno = errno;
 
       result = INLINE_SYSCALL (setreuid32, 2, ruid, euid);
 
-      if (result == 0 || errno != ENOSYS)
+      if (result == 0)
+	goto out;
+      if (errno != ENOSYS)
 	return result;
 
       __set_errno (saved_errno);
@@ -63,7 +67,25 @@ __setreuid (uid_t ruid, uid_t euid)
       return -1;
     }
 
-  return INLINE_SYSCALL (setreuid, 2, ruid, euid);
+  result = INLINE_SYSCALL (setreuid, 2, ruid, euid);
+# ifdef __NR_setreuid32
+ out:
+# endif
 #endif
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setreuid32;
+      cmd.id[0] = ruid;
+      cmd.id[1] = euid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
 }
+#ifndef __setreuid
 weak_alias (__setreuid, setreuid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/setuid.c b/sysdeps/unix/sysv/linux/i386/setuid.c
index 69bf42596f..a11fb7f60c 100644
--- a/sysdeps/unix/sysv/linux/i386/setuid.c
+++ b/sysdeps/unix/sysv/linux/i386/setuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,8 @@
 
 #include <linux/posix_types.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
+
 
 #ifdef __NR_setuid32
 # if __ASSUME_32BITUIDS == 0
@@ -37,8 +39,10 @@ extern int __libc_missing_32bit_uids;
 int
 __setuid (uid_t uid)
 {
-#if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (setuid32, 1, uid);
+  int result;
+
+#if __ASSUME_32BITUIDS > 0 && defined __NR_setuid32
+  result = INLINE_SYSCALL (setuid32, 1, uid);
 #else
 # ifdef __NR_setuid32
   if (__libc_missing_32bit_uids <= 0)
@@ -47,7 +51,9 @@ __setuid (uid_t uid)
       int saved_errno = errno;
 
       result = INLINE_SYSCALL (setuid32, 1, uid);
-      if (result == 0 || errno != ENOSYS)
+      if (result == 0)
+	goto out;
+      if (errno != ENOSYS)
 	return result;
 
       __set_errno (saved_errno);
@@ -62,7 +68,24 @@ __setuid (uid_t uid)
       return -1;
     }
 
-  return INLINE_SYSCALL (setuid, 1, uid);
+  result = INLINE_SYSCALL (setuid, 1, uid);
+# ifdef __NR_setuid32
+ out:
+# endif
+#endif
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setuid32;
+      cmd.id[0] = uid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
 #endif
+
+  return result;
 }
+#ifndef __setuid
 weak_alias (__setuid, setuid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index 79ad72abff..8845e46157 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 1992,1993,1995-2000,2002,2003 Free Software Foundation, Inc.
+/* Copyright (C) 1992,1993,1995-2000,2002,2003,2004
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995.
 
@@ -343,7 +344,10 @@ asm (".L__X'%ebx = 1\n\t"
 /* Define a macro which expands inline into the wrapper code for a system
    call.  This use is for internal calls that do not need to handle errors
    normally.  It will never touch errno.  This returns just what the kernel
-   gave back.  */
+   gave back.
+
+   The _NCS variant allows non-constant syscall numbers but it is not
+   possible to use more than four parameters.  */
 #undef INTERNAL_SYSCALL
 #ifdef I386_USE_SYSENTER
 # ifdef SHARED
@@ -360,6 +364,18 @@ asm (".L__X'%ebx = 1\n\t"
     : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))		      \
       ASMFMT_##nr(args) : "memory", "cc");				      \
     (int) resultvar; })
+#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+  ({									      \
+    register unsigned int resultvar;					      \
+    EXTRAVAR_##nr							      \
+    asm volatile (							      \
+    LOADARGS_##nr							      \
+    "call *%%gs:%P2\n\t"						      \
+    RESTOREARGS_##nr							      \
+    : "=a" (resultvar)							      \
+    : "0" (name), "i" (offsetof (tcbhead_t, sysinfo))			      \
+      ASMFMT_##nr(args) : "memory", "cc");				      \
+    (int) resultvar; })
 # else
 #  define INTERNAL_SYSCALL(name, err, nr, args...) \
   ({									      \
@@ -373,6 +389,17 @@ asm (".L__X'%ebx = 1\n\t"
     : "=a" (resultvar)							      \
     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");		      \
     (int) resultvar; })
+#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+  ({									      \
+    register unsigned int resultvar;					      \
+    EXTRAVAR_##nr							      \
+    asm volatile (							      \
+    LOADARGS_##nr							      \
+    "call *_dl_sysinfo\n\t"						      \
+    RESTOREARGS_##nr							      \
+    : "=a" (resultvar)							      \
+    : "0" (name) ASMFMT_##nr(args) : "memory", "cc");			      \
+    (int) resultvar; })
 # endif
 #else
 # define INTERNAL_SYSCALL(name, err, nr, args...) \
@@ -387,6 +414,17 @@ asm (".L__X'%ebx = 1\n\t"
     : "=a" (resultvar)							      \
     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");		      \
     (int) resultvar; })
+# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+  ({									      \
+    register unsigned int resultvar;					      \
+    EXTRAVAR_##nr							      \
+    asm volatile (							      \
+    LOADARGS_##nr							      \
+    "int $0x80\n\t"							      \
+    RESTOREARGS_##nr							      \
+    : "=a" (resultvar)							      \
+    : "0" (name) ASMFMT_##nr(args) : "memory", "cc");			      \
+    (int) resultvar; })
 #endif
 
 #undef INTERNAL_SYSCALL_DECL
diff --git a/sysdeps/unix/sysv/linux/ia64/sysdep.h b/sysdeps/unix/sysv/linux/ia64/sysdep.h
index 0868ad50ef..0ebfc56fdd 100644
--- a/sysdeps/unix/sysv/linux/ia64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/ia64/sysdep.h
@@ -199,33 +199,33 @@
 
 #ifdef IA64_USE_NEW_STUB
 
-#define DO_INLINE_SYSCALL(name, nr, args...)					\
-    LOAD_ARGS_##nr (args)							\
-    register long _r8 __asm ("r8");						\
-    register long _r10 __asm ("r10");						\
-    register long _r15 __asm ("r15") = __NR_##name;				\
-    register void *_b7 __asm ("b7") = ((tcbhead_t *) __thread_self)->private;	\
-    long _retval;								\
-    LOAD_REGS_##nr								\
-    /*										\
-     * Don't specify any unwind info here.  We mark ar.pfs as			\
-     * clobbered.  This will force the compiler to save ar.pfs			\
-     * somewhere and emit appropriate unwind info for that save.		\
-     */										\
-    __asm __volatile ("br.call.sptk.many b6=%0;;\n"				\
-		      : "=b"(_b7), "=r" (_r8), "=r" (_r10), "=r" (_r15)		\
-			ASM_OUTARGS_##nr					\
-		      : "0" (_b7), "3" (_r15) ASM_ARGS_##nr			\
-		      : "memory", "ar.pfs" ASM_CLOBBERS_##nr);			\
+# define DO_INLINE_SYSCALL(name, nr, args...)				      \
+    LOAD_ARGS_##nr (args)						      \
+    register long _r8 __asm ("r8");					      \
+    register long _r10 __asm ("r10");					      \
+    register long _r15 __asm ("r15") = name;				      \
+    register void *_b7 __asm ("b7") = ((tcbhead_t *) __thread_self)->private; \
+    long _retval;							      \
+    LOAD_REGS_##nr							      \
+    /*									      \
+     * Don't specify any unwind info here.  We mark ar.pfs as		      \
+     * clobbered.  This will force the compiler to save ar.pfs		      \
+     * somewhere and emit appropriate unwind info for that save.	      \
+     */									      \
+    __asm __volatile ("br.call.sptk.many b6=%0;;\n"			      \
+		      : "=b"(_b7), "=r" (_r8), "=r" (_r10), "=r" (_r15)	      \
+			ASM_OUTARGS_##nr				      \
+		      : "0" (_b7), "3" (_r15) ASM_ARGS_##nr		      \
+		      : "memory", "ar.pfs" ASM_CLOBBERS_##nr);		      \
     _retval = _r8;
 
 #else /* !IA64_USE_NEW_STUB */
 
-#define DO_INLINE_SYSCALL(name, nr, args...)			\
+# define DO_INLINE_SYSCALL(name, nr, args...)			\
     LOAD_ARGS_##nr (args)					\
     register long _r8 asm ("r8");				\
     register long _r10 asm ("r10");				\
-    register long _r15 asm ("r15") = __NR_##name;		\
+    register long _r15 asm ("r15") = name;			\
     long _retval;						\
     LOAD_REGS_##nr						\
     __asm __volatile (BREAK_INSN (__BREAK_SYSCALL)		\
@@ -240,7 +240,7 @@
 #undef INLINE_SYSCALL
 #define INLINE_SYSCALL(name, nr, args...)	\
   ({						\
-    DO_INLINE_SYSCALL(name, nr, args)		\
+    DO_INLINE_SYSCALL(__NR_##name, nr, args)	\
     if (_r10 == -1)				\
       {						\
 	__set_errno (_retval);			\
@@ -252,11 +252,13 @@
 #define INTERNAL_SYSCALL_DECL(err) long int err
 
 #undef INTERNAL_SYSCALL
-#define INTERNAL_SYSCALL(name, err, nr, args...)	\
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...)	\
   ({							\
     DO_INLINE_SYSCALL(name, nr, args)			\
     err = _r10;						\
     _retval; })
+#define INTERNAL_SYSCALL(name, err, nr, args...)	\
+  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
 
 #undef INTERNAL_SYSCALL_ERROR_P
 #define INTERNAL_SYSCALL_ERROR_P(val, err)	(err == -1)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
index 269b4dd531..2ee3e60229 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
@@ -79,7 +79,7 @@
 # define INTERNAL_SYSCALL_DECL(err) long int err
 
 # undef INTERNAL_SYSCALL
-# define INTERNAL_SYSCALL(name, err, nr, args...)			\
+# define INTERNAL_SYSCALL_NCS(name, err, nr, args...)			\
   ({									\
     register long int r0  __asm__ ("r0");				\
     register long int r3  __asm__ ("r3");				\
@@ -104,6 +104,8 @@
     err = r0;								\
     (int) r3;								\
   })
+# define INTERNAL_SYSCALL(name, err, nr, args...) \
+  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
 
 # undef INTERNAL_SYSCALL_ERROR_P
 # define INTERNAL_SYSCALL_ERROR_P(val, err) \
@@ -113,48 +115,48 @@
 # define INTERNAL_SYSCALL_ERRNO(val, err)     (val)
 
 # define LOADARGS_0(name, dummy) \
-	r0 = __NR_##name
+	r0 = name
 # define LOADARGS_1(name, __arg1) \
 	long int arg1 = (long int) (__arg1);	\
 	LOADARGS_0(name, 0); \
-	extern void __illegally_sized_syscall_##name##_arg1 (void); \
+	extern void __illegally_sized_syscall_arg1 (void); \
 	if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 4) \
-	  __illegally_sized_syscall_##name##_arg1 (); \
+	  __illegally_sized_syscall_arg1 (); \
 	r3 = arg1
 # define LOADARGS_2(name, __arg1, __arg2) \
 	long int arg2 = (long int) (__arg2); \
 	LOADARGS_1(name, __arg1); \
-	extern void __illegally_sized_syscall_##name##_arg2 (void); \
+	extern void __illegally_sized_syscall_arg2 (void); \
 	if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 4) \
-	  __illegally_sized_syscall_##name##_arg2 (); \
+	  __illegally_sized_syscall_arg2 (); \
 	r4 = arg2
 # define LOADARGS_3(name, __arg1, __arg2, __arg3) \
 	long int arg3 = (long int) (__arg3); \
 	LOADARGS_2(name, __arg1, __arg2); \
-	extern void __illegally_sized_syscall_##name##_arg3 (void); \
+	extern void __illegally_sized_syscall_arg3 (void); \
 	if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 4) \
-	  __illegally_sized_syscall_##name##_arg3 (); \
+	  __illegally_sized_syscall_arg3 (); \
 	r5 = arg3
 # define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
 	long int arg4 = (long int) (__arg4); \
 	LOADARGS_3(name, __arg1, __arg2, __arg3); \
-	extern void __illegally_sized_syscall_##name##_arg4 (void); \
+	extern void __illegally_sized_syscall_arg4 (void); \
 	if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 4) \
-	  __illegally_sized_syscall_##name##_arg4 (); \
+	  __illegally_sized_syscall_arg4 (); \
 	r6 = arg4
 # define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
 	long int arg5 = (long int) (__arg5); \
 	LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
-	extern void __illegally_sized_syscall_##name##_arg5 (void); \
+	extern void __illegally_sized_syscall_arg5 (void); \
 	if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 4) \
-	  __illegally_sized_syscall_##name##_arg5 (); \
+	  __illegally_sized_syscall_arg5 (); \
 	r7 = arg5
 # define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
 	long int arg6 = (long int) (__arg6); \
 	LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
-	extern void __illegally_sized_syscall_##name##_arg6 (void); \
+	extern void __illegally_sized_syscall_arg6 (void); \
 	if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 4) \
-	  __illegally_sized_syscall_##name##_arg6 (); \
+	  __illegally_sized_syscall_arg6 (); \
 	r8 = arg6
 
 # define ASM_INPUT_0 "0" (r0)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
index 2e1adccd5d..38a376fa90 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -91,7 +91,7 @@
    the negation of the return value in the kernel gets reverted.  */
 
 #undef INTERNAL_SYSCALL
-#define INTERNAL_SYSCALL(name, err, nr, args...)			\
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
   ({									\
     register long int r0  __asm__ ("r0");				\
     register long int r3  __asm__ ("r3");				\
@@ -114,6 +114,8 @@
 	  err = r0;  \
     (int) r3;  \
   })
+#define INTERNAL_SYSCALL(name, err, nr, args...)			\
+  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
 
 #undef INTERNAL_SYSCALL_DECL
 #define INTERNAL_SYSCALL_DECL(err) long int err
@@ -126,48 +128,48 @@
 #define INTERNAL_SYSCALL_ERRNO(val, err)     (val)
 
 #define LOADARGS_0(name, dummy) \
-	r0 = __NR_##name
+	r0 = name
 #define LOADARGS_1(name, __arg1) \
 	long int arg1 = (long int) (__arg1); \
 	LOADARGS_0(name, 0); \
-	extern void __illegally_sized_syscall_##name##_arg1 (void); \
+	extern void __illegally_sized_syscall_arg1 (void); \
 	if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 8) \
-	  __illegally_sized_syscall_##name##_arg1 (); \
+	  __illegally_sized_syscall_arg1 (); \
 	r3 = arg1
 #define LOADARGS_2(name, __arg1, __arg2) \
 	long int arg2 = (long int) (__arg2); \
 	LOADARGS_1(name, __arg1); \
-	extern void __illegally_sized_syscall_##name##_arg2 (void); \
+	extern void __illegally_sized_syscall_arg2 (void); \
 	if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 8) \
-	  __illegally_sized_syscall_##name##_arg2 (); \
+	  __illegally_sized_syscall_arg2 (); \
 	r4 = arg2
 #define LOADARGS_3(name, __arg1, __arg2, __arg3) \
 	long int arg3 = (long int) (__arg3); \
 	LOADARGS_2(name, __arg1, __arg2); \
-	extern void __illegally_sized_syscall_##name##_arg3 (void); \
+	extern void __illegally_sized_syscall_arg3 (void); \
 	if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 8) \
-	  __illegally_sized_syscall_##name##_arg3 (); \
+	  __illegally_sized_syscall_arg3 (); \
 	r5 = arg3
 #define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
 	long int arg4 = (long int) (__arg4); \
 	LOADARGS_3(name, __arg1, __arg2, __arg3); \
-	extern void __illegally_sized_syscall_##name##_arg4 (void); \
+	extern void __illegally_sized_syscall_arg4 (void); \
 	if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 8) \
-	  __illegally_sized_syscall_##name##_arg4 (); \
+	  __illegally_sized_syscall_arg4 (); \
 	r6 = arg4
 #define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
 	long int arg5 = (long int) (__arg5); \
 	LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
-	extern void __illegally_sized_syscall_##name##_arg5 (void); \
+	extern void __illegally_sized_syscall_arg5 (void); \
 	if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 8) \
-	  __illegally_sized_syscall_##name##_arg5 (); \
+	  __illegally_sized_syscall_arg5 (); \
 	r7 = arg5
 #define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
 	long int arg6 = (long int) (__arg6); \
 	LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
-	extern void __illegally_sized_syscall_##name##_arg6 (void); \
+	extern void __illegally_sized_syscall_arg6 (void); \
 	if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 8) \
-	  __illegally_sized_syscall_##name##_arg6 (); \
+	  __illegally_sized_syscall_arg6 (); \
 	r8 = arg6
 
 #define ASM_INPUT_0 "0" (r0)
diff --git a/sysdeps/unix/sysv/linux/setegid.c b/sysdeps/unix/sysv/linux/setegid.c
index 34e64a3dee..33e91c773a 100644
--- a/sysdeps/unix/sysv/linux/setegid.c
+++ b/sysdeps/unix/sysv/linux/setegid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -23,6 +23,8 @@
 
 #include <sysdep.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
+
 
 #if defined __NR_setresgid || __ASSUME_SETRESGID_SYSCALL > 0
 
@@ -40,10 +42,10 @@ setegid (gid_t gid)
     }
 
 # if __ASSUME_32BITUIDS > 0 && defined __NR_setresgid32
-  return INLINE_SYSCALL (setresgid32, 3, -1, gid, -1);
+  result = INLINE_SYSCALL (setresgid32, 3, -1, gid, -1);
 # else
   /* First try the syscall.  */
-  result = __setresgid (-1, gid, -1);
+  result = INLINE_SYSCALL (setresgid, 3, -1, gid, -1);
 #  if __ASSUME_SETRESGID_SYSCALL == 0
   if (result == -1 && errno == ENOSYS)
     /* No system call available.  Use emulation.  This may not work
@@ -51,11 +53,29 @@ setegid (gid_t gid)
        equal to the real group ID, making it impossible to switch back. */
     result = __setregid (-1, gid);
 #  endif
+# endif
 
-  return result;
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+# ifdef __NR_setresgid32
+      cmd.syscall_no = __NR_setresgid32;
+# else
+      cmd.syscall_no = __NR_setresgid;
 # endif
+      cmd.id[0] = -1;
+      cmd.id[1] = gid;
+      cmd.id[2] = -1;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
 }
+#ifndef setegid
 libc_hidden_def (setegid)
+#endif
 #else
 # include <sysdeps/unix/bsd/setegid.c>
 #endif
diff --git a/sysdeps/unix/sysv/linux/seteuid.c b/sysdeps/unix/sysv/linux/seteuid.c
index a1832d64bc..da03a1e6ef 100644
--- a/sysdeps/unix/sysv/linux/seteuid.c
+++ b/sysdeps/unix/sysv/linux/seteuid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -23,6 +23,8 @@
 
 #include <sysdep.h>
 #include "kernel-features.h"
+#include <pthread-functions.h>
+
 
 #if defined __NR_setresuid || __ASSUME_SETRESUID_SYSCALL > 0
 
@@ -40,22 +42,40 @@ seteuid (uid_t uid)
     }
 
 # if __ASSUME_32BITUIDS > 0 && defined __NR_setresuid32
-  return INLINE_SYSCALL (setresuid32, 3, -1, uid, -1);
+  result = INLINE_SYSCALL (setresuid32, 3, -1, uid, -1);
 # else
   /* First try the syscall.  */
-  result = __setresuid (-1, uid, -1);
-# if __ASSUME_SETRESUID_SYSCALL == 0
+  result = INLINE_SYSCALL (setresuid, 3, -1, uid, -1);
+#  if __ASSUME_SETRESUID_SYSCALL == 0
   if (result == -1 && errno == ENOSYS)
     /* No system call available.  Use emulation.  This may not work
        since `setreuid' also sets the saved user ID when UID is not
        equal to the real user ID, making it impossible to switch back.  */
     result = __setreuid (-1, uid);
+#  endif
 # endif
 
-  return result;
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+# ifdef __NR_setresuid32
+      cmd.syscall_no = __NR_setresuid32;
+# else
+      cmd.syscall_no = __NR_setresuid;
 # endif
+      cmd.id[0] = -1;
+      cmd.id[1] = uid;
+      cmd.id[2] = -1;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
 }
+#ifndef seteuid
 libc_hidden_def (seteuid)
+#endif
 #else
 # include <sysdeps/unix/bsd/seteuid.c>
 #endif
diff --git a/sysdeps/unix/sysv/linux/setgid.c b/sysdeps/unix/sysv/linux/setgid.c
new file mode 100644
index 0000000000..dae642abb5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setgid.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include <linux/posix_types.h>
+#include "kernel-features.h"
+#include <pthread-functions.h>
+
+
+
+int
+__setgid (gid_t gid)
+{
+  int result;
+
+  result = INLINE_SYSCALL (setgid, 1, gid);
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setgid;
+      cmd.id[0] = gid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
+}
+#ifndef __setgid
+weak_alias (__setgid, setgid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/setregid.c b/sysdeps/unix/sysv/linux/setregid.c
new file mode 100644
index 0000000000..1d539260ed
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setregid.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include <linux/posix_types.h>
+#include "kernel-features.h"
+#include <pthread-functions.h>
+
+
+int
+__setregid (gid_t rgid, gid_t egid)
+{
+  int result;
+
+  result = INLINE_SYSCALL (setregid, 2, rgid, egid);
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setregid;
+      cmd.id[0] = rgid;
+      cmd.id[1] = egid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
+}
+#ifndef __setregid
+weak_alias (__setregid, setregid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/setresgid.c b/sysdeps/unix/sysv/linux/setresgid.c
new file mode 100644
index 0000000000..ae61d42e6b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setresgid.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include <linux/posix_types.h>
+#include "kernel-features.h"
+#include <pthread-functions.h>
+
+
+int
+__setresgid (gid_t rgid, gid_t egid, gid_t sgid)
+{
+  int result;
+
+  result = INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid);
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setresgid;
+      cmd.id[0] = rgid;
+      cmd.id[1] = egid;
+      cmd.id[2] = sgid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
+}
+#ifndef __setresgid
+weak_alias (__setresgid, setresgid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/setresuid.c b/sysdeps/unix/sysv/linux/setresuid.c
new file mode 100644
index 0000000000..962d944aa4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setresuid.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include <linux/posix_types.h>
+#include "kernel-features.h"
+#include <pthread-functions.h>
+
+
+int
+__setresuid (uid_t ruid, uid_t euid, uid_t suid)
+{
+  int result;
+
+  result = INLINE_SYSCALL (setresuid, 3, ruid, euid, suid);
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setresuid;
+      cmd.id[0] = ruid;
+      cmd.id[1] = euid;
+      cmd.id[2] = suid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
+}
+#ifndef __setresuid
+weak_alias (__setresuid, setresuid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/setreuid.c b/sysdeps/unix/sysv/linux/setreuid.c
new file mode 100644
index 0000000000..c9d841eca0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setreuid.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include <linux/posix_types.h>
+#include "kernel-features.h"
+#include <pthread-functions.h>
+
+
+int
+__setreuid (uid_t ruid, uid_t euid)
+{
+  int result;
+
+  result = INLINE_SYSCALL (setreuid, 2, ruid, euid);
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setreuid;
+      cmd.id[0] = ruid;
+      cmd.id[1] = euid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
+}
+#ifndef __setreuid
+weak_alias (__setreuid, setreuid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/setuid.c b/sysdeps/unix/sysv/linux/setuid.c
new file mode 100644
index 0000000000..84f35176a1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setuid.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include <linux/posix_types.h>
+#include "kernel-features.h"
+#include <pthread-functions.h>
+
+
+int
+__setuid (uid_t uid)
+{
+  int result;
+
+  result = INLINE_SYSCALL (setuid, 1, uid);
+
+#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD
+  if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL)
+    {
+      struct xid_command cmd;
+      cmd.syscall_no = __NR_setuid;
+      cmd.id[0] = uid;
+      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
+    }
+#endif
+
+  return result;
+}
+#ifndef __setuid
+weak_alias (__setuid, setuid)
+#endif
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c b/sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c
index 96f807484d..2e3a54c893 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c
@@ -1,54 +1 @@
-/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <errno.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#ifdef __NR_setresgid32
-
-extern int __setresgid (gid_t rgid, gid_t egid, gid_t sgid);
-
-int
-setegid (gid_t gid)
-{
-  int result;
-
-  if (gid == (gid_t) ~0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  /* First try the syscall.  */
-  result = __setresgid (-1, gid, -1);
-# if __ASSUME_SETRESGID_SYSCALL == 0
-  if (result == -1 && errno == ENOSYS)
-    /* No system call available.  Use emulation.  This may not work
-       since `setregid' also sets the saved group ID when GID is not
-       equal to the real group ID, making it impossible to switch back. */
-    result = __setregid (-1, gid);
-# endif
-
-  return result;
-}
-libc_hidden_def (setegid)
-#else
-# include <sysdeps/unix/bsd/setegid.c>
-#endif
+#include <sysdeps/unix/sysv/linux/i386/setegid.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c b/sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c
index 34638ce4be..18e41d08c1 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c
@@ -1,56 +1 @@
-/* Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <errno.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "kernel-features.h"
-
-#if defined __NR_setresuid32 || __ASSUME_SETRESUID_SYSCALL > 0
-
-extern int __setresuid (uid_t ruid, uid_t euid, uid_t suid);
-
-int
-seteuid (uid_t uid)
-{
-  int result;
-
-  if (uid == (uid_t) ~0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  /* First try the syscall.  */
-  result = __setresuid (-1, uid, -1);
-# if __ASSUME_SETRESUID_SYSCALL == 0
-  if (result == -1 && errno == ENOSYS)
-    /* No system call available.  Use emulation.  This may not work
-       since `setreuid' also sets the saved user ID when UID is not
-       equal to the real user ID, making it impossible to switch back.  */
-    result = __setreuid (-1, uid);
-# endif
-
-  return result;
-}
-libc_hidden_def (seteuid)
-#else
-# include <sysdeps/unix/bsd/seteuid.c>
-#endif
+#include <sysdeps/unix/sysv/linux/i386/seteuid.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c b/sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c
new file mode 100644
index 0000000000..daca1a4833
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/setresgid.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c b/sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c
new file mode 100644
index 0000000000..3aeabe9ad7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/setresuid.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list b/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list
index 6d8e32f9f7..2bfe376a3b 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list
@@ -2,7 +2,5 @@
 
 setrlimit	-	setrlimit	2	__setrlimit	setrlimit
 getrlimit	-	getrlimit	2	__getrlimit	getrlimit
-setresuid	-	setresuid32	3	__setresuid	setresuid
-setresgid	-	setresgid32	3	__setresgid	setresgid
 getresuid	-	getresuid32	3	getresuid
 getresgid	-	getresgid32	3	getresgid
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
index 09f8492cc6..56e4422a73 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
@@ -236,18 +236,19 @@
 #undef INTERNAL_SYSCALL_DECL
 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
 
-#undef INTERNAL_SYSCALL
-#define INTERNAL_SYSCALL(name, err, nr, args...) \
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
   ({									      \
     unsigned long resultvar;						      \
     LOAD_ARGS_##nr (args)						      \
     LOAD_REGS_##nr							      \
     asm volatile (							      \
-    "movq %1, %%rax\n\t"						      \
     "syscall\n\t"							      \
     : "=a" (resultvar)							      \
-    : "i" (__NR_##name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx");	      \
+    : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx");		      \
     (long) resultvar; })
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, err, nr, args...) \
+  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
 
 #undef INTERNAL_SYSCALL_ERROR_P
 #define INTERNAL_SYSCALL_ERROR_P(val, err) \