about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-09-20 00:16:11 +0000
committerUlrich Drepper <drepper@redhat.com>2004-09-20 00:16:11 +0000
commit2edb61e3f955bfcc9dd3cb6b3b1acfe4806234a6 (patch)
treeeb3ba83120d92a0ea9955520f2df4e00a22bc884
parent29e11320c90722aec6335a5f8d8af84d12ba3c6b (diff)
downloadglibc-2edb61e3f955bfcc9dd3cb6b3b1acfe4806234a6.tar.gz
glibc-2edb61e3f955bfcc9dd3cb6b3b1acfe4806234a6.tar.xz
glibc-2edb61e3f955bfcc9dd3cb6b3b1acfe4806234a6.zip
Update.
	* sysdeps/unix/sysv/linux/setegid.c [HAVE_PTR__NPTL_SETXID]: Call
	callback to set IDs in all other threads as well.
	* sysdeps/unix/sysv/linux/seteuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setegid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/seteuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setgid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setreuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setreuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise.
	* sysdeps/unix/sysv/linux/setuid.c: New file.
	* sysdeps/unix/sysv/linux/setgid.c: New file.
	* sysdeps/unix/sysv/linux/setreuid.c: New file.
	* sysdeps/unix/sysv/linux/setregid.c: New file.
	* sysdeps/unix/sysv/linux/setresuid.c: New file.
	* sysdeps/unix/sysv/linux/setresgid.c: New file.
	* sysdeps/unix/sysv/linux/i386/sysdep.h: Define INTERNAL_SYSCALL_NCS.
	* sysdeps/unix/sysv/linux/ia64/sysdep.h: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c: Use x86 version.
	* sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list: Remove setresgid
	and setresuid.
	* nscd/aicache.c: Use pthread_seteuid_np instead of seteuid.
	* nscd/grpcache.c: Likewise.
	* nscd/hstcache.c: Likewise.
	* nscd/pwdcache.c: Likewise.
-rw-r--r--ChangeLog33
-rw-r--r--linuxthreads/ChangeLog22
-rw-r--r--linuxthreads/Makefile6
-rw-r--r--linuxthreads/Versions6
-rw-r--r--linuxthreads/pthread_setegid.c27
-rw-r--r--linuxthreads/pthread_seteuid.c27
-rw-r--r--linuxthreads/pthread_setgid.c27
-rw-r--r--linuxthreads/pthread_setregid.c27
-rw-r--r--linuxthreads/pthread_setresgid.c27
-rw-r--r--linuxthreads/pthread_setresuid.c27
-rw-r--r--linuxthreads/pthread_setreuid.c27
-rw-r--r--linuxthreads/pthread_setuid.c27
-rw-r--r--linuxthreads/sysdeps/pthread/pthread.h30
-rw-r--r--nptl/ChangeLog34
-rw-r--r--nptl/Makefile6
-rw-r--r--nptl/Versions5
-rw-r--r--nptl/allocatestack.c81
-rw-r--r--nptl/descr.h10
-rw-r--r--nptl/init.c40
-rw-r--r--nptl/pt-allocrtsig.c7
-rw-r--r--nptl/pthreadP.h9
-rw-r--r--nptl/pthread_setegid.c3
-rw-r--r--nptl/pthread_seteuid.c3
-rw-r--r--nptl/pthread_setgid.c3
-rw-r--r--nptl/pthread_setregid.c3
-rw-r--r--nptl/pthread_setresgid.c3
-rw-r--r--nptl/pthread_setresuid.c3
-rw-r--r--nptl/pthread_setreuid.c3
-rw-r--r--nptl/pthread_setuid.c3
-rw-r--r--nptl/sysdeps/pthread/pthread-functions.h2
-rw-r--r--nptl/sysdeps/pthread/pthread.h30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/allocrtsig.c4
-rw-r--r--nscd/aicache.c4
-rw-r--r--nscd/grpcache.c4
-rw-r--r--nscd/hstcache.c4
-rw-r--r--nscd/pwdcache.c4
-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
62 files changed, 1252 insertions, 233 deletions
diff --git a/ChangeLog b/ChangeLog
index f847079669..768ae143c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,38 @@
 2004-09-19  Ulrich Drepper  <drepper@redhat.com>
 
+	* sysdeps/unix/sysv/linux/setegid.c [HAVE_PTR__NPTL_SETXID]: Call
+	callback to set IDs in all other threads as well.
+	* sysdeps/unix/sysv/linux/seteuid.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/setegid.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/seteuid.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/setgid.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/setuid.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/setreuid.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/setreuid.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise.
+	* sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise.
+	* sysdeps/unix/sysv/linux/setuid.c: New file.
+	* sysdeps/unix/sysv/linux/setgid.c: New file.
+	* sysdeps/unix/sysv/linux/setreuid.c: New file.
+	* sysdeps/unix/sysv/linux/setregid.c: New file.
+	* sysdeps/unix/sysv/linux/setresuid.c: New file.
+	* sysdeps/unix/sysv/linux/setresgid.c: New file.
+	* sysdeps/unix/sysv/linux/i386/sysdep.h: Define INTERNAL_SYSCALL_NCS.
+	* sysdeps/unix/sysv/linux/ia64/sysdep.h: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c: Use x86 version.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c: New file.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c: New file.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list: Remove setresgid
+	and setresuid.
+	* nscd/aicache.c: Use pthread_seteuid_np instead of seteuid.
+	* nscd/grpcache.c: Likewise.
+	* nscd/hstcache.c: Likewise.
+	* nscd/pwdcache.c: Likewise.
+
 	* resolv/res_mkquery.c (res_nmkquery): Fix typo.
 
 2004-09-18  Ulrich Drepper  <drepper@redhat.com>
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index e31fd400e5..4a107da62a 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,25 @@
+2004-09-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/pthread.h: Declare pthread_setgid_np,
+	pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np,
+	pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np,
+	and pthread_setresuid_np.
+	* pthread_setgid_np.c: New file.
+	* pthread_setuid_np.c: New file.
+	* pthread_setegid_np.c: New file.
+	* pthread_seteuid_np.c: New file.
+	* pthread_setregid_np.c: New file.
+	* pthread_setreuid_np.c: New file.
+	* pthread_setresgid_np.c: New file.
+	* pthread_setresuid_np.c: New file.
+	* Versions [libpthread, GLIBC_2.3.4]: Add pthread_setgid_np,
+	pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np,
+	pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np,
+	and pthread_setresuid_np.
+	* Makefile (libpthread-routines): Add pthread_setuid, pthread_seteuid,
+	pthread_setreuid, pthread_setresuid, pthread_setgid, pthread_setegid,
+	pthread_setregid, and pthread_setresgid.
+
 2004-09-12  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/pthread/pthread.h: Make rwlock prototypes available also
diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile
index 926de32913..79d412df91 100644
--- a/linuxthreads/Makefile
+++ b/linuxthreads/Makefile
@@ -51,7 +51,11 @@ libpthread-routines := attr cancel condvar join manager mutex ptfork \
 		       ptw-open ptw-open64 ptw-pause ptw-pread ptw-pread64 \
 		       ptw-pwrite ptw-pwrite64 ptw-tcdrain ptw-wait \
 		       ptw-waitpid pt-system old_pthread_atfork pthread_atfork \
-		       ptcleanup
+		       ptcleanup \
+		       pthread_setuid pthread_seteuid pthread_setreuid \
+		       pthread_setresuid \
+		       pthread_setgid pthread_setegid pthread_setregid \
+		       pthread_setresgid
 # Don't generate deps for calls with no sources.  See sysdeps/unix/Makefile.
 omit-deps = $(unix-syscalls:%=ptw-%)
 
diff --git a/linuxthreads/Versions b/linuxthreads/Versions
index b9de1612c3..51896974e5 100644
--- a/linuxthreads/Versions
+++ b/linuxthreads/Versions
@@ -172,6 +172,12 @@ libpthread {
     pthread_cond_wait; pthread_cond_timedwait;
     pthread_cond_signal; pthread_cond_broadcast;
   }
+  GLIBC_2.3.4 {
+    pthread_setuid_np; pthread_seteuid_np; pthread_setreuid_np;
+    pthread_setresuid_np;
+    pthread_setgid_np; pthread_setegid_np; pthread_setregid_np;
+    pthread_setresgid_np;
+  }
   GLIBC_PRIVATE {
     # Internal libc interface to libpthread
     __pthread_initialize;
diff --git a/linuxthreads/pthread_setegid.c b/linuxthreads/pthread_setegid.c
new file mode 100644
index 0000000000..9e16828fa5
--- /dev/null
+++ b/linuxthreads/pthread_setegid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setegid_np (gid_t gid)
+{
+  return setegid (gid);
+}
diff --git a/linuxthreads/pthread_seteuid.c b/linuxthreads/pthread_seteuid.c
new file mode 100644
index 0000000000..9d29d81118
--- /dev/null
+++ b/linuxthreads/pthread_seteuid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_seteuid_np (uid_t uid)
+{
+  return seteuid (uid);
+}
diff --git a/linuxthreads/pthread_setgid.c b/linuxthreads/pthread_setgid.c
new file mode 100644
index 0000000000..db37dd1465
--- /dev/null
+++ b/linuxthreads/pthread_setgid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setgid_np (gid_t gid)
+{
+  return setgid (gid);
+}
diff --git a/linuxthreads/pthread_setregid.c b/linuxthreads/pthread_setregid.c
new file mode 100644
index 0000000000..bd75154c50
--- /dev/null
+++ b/linuxthreads/pthread_setregid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setregid_np (gid_t rgid, gid_t egid)
+{
+  return setregid (rgid, egid);
+}
diff --git a/linuxthreads/pthread_setresgid.c b/linuxthreads/pthread_setresgid.c
new file mode 100644
index 0000000000..b5702804ee
--- /dev/null
+++ b/linuxthreads/pthread_setresgid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setresgid_np (gid_t rgid, gid_t egid, gid_t sgid)
+{
+  return setresgid (rgid, egid, sgid);
+}
diff --git a/linuxthreads/pthread_setresuid.c b/linuxthreads/pthread_setresuid.c
new file mode 100644
index 0000000000..ceb724deaf
--- /dev/null
+++ b/linuxthreads/pthread_setresuid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setresuid_np (uid_t ruid, uid_t euid, uid_t suid)
+{
+  return setresuid (ruid, euid, suid);
+}
diff --git a/linuxthreads/pthread_setreuid.c b/linuxthreads/pthread_setreuid.c
new file mode 100644
index 0000000000..ae8933ece5
--- /dev/null
+++ b/linuxthreads/pthread_setreuid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setreuid_np (uid_t ruid, uid_t euid)
+{
+  return setreuid (ruid, euid);
+}
diff --git a/linuxthreads/pthread_setuid.c b/linuxthreads/pthread_setuid.c
new file mode 100644
index 0000000000..f82ccc1a2f
--- /dev/null
+++ b/linuxthreads/pthread_setuid.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 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 <pthread.h>
+#include <unistd.h>
+
+
+int
+pthread_setuid_np (uid_t uid)
+{
+  return setuid (uid);
+}
diff --git a/linuxthreads/sysdeps/pthread/pthread.h b/linuxthreads/sysdeps/pthread/pthread.h
index 86c7ff7391..9589e968b5 100644
--- a/linuxthreads/sysdeps/pthread/pthread.h
+++ b/linuxthreads/sysdeps/pthread/pthread.h
@@ -681,6 +681,36 @@ extern int pthread_atfork (void (*__prepare) (void),
 
 extern void pthread_kill_other_threads_np (void) __THROW;
 
+
+#ifdef __USE_GNU
+/* Change UID of calling thread.  */
+extern int pthread_setuid_np (__uid_t __uid) __THROW;
+
+/* Change effective UID of calling thread.  */
+extern int pthread_seteuid_np (__uid_t __uid) __THROW;
+
+/* Change real and effective UID of calling thread.  */
+extern int pthread_setreuid_np (__uid_t __ruid, __uid_t __euid) __THROW;
+
+/* Change real, effective, and saved UID of calling thread.  */
+extern int pthread_setresuid_np (__uid_t __ruid, __uid_t __euid,
+				 __uid_t __suid) __THROW;
+
+
+/* Change GID of calling thread.  */
+extern int pthread_setgid_np (__gid_t __gid) __THROW;
+
+/* Change effective GID of calling thread.  */
+extern int pthread_setegid_np (__gid_t __gid) __THROW;
+
+/* Change real and effective GID of calling thread.  */
+extern int pthread_setregid_np (__gid_t __rgid, __gid_t __egid) __THROW;
+
+/* Change real, effective, and saved GID of calling thread.  */
+extern int pthread_setresgid_np (__gid_t __rgid, __gid_t __egid,
+				 __gid_t __sgid) __THROW;
+#endif
+
 __END_DECLS
 
 #endif	/* pthread.h */
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index db3aeba3f7..e4bcfed2e9 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,37 @@
+2004-09-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/allocrtsig.c: Allocate second signal for
+	internal use.
+	* allocatestack.c (__nptl_setxid): New function.
+	* descr.h (struct xid_command): Define type.
+	* init.c (pthread_functions): Add ptr__nptl_setxid initialization.
+	(sighandler_setxid): New function.
+	(__pthread_initialize_minimal): Register sighandler_setxid for
+	SIGCANCEL.
+	* pt-allocrtsig.c: Update comment.
+	* pthreadP.h: Define SIGSETXID.  Declare __xidcmd variable.
+	Declare __nptl_setxid.
+	* sysdeps/pthread/pthread-functions.h: Add ptr__nptl_setxid.
+	* sysdeps/pthread/pthread.h: Declare pthread_setgid_np,
+	pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np,
+	pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np,
+	and pthread_setresuid_np.
+	* pthread_setgid_np.c: New file.
+	* pthread_setuid_np.c: New file.
+	* pthread_setegid_np.c: New file.
+	* pthread_seteuid_np.c: New file.
+	* pthread_setregid_np.c: New file.
+	* pthread_setreuid_np.c: New file.
+	* pthread_setresgid_np.c: New file.
+	* pthread_setresuid_np.c: New file.
+	* Versions [libpthread, GLIBC_2.3.4]: Add pthread_setgid_np,
+	pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np,
+	pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np,
+	and pthread_setresuid_np.
+	* Makefile (libpthread-routines): Add pthread_setuid, pthread_seteuid,
+	pthread_setreuid, pthread_setresuid, pthread_setgid, pthread_setegid,
+	pthread_setregid, and pthread_setresgid.
+
 2004-09-18  Ulrich Drepper  <drepper@redhat.com>
 
 	* allocatestack.c (allocate_stack): Return EAGAIN instead of
diff --git a/nptl/Makefile b/nptl/Makefile
index e75752f801..beaf6d7eab 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -115,7 +115,11 @@ libpthread-routines = init events version \
 		      pthread_kill_other_threads \
 		      pthread_getaffinity pthread_setaffinity \
 		      pthread_attr_getaffinity pthread_attr_setaffinity \
-		      cleanup_routine unwind-forcedunwind
+		      cleanup_routine unwind-forcedunwind \
+		      pthread_setuid pthread_seteuid pthread_setreuid \
+		      pthread_setresuid \
+		      pthread_setgid pthread_setegid pthread_setregid \
+		      pthread_setresgid
 
 libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind
 libpthread-static-only-routines = pthread_atfork
diff --git a/nptl/Versions b/nptl/Versions
index 7e8ac9e271..ee4a6e04b5 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -228,6 +228,11 @@ libpthread {
     # New affinity interfaces.
     pthread_getaffinity_np; pthread_setaffinity_np;
     pthread_attr_getaffinity_np; pthread_attr_setaffinity_np;
+
+    pthread_setuid_np; pthread_seteuid_np; pthread_setreuid_np;
+    pthread_setresuid_np;
+    pthread_setgid_np; pthread_setegid_np; pthread_setregid_np;
+    pthread_setresgid_np;
   }
 
   GLIBC_PRIVATE {
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index cbdd781eeb..242da0a5a1 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -19,6 +19,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <signal.h>
 #include <stdint.h>
 #include <string.h>
 #include <unistd.h>
@@ -26,7 +27,7 @@
 #include <sys/param.h>
 #include <dl-sysdep.h>
 #include <tls.h>
-
+#include <lowlevellock.h>
 
 
 #ifndef NEED_SEPARATE_REGISTER_STACK
@@ -815,6 +816,84 @@ __find_thread_by_id (pid_t tid)
 }
 #endif
 
+void
+attribute_hidden
+__nptl_setxid (struct xid_command *cmdp)
+{
+  lll_lock (stack_cache_lock);
+
+  __xidcmd = cmdp;
+  cmdp->cntr = 0;
+
+  INTERNAL_SYSCALL_DECL (err);
+
+  struct pthread *self = THREAD_SELF;
+
+  /* Iterate over the list with system-allocated threads first.  */
+  list_t *runp;
+  list_for_each (runp, &stack_used)
+    {
+      struct pthread *t = list_entry (runp, struct pthread, list);
+      if (t != self)
+	{
+	  int val;
+#if __ASSUME_TGKILL
+	  val = INTERNAL_SYSCALL (tgkill, err, 3,
+				  THREAD_GETMEM (THREAD_SELF, pid),
+				  t->tid, SIGSETXID);
+#else
+# ifdef __NR_tgkill
+	  val = INTERNAL_SYSCALL (tgkill, err, 3,
+				  THREAD_GETMEM (THREAD_SELF, pid),
+				  t->tid, SIGSETXID);
+	  if (INTERNAL_SYSCALL_ERROR_P (val, err)
+	      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
+# endif
+	    val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
+#endif
+
+	  if (!INTERNAL_SYSCALL_ERROR_P (val, err))
+	    atomic_increment (&cmdp->cntr);
+	}
+    }
+
+  /* Now the list with threads using user-allocated stacks.  */
+  list_for_each (runp, &__stack_user)
+    {
+      struct pthread *t = list_entry (runp, struct pthread, list);
+      if (t != self)
+	{
+	  int val;
+#if __ASSUME_TGKILL
+	  val = INTERNAL_SYSCALL (tgkill, err, 3,
+				  THREAD_GETMEM (THREAD_SELF, pid),
+				  t->tid, SIGSETXID);
+#else
+# ifdef __NR_tgkill
+	  val = INTERNAL_SYSCALL (tgkill, err, 3,
+				  THREAD_GETMEM (THREAD_SELF, pid),
+				  t->tid, SIGSETXID);
+	  if (INTERNAL_SYSCALL_ERROR_P (val, err)
+	      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
+# endif
+	    val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
+#endif
+
+	  if (!INTERNAL_SYSCALL_ERROR_P (val, err))
+	    atomic_increment (&cmdp->cntr);
+	}
+    }
+
+  int cur = cmdp->cntr;
+  while (cur != 0)
+    {
+      lll_futex_wait (&cmdp->cntr, cur);
+      cur = cmdp->cntr;
+    }
+
+  lll_unlock (stack_cache_lock);
+}
+
 static inline void __attribute__((always_inline))
 init_one_static_tls (struct pthread *curp, struct link_map *map)
 {
diff --git a/nptl/descr.h b/nptl/descr.h
index 3611698048..0f8d347b79 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -92,6 +92,16 @@ struct pthread_unwind_buf
 };
 
 
+/* Opcodes and data types for communication with the signal handler to
+   change user/group IDs.  */
+struct xid_command
+{
+  int syscall_no;
+  id_t id[3];
+  volatile int cntr;
+};
+
+
 /* Thread descriptor data structure.  */
 struct pthread
 {
diff --git a/nptl/init.c b/nptl/init.c
index e58dae0ba6..aad2c9001f 100644
--- a/nptl/init.c
+++ b/nptl/init.c
@@ -32,6 +32,7 @@
 #include <version.h>
 #include <shlib-compat.h>
 #include <smp.h>
+#include <lowlevellock.h>
 
 
 #ifndef __NR_set_tid_address
@@ -131,7 +132,8 @@ static const struct pthread_functions pthread_functions =
     .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore,
     .ptr_nthreads = &__nptl_nthreads,
     .ptr___pthread_unwind = &__pthread_unwind,
-    .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd
+    .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd,
+    .ptr__nptl_setxid = __nptl_setxid
   };
 # define ptr_pthread_functions &pthread_functions
 #else
@@ -144,7 +146,7 @@ static void
 sigcancel_handler (int sig, siginfo_t *si, void *ctx)
 {
   /* Safety check.  It would be possible to call this function for
-     other signals and send a signal from another thread.  This is not
+     other signals and send a signal from another process.  This is not
      correct and might even be a security problem.  Try to catch as
      many incorrect invocations as possible.  */
   if (sig != SIGCANCEL
@@ -190,6 +192,34 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx)
 }
 
 
+struct xid_command *__xidcmd attribute_hidden;
+
+/* For asynchronous cancellation we use a signal.  This is the handler.  */
+static void
+sighandler_setxid (int sig, siginfo_t *si, void *ctx)
+{
+  /* Safety check.  It would be possible to call this function for
+     other signals and send a signal from another process.  This is not
+     correct and might even be a security problem.  Try to catch as
+     many incorrect invocations as possible.  */
+  if (sig != SIGSETXID
+#ifdef __ASSUME_CORRECT_SI_PID
+      /* Kernels before 2.5.75 stored the thread ID and not the process
+	 ID in si_pid so we skip this test.  */
+      || si->si_pid != THREAD_GETMEM (THREAD_SELF, pid)
+#endif
+      || si->si_code != SI_TKILL)
+    return;
+
+  INTERNAL_SYSCALL_DECL (err);
+  INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0],
+			__xidcmd->id[1], __xidcmd->id[2]);
+
+  if (atomic_decrement_val (&__xidcmd->cntr) == 0)
+    lll_futex_wake (&__xidcmd->cntr, 1);
+}
+
+
 /* When using __thread for this, we do it in libc so as not
    to give libpthread its own TLS segment just for this.  */
 extern void **__libc_dl_error_tsd (void) __attribute__ ((const));
@@ -242,6 +272,12 @@ __pthread_initialize_minimal_internal (void)
 
   (void) __libc_sigaction (SIGCANCEL, &sa, NULL);
 
+  /* Install the handle to change the threads' uid/gid.  */
+  sa.sa_sigaction = sighandler_setxid;
+  sa.sa_flags = SA_SIGINFO | SA_RESTART;
+
+  (void) __libc_sigaction (SIGSETXID, &sa, NULL);
+
   /* The parent process might have left the signal blocked.  Just in
      case, unblock it.  We reuse the signal mask in the sigaction
      structure.  It is already cleared.  */
diff --git a/nptl/pt-allocrtsig.c b/nptl/pt-allocrtsig.c
index 3598dbb49f..9481e15f25 100644
--- a/nptl/pt-allocrtsig.c
+++ b/nptl/pt-allocrtsig.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -27,8 +27,9 @@ extern int __libc_current_sigrtmax_private (void);
 extern int __libc_allocate_rtsig_private (int high);
 
 
-/* We reserve __SIGRTMIN for use as the cancelation signal.  This
-   signal is used internally.  */
+/* We reserve __SIGRTMIN for use as the cancellation signal and
+   __SIGRTMIN+1 to andle setuid et.al.  These signals are used
+   internally.  */
 int
 __libc_current_sigrtmin (void)
 {
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index c0941f0cf5..1fedce5f3a 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -206,6 +206,13 @@ __do_cancel (void)
 #define SIGTIMER	SIGCANCEL
 
 
+/* Signal used to implement the setuid et.al. functions.  */
+#define SIGSETXID	(__SIGRTMIN + 1)
+
+/* Used to communicate with signal handler.  */
+extern struct xid_command *__xidcmd attribute_hidden;
+
+
 /* Internal prototypes.  */
 
 /* Thread list handling.  */
@@ -441,4 +448,6 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer
 
 extern void __nptl_deallocate_tsd (void) attribute_hidden;
 
+extern void __nptl_setxid (struct xid_command *cmdp) attribute_hidden;
+
 #endif	/* pthreadP.h */
diff --git a/nptl/pthread_setegid.c b/nptl/pthread_setegid.c
new file mode 100644
index 0000000000..9252dfac7d
--- /dev/null
+++ b/nptl/pthread_setegid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define setegid pthread_setegid_np
+#include <setegid.c>
diff --git a/nptl/pthread_seteuid.c b/nptl/pthread_seteuid.c
new file mode 100644
index 0000000000..47bb698025
--- /dev/null
+++ b/nptl/pthread_seteuid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define seteuid pthread_seteuid_np
+#include <seteuid.c>
diff --git a/nptl/pthread_setgid.c b/nptl/pthread_setgid.c
new file mode 100644
index 0000000000..b06bffbf32
--- /dev/null
+++ b/nptl/pthread_setgid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setgid pthread_setgid_np
+#include <setgid.c>
diff --git a/nptl/pthread_setregid.c b/nptl/pthread_setregid.c
new file mode 100644
index 0000000000..7461d2b7fd
--- /dev/null
+++ b/nptl/pthread_setregid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setregid pthread_setregid_np
+#include <setregid.c>
diff --git a/nptl/pthread_setresgid.c b/nptl/pthread_setresgid.c
new file mode 100644
index 0000000000..369fae2672
--- /dev/null
+++ b/nptl/pthread_setresgid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setresgid pthread_setresgid_np
+#include <setresgid.c>
diff --git a/nptl/pthread_setresuid.c b/nptl/pthread_setresuid.c
new file mode 100644
index 0000000000..ac57c0fa8d
--- /dev/null
+++ b/nptl/pthread_setresuid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setresuid pthread_setresuid_np
+#include <setresuid.c>
diff --git a/nptl/pthread_setreuid.c b/nptl/pthread_setreuid.c
new file mode 100644
index 0000000000..aa804ab01d
--- /dev/null
+++ b/nptl/pthread_setreuid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setreuid pthread_setreuid_np
+#include <setreuid.c>
diff --git a/nptl/pthread_setuid.c b/nptl/pthread_setuid.c
new file mode 100644
index 0000000000..ff949c850f
--- /dev/null
+++ b/nptl/pthread_setuid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setuid pthread_setuid_np
+#include <setuid.c>
diff --git a/nptl/sysdeps/pthread/pthread-functions.h b/nptl/sysdeps/pthread/pthread-functions.h
index 23af214518..b1e0fcb26d 100644
--- a/nptl/sysdeps/pthread/pthread-functions.h
+++ b/nptl/sysdeps/pthread/pthread-functions.h
@@ -93,6 +93,8 @@ struct pthread_functions
   void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *)
        __attribute ((noreturn)) __cleanup_fct_attribute;
   void (*ptr__nptl_deallocate_tsd) (void);
+#define HAVE_PTR__NPTL_SETXID
+  void (*ptr__nptl_setxid) (struct xid_command *);
 };
 
 /* Variable in libc.so.  */
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h
index 27666483d9..16f02d1314 100644
--- a/nptl/sysdeps/pthread/pthread.h
+++ b/nptl/sysdeps/pthread/pthread.h
@@ -953,6 +953,36 @@ extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__parent) (void),
 			   void (*__child) (void)) __THROW;
 
+
+#ifdef __USE_GNU
+/* Change UID of calling thread.  */
+extern int pthread_setuid_np (__uid_t __uid) __THROW;
+
+/* Change effective UID of calling thread.  */
+extern int pthread_seteuid_np (__uid_t __uid) __THROW;
+
+/* Change real and effective UID of calling thread.  */
+extern int pthread_setreuid_np (__uid_t __ruid, __uid_t __euid) __THROW;
+
+/* Change real, effective, and saved UID of calling thread.  */
+extern int pthread_setresuid_np (__uid_t __ruid, __uid_t __euid,
+				 __uid_t __suid) __THROW;
+
+
+/* Change GID of calling thread.  */
+extern int pthread_setgid_np (__gid_t __gid) __THROW;
+
+/* Change effective GID of calling thread.  */
+extern int pthread_setegid_np (__gid_t __gid) __THROW;
+
+/* Change real and effective GID of calling thread.  */
+extern int pthread_setregid_np (__gid_t __rgid, __gid_t __egid) __THROW;
+
+/* Change real, effective, and saved GID of calling thread.  */
+extern int pthread_setresgid_np (__gid_t __rgid, __gid_t __egid,
+				 __gid_t __sgid) __THROW;
+#endif
+
 __END_DECLS
 
 #endif	/* pthread.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/allocrtsig.c b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c
index 51aeb22765..b37d54d65b 100644
--- a/nptl/sysdeps/unix/sysv/linux/allocrtsig.c
+++ b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -20,7 +20,7 @@
 #include <signal.h>
 
 
-static int current_rtmin = __SIGRTMIN + 1;
+static int current_rtmin = __SIGRTMIN + 2;
 static int current_rtmax = __SIGRTMAX;
 
 
diff --git a/nscd/aicache.c b/nscd/aicache.c
index 7fddd7d98c..8c2f3f1489 100644
--- a/nscd/aicache.c
+++ b/nscd/aicache.c
@@ -80,7 +80,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
   if (db->secure)
     {
       oldeuid = geteuid ();
-      seteuid (uid);
+      pthread_seteuid_np (uid);
     }
 
   static service_user *hosts_database;
@@ -426,7 +426,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
   _res.options = old_res_options;
 
   if (db->secure)
-    seteuid (oldeuid);
+    pthread_seteuid_np (oldeuid);
 
   if (dataset != NULL && !alloca_used)
     {
diff --git a/nscd/grpcache.c b/nscd/grpcache.c
index bf4a225edd..d9d9139991 100644
--- a/nscd/grpcache.c
+++ b/nscd/grpcache.c
@@ -419,7 +419,7 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req,
   if (db->secure)
     {
       oldeuid = geteuid ();
-      seteuid (uid);
+      pthread_seteuid_np (uid);
     }
 
   while (lookup (req->type, key, &resultbuf, buffer, buflen, &grp) != 0
@@ -456,7 +456,7 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req,
     }
 
   if (db->secure)
-    seteuid (oldeuid);
+    pthread_seteuid_np (oldeuid);
 
   cache_addgr (db, fd, req, keystr, grp, uid, he, dh, errval);
 
diff --git a/nscd/hstcache.c b/nscd/hstcache.c
index 4066aeec7f..d001e6526c 100644
--- a/nscd/hstcache.c
+++ b/nscd/hstcache.c
@@ -442,7 +442,7 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req,
   if (db->secure)
     {
       oldeuid = geteuid ();
-      seteuid (uid);
+      pthread_seteuid_np (uid);
     }
 
   while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst) != 0
@@ -480,7 +480,7 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req,
     }
 
   if (db->secure)
-    seteuid (oldeuid);
+    pthread_seteuid_np (oldeuid);
 
   cache_addhst (db, fd, req, key, hst, uid, he, dh,
 		h_errno == TRY_AGAIN ? errval : 0);
diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c
index 93049bab12..bfc9ec0e07 100644
--- a/nscd/pwdcache.c
+++ b/nscd/pwdcache.c
@@ -415,7 +415,7 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req,
   if (db->secure)
     {
       oldeuid = geteuid ();
-      seteuid (c_uid);
+      pthread_seteuid_np (c_uid);
     }
 
   while (lookup (req->type, key, &resultbuf, buffer, buflen, &pwd) != 0
@@ -452,7 +452,7 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req,
     }
 
   if (db->secure)
-    seteuid (oldeuid);
+    pthread_seteuid_np (oldeuid);
 
   /* Add the entry to the cache.  */
   cache_addpw (db, fd, req, keystr, pwd, c_uid, he, dh, errval);
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) \