This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix set{,e,re,res}[ug]id


Hi!

This patch obsoletes
http://sources.redhat.com/ml/libc-alpha/2004-11/msg00084.html
While working on that patch, I started writing a testcase, but was
unpleasantly surprised that uids aren't changed in the other threads.
The problem is that if e.g. a root owned thread first calls setuid
to some non-priviledged user and after it tgkill's other threads with
SIGSETXID to ask them to setuid as well, the tgkill syscalls fail, as
the current thread is now longer priviledged enough to send them
the signal.  This patch in addition to the changes posted last
time changes things so that it first asks other threads to call the
set*id syscalls (which ought to be possible as they are owned by
the same user) and only after that is done calls the syscall in
the current thread.

2004-11-10  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/unix/sysv/linux/setreuid.c: Remove sys/syscall.h,
	sys/types.h, linux/posix_types.h, sysdep.h and pthread-functions.h
	includes.  Include setxid.h.  Use INLINE_SETXID_SYSCALL macro
	instead of INLINE_SYSCALL, kill the HAVE_PTR__NPTL_SETXID guarded
	snippets.
	* sysdeps/unix/sysv/linux/setegid.c: Likewise.
	* sysdeps/unix/sysv/linux/setuid.c: Likewise.
	* sysdeps/unix/sysv/linux/seteuid.c: Likewise.
	* sysdeps/unix/sysv/linux/setgid.c: Likewise.
	* sysdeps/unix/sysv/linux/setresuid.c: Likewise.
	* sysdeps/unix/sysv/linux/setresgid.c: Likewise.
	* sysdeps/unix/sysv/linux/setregid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setegid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setreuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/seteuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setgid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setresgid.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/setregid.c: Likewise.
	* sysdeps/unix/sysv/linux/alpha/setreuid.c: Likewise.
	Formatting.  Change signed int into int.
	* sysdeps/unix/sysv/linux/alpha/setresuid.c: Likewise.
	* sysdeps/unix/sysv/linux/alpha/setresgid.c: Likewise.
	* sysdeps/unix/sysv/linux/alpha/setregid.c: Likewise.
	* sysdeps/unix/sysv/linux/syscalls.list (setresuid, setresgid):
	Remove.
	* sysdeps/unix/setxid.h: New file.

	* Rules (binaries-static): Add xtests-static.
	* Makeconfig (run-program-prefix): Filter also xtests-static.
nptl/
	* sysdeps/pthread/setxid.h: New file.
	* sysdeps/pthread/pthread-functions.h (HAVE_PTR__NPTL_SETXID): Remove.
	(struct xid_command): Add forward decl.
	(struct pthread_functions): Change return type of __nptl_setxid hook
	to int.
	* pthreadP.h (__nptl_setxid): Change return type to int.
	* allocatestack.c (__nptl_setxid): Call INTERNAL_SYSCALL_NCS in the
	calling thread, return its return value and set errno on failure.
	* descr.h (struct xid_command): Change id type to long array.

	* Makefile: Add rules to build and test tst-setuid1 and
	tst-setuid1-static.
	* tst-setuid1.c: New test.
	* tst-setuid1-static.c: New test.

--- libc/sysdeps/unix/setxid.h.jj	2004-11-10 13:12:58.000000000 +0100
+++ libc/sysdeps/unix/setxid.h	2004-11-11 13:23:18.228581275 +0100
@@ -0,0 +1,4 @@
+#include <sysdep.h>
+
+#define INLINE_SETXID_SYSCALL(name, nr, args...) \
+  INLINE_SYSCALL (name, nr, args)
--- libc/sysdeps/unix/sysv/linux/setegid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/setegid.c	2004-11-11 14:44:07.788108725 +0100
@@ -17,13 +17,9 @@
    02111-1307 USA.  */
 
 #include <errno.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
 #include <unistd.h>
-
-#include <sysdep.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #if defined __NR_setresgid || __ASSUME_SETRESGID_SYSCALL > 0
@@ -42,10 +38,10 @@ setegid (gid_t gid)
     }
 
 # if __ASSUME_32BITUIDS > 0 && defined __NR_setresgid32
-  result = INLINE_SYSCALL (setresgid32, 3, -1, gid, -1);
+  result = INLINE_SETXID_SYSCALL (setresgid32, 3, -1, gid, -1);
 # else
   /* First try the syscall.  */
-  result = INLINE_SYSCALL (setresgid, 3, -1, gid, -1);
+  result = INLINE_SETXID_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
@@ -55,22 +51,6 @@ setegid (gid_t gid)
 #  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;
-# 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/sysdeps/unix/sysv/linux/setreuid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/setreuid.c	2004-11-11 14:53:53.802937595 +0100
@@ -18,35 +18,13 @@
 
 #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>
+#include <setxid.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;
+  return INLINE_SETXID_SYSCALL (setreuid, 2, ruid, euid);
 }
 #ifndef __setreuid
 weak_alias (__setreuid, setreuid)
--- libc/sysdeps/unix/sysv/linux/setuid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/setuid.c	2004-11-11 14:54:10.575956012 +0100
@@ -18,34 +18,12 @@
 
 #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>
-
+#include <setxid.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;
+  return INLINE_SETXID_SYSCALL (setuid, 1, uid);
 }
 #ifndef __setuid
 weak_alias (__setuid, setuid)
--- libc/sysdeps/unix/sysv/linux/seteuid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/seteuid.c	2004-11-11 14:44:49.724645096 +0100
@@ -17,13 +17,9 @@
    02111-1307 USA.  */
 
 #include <errno.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
 #include <unistd.h>
-
-#include <sysdep.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #if defined __NR_setresuid || __ASSUME_SETRESUID_SYSCALL > 0
@@ -42,10 +38,10 @@ seteuid (uid_t uid)
     }
 
 # if __ASSUME_32BITUIDS > 0 && defined __NR_setresuid32
-  result = INLINE_SYSCALL (setresuid32, 3, -1, uid, -1);
+  result = INLINE_SETXID_SYSCALL (setresuid32, 3, -1, uid, -1);
 # else
   /* First try the syscall.  */
-  result = INLINE_SYSCALL (setresuid, 3, -1, uid, -1);
+  result = INLINE_SETXID_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
@@ -55,22 +51,6 @@ seteuid (uid_t uid)
 #  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;
-# 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/sysdeps/unix/sysv/linux/setgid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/setgid.c	2004-11-11 14:45:17.581687040 +0100
@@ -18,35 +18,13 @@
 
 #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>
-
+#include <setxid.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;
+  return INLINE_SETXID_SYSCALL (setgid, 1, gid);
 }
 #ifndef __setgid
 weak_alias (__setgid, setgid)
--- libc/sysdeps/unix/sysv/linux/alpha/setreuid.c.jj	2004-11-01 06:31:54.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/alpha/setreuid.c	2004-11-11 15:41:47.592449164 +0100
@@ -18,35 +18,13 @@
 
 #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>
+#include <setxid.h>
 
 
 int
 __setreuid (uid_t ruid, uid_t euid)
 {
-  int result;
-
-  result = INLINE_SYSCALL (setreuid, 2, (signed int)ruid, (signed int)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;
+  return INLINE_SETXID_SYSCALL (setreuid, 2, (int) ruid, (int) euid);
 }
 #ifndef __setreuid
 weak_alias (__setreuid, setreuid)
--- libc/sysdeps/unix/sysv/linux/alpha/setresuid.c.jj	2004-11-01 06:31:54.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/alpha/setresuid.c	2004-11-11 15:43:24.724161139 +0100
@@ -18,36 +18,14 @@
 
 #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>
+#include <setxid.h>
 
 
 int
 __setresuid (uid_t ruid, uid_t euid, uid_t suid)
 {
-  int result;
-
-  result = INLINE_SYSCALL (setresuid, 3, (signed int)ruid, (signed int)euid, (signed int)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;
+  return INLINE_SETXID_SYSCALL (setresuid, 3, (int) ruid,
+				(int) euid, (int) suid);
 }
 libc_hidden_def (__setresuid)
 #ifndef __setresuid
--- libc/sysdeps/unix/sysv/linux/alpha/setresgid.c.jj	2004-11-01 06:31:54.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/alpha/setresgid.c	2004-11-11 15:43:30.855069896 +0100
@@ -18,36 +18,14 @@
 
 #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>
+#include <setxid.h>
 
 
 int
 __setresgid (gid_t rgid, gid_t egid, gid_t sgid)
 {
-  int result;
-
-  result = INLINE_SYSCALL (setresgid, 3, (signed int)rgid, (signed int)egid, (signed int)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;
+  return INLINE_SETXID_SYSCALL (setresgid, 3, (int) rgid,
+				(int) egid, (int) sgid);
 }
 libc_hidden_def (__setresgid)
 #ifndef __setresgid
--- libc/sysdeps/unix/sysv/linux/alpha/setregid.c.jj	2004-11-01 06:31:54.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/alpha/setregid.c	2004-11-11 15:41:24.557548902 +0100
@@ -18,35 +18,13 @@
 
 #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>
+#include <setxid.h>
 
 
 int
 __setregid (gid_t rgid, gid_t egid)
 {
-  int result;
-
-  result = INLINE_SYSCALL (setregid, 2, (signed int)rgid, (signed int)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;
+  return INLINE_SETXID_SYSCALL (setregid, 2, (int) rgid, (int) egid);
 }
 #ifndef __setregid
 weak_alias (__setregid, setregid)
--- libc/sysdeps/unix/sysv/linux/setresuid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/setresuid.c	2004-11-11 17:21:32.838500173 +0100
@@ -18,37 +18,15 @@
 
 #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>
+#include <setxid.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;
+  return INLINE_SETXID_SYSCALL (setresuid, 3, ruid, euid, suid);
 }
+libc_hidden_def (__setresuid)
 #ifndef __setresuid
 weak_alias (__setresuid, setresuid)
 #endif
--- libc/sysdeps/unix/sysv/linux/i386/setegid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/setegid.c	2004-11-11 14:56:46.783185565 +0100
@@ -18,11 +18,8 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <sys/types.h>
-
-#include <sysdep.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #ifdef __NR_setresgid
@@ -42,7 +39,7 @@ setegid (gid)
     }
 
 #if __ASSUME_32BITUIDS > 0
-  result = INLINE_SYSCALL (setresgid32, 3, -1, gid, -1);
+  result = INLINE_SETXID_SYSCALL (setresgid32, 3, -1, gid, -1);
 #else
   /* First try the syscall.  */
 # ifdef __NR_setresgid
@@ -59,18 +56,6 @@ setegid (gid)
     result = __setregid (-1, gid);
 #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] = -1;
-      cmd.id[1] = gid;
-      cmd.id[2] = -1;
-      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
-    }
-#endif
-
   return result;
 }
 libc_hidden_def (setegid)
--- libc/sysdeps/unix/sysv/linux/i386/setreuid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/setreuid.c	2004-11-11 15:39:58.938786810 +0100
@@ -17,15 +17,9 @@
    02111-1307 USA.  */
 
 #include <errno.h>
-#include <sys/types.h>
 #include <unistd.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-#include <linux/posix_types.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #ifdef __NR_setreuid32
@@ -42,14 +36,14 @@ __setreuid (uid_t ruid, uid_t euid)
   int result;
 
 #if __ASSUME_32BITUIDS > 0
-  result = INLINE_SYSCALL (setreuid32, 2, ruid, euid);
+  result = INLINE_SETXID_SYSCALL (setreuid32, 2, ruid, euid);
 #else
 # ifdef __NR_setreuid32
   if (__libc_missing_32bit_uids <= 0)
     {
       int saved_errno = errno;
 
-      result = INLINE_SYSCALL (setreuid32, 2, ruid, euid);
+      result = INLINE_SETXID_SYSCALL (setreuid32, 2, ruid, euid);
 
       if (result == 0)
 	goto out;
@@ -67,23 +61,12 @@ __setreuid (uid_t ruid, uid_t euid)
       return -1;
     }
 
-  result = INLINE_SYSCALL (setreuid, 2, ruid, euid);
+  result = INLINE_SETXID_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
--- libc/sysdeps/unix/sysv/linux/i386/setuid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/setuid.c	2004-11-11 15:40:45.658472016 +0100
@@ -18,14 +18,8 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <sys/types.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-#include <linux/posix_types.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #ifdef __NR_setuid32
@@ -42,14 +36,14 @@ __setuid (uid_t uid)
   int result;
 
 #if __ASSUME_32BITUIDS > 0 && defined __NR_setuid32
-  result = INLINE_SYSCALL (setuid32, 1, uid);
+  result = INLINE_SETXID_SYSCALL (setuid32, 1, uid);
 #else
 # ifdef __NR_setuid32
   if (__libc_missing_32bit_uids <= 0)
     {
       int saved_errno = errno;
 
-      result = INLINE_SYSCALL (setuid32, 1, uid);
+      result = INLINE_SETXID_SYSCALL (setuid32, 1, uid);
       if (result == 0)
 	goto out;
       if (errno != ENOSYS)
@@ -67,22 +61,12 @@ __setuid (uid_t uid)
       return -1;
     }
 
-  result = INLINE_SYSCALL (setuid, 1, uid);
+  result = INLINE_SETXID_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
--- libc/sysdeps/unix/sysv/linux/i386/seteuid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/seteuid.c	2004-11-11 15:33:30.520940397 +0100
@@ -17,12 +17,9 @@
    02111-1307 USA.  */
 
 #include <errno.h>
-#include <sys/types.h>
 #include <unistd.h>
-
-#include <sysdep.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #ifdef __NR_setresuid
@@ -41,7 +38,7 @@ seteuid (uid_t uid)
     }
 
 #if __ASSUME_32BITUIDS > 0
-  result = INLINE_SYSCALL (setresuid32, 3, -1, uid, -1);
+  result = INLINE_SETXID_SYSCALL (setresuid32, 3, -1, uid, -1);
 #else
   /* First try the syscall.  */
 # ifdef __NR_setresuid
@@ -58,18 +55,6 @@ seteuid (uid_t uid)
     result = __setreuid (-1, uid);
 #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] = -1;
-      cmd.id[1] = uid;
-      cmd.id[2] = -1;
-      __libc_pthread_functions.ptr__nptl_setxid (&cmd);
-    }
-#endif
-
   return result;
 }
 libc_hidden_def (seteuid)
--- libc/sysdeps/unix/sysv/linux/i386/setgid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/setgid.c	2004-11-11 15:36:47.760820474 +0100
@@ -1,5 +1,4 @@
-/* Copyright (C) 1998, 2000, 2003, 2004
-   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
@@ -19,15 +18,8 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <sys/types.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-#include <linux/posix_types.h>
-
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #ifdef __NR_setgid32
@@ -44,14 +36,14 @@ __setgid (gid_t gid)
   int result;
 
 #if __ASSUME_32BITUIDS > 0
-  result = INLINE_SYSCALL (setgid32, 1, gid);
+  result = INLINE_SETXID_SYSCALL (setgid32, 1, gid);
 #else
 # ifdef __NR_setgid32
   if (__libc_missing_32bit_uids <= 0)
     {
       int saved_errno = errno;
 
-      result = INLINE_SYSCALL (setgid32, 1, gid);
+      result = INLINE_SETXID_SYSCALL (setgid32, 1, gid);
 
       if (result == 0)
 	goto out;
@@ -70,22 +62,12 @@ __setgid (gid_t gid)
       return -1;
     }
 
-  result = INLINE_SYSCALL (setgid, 1, gid);
+  result = INLINE_SETXID_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
--- libc/sysdeps/unix/sysv/linux/i386/setresuid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/setresuid.c	2004-11-11 15:38:27.082134662 +0100
@@ -18,14 +18,8 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <sys/types.h>
-
-#include <linux/posix_types.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #if defined __NR_setresuid || defined __NR_setresuid32
@@ -44,14 +38,14 @@ __setresuid (uid_t ruid, uid_t euid, uid
   int result;
 
 # if __ASSUME_32BITUIDS > 0 || !defined __NR_setresuid
-  result = INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid);
+  result = INLINE_SETXID_SYSCALL (setresuid32, 3, ruid, euid, suid);
 # else
 #  ifdef __NR_setresuid32
   if (__libc_missing_32bit_uids <= 0)
     {
       int saved_errno = errno;
 
-      result = INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid);
+      result = INLINE_SETXID_SYSCALL (setresuid32, 3, ruid, euid, suid);
       if (result == 0)
 	goto out;
       if (errno != ENOSYS)
@@ -70,24 +64,12 @@ __setresuid (uid_t ruid, uid_t euid, uid
       return -1;
     }
 
-  result = INLINE_SYSCALL (setresuid, 3, ruid, euid, suid);
+  result = INLINE_SETXID_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)
--- libc/sysdeps/unix/sysv/linux/i386/setresgid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/setresgid.c	2004-11-11 15:37:55.891688708 +0100
@@ -18,14 +18,8 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <sys/types.h>
-
-#include <linux/posix_types.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #if defined __NR_setresgid || defined __NR_setresgid32
@@ -44,14 +38,14 @@ __setresgid (gid_t rgid, gid_t egid, gid
   int result;
 
 # if __ASSUME_32BITUIDS > 0 || !defined __NR_setresgid
-  result = INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid);
+  result = INLINE_SETXID_SYSCALL (setresgid32, 3, rgid, egid, sgid);
 # else
 #  ifdef __NR_setresgid32
   if (__libc_missing_32bit_uids <= 0)
     {
       int saved_errno = errno;
 
-      result = INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid);
+      result = INLINE_SETXID_SYSCALL (setresgid32, 3, rgid, egid, sgid);
       if (result == 0)
 	goto out;
       if (errno != ENOSYS)
@@ -70,24 +64,12 @@ __setresgid (gid_t rgid, gid_t egid, gid
       return -1;
     }
 
-  result = INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid);
+  result = INLINE_SETXID_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)
--- libc/sysdeps/unix/sysv/linux/i386/setregid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/setregid.c	2004-11-11 15:37:22.688601078 +0100
@@ -17,15 +17,9 @@
    02111-1307 USA.  */
 
 #include <errno.h>
-#include <sys/types.h>
 #include <unistd.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-#include <linux/posix_types.h>
+#include <setxid.h>
 #include "kernel-features.h"
-#include <pthread-functions.h>
 
 
 #ifdef __NR_setregid32
@@ -42,14 +36,14 @@ __setregid (gid_t rgid, gid_t egid)
   int result;
 
 #if __ASSUME_32BITUIDS > 0
-  result = INLINE_SYSCALL (setregid32, 2, rgid, egid);
+  result = INLINE_SETXID_SYSCALL (setregid32, 2, rgid, egid);
 #else
 # ifdef __NR_setregid32
   if (__libc_missing_32bit_uids <= 0)
     {
       int saved_errno = errno;
 
-      result = INLINE_SYSCALL (setregid32, 2, rgid, egid);
+      result = INLINE_SETXID_SYSCALL (setregid32, 2, rgid, egid);
 
       if (result == 0)
 	goto out;
@@ -67,23 +61,12 @@ __setregid (gid_t rgid, gid_t egid)
       return -1;
     }
 
-  result = INLINE_SYSCALL (setregid, 2, rgid, egid);
+  result = INLINE_SETXID_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
--- libc/sysdeps/unix/sysv/linux/setresgid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/setresgid.c	2004-11-11 17:21:43.288642430 +0100
@@ -18,37 +18,15 @@
 
 #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>
+#include <setxid.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;
+  return INLINE_SETXID_SYSCALL (setresgid, 3, rgid, egid, sgid);
 }
+libc_hidden_def (__setresgid)
 #ifndef __setresgid
 weak_alias (__setresgid, setresgid)
 #endif
--- libc/sysdeps/unix/sysv/linux/syscalls.list.jj	2004-11-01 13:25:48.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/syscalls.list	2004-11-10 15:34:44.000000000 +0100
@@ -66,8 +66,6 @@ sendfile64	-	sendfile64	i:iipi	sendfile6
 setfsgid	EXTRA	setfsgid	i:i	setfsgid
 setfsuid	EXTRA	setfsuid	i:i	setfsuid
 setpgid		-	setpgid		i:ii	__setpgid	setpgid
-setresuid	-	setresuid	i:iii	__setresuid	setresuid
-setresgid	-	setresgid	i:iii	__setresgid	setresgid
 sigaltstack	-	sigaltstack	i:PP	__sigaltstack	sigaltstack
 sysinfo		EXTRA	sysinfo		i:p	sysinfo
 swapon		-	swapon		i:si	__swapon	swapon
--- libc/sysdeps/unix/sysv/linux/setregid.c.jj	2004-11-10 15:14:00.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/setregid.c	2004-11-11 14:53:37.256878713 +0100
@@ -18,35 +18,13 @@
 
 #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>
+#include <setxid.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;
+  return INLINE_SETXID_SYSCALL (setregid, 2, rgid, egid);
 }
 #ifndef __setregid
 weak_alias (__setregid, setregid)
--- libc/nptl/tst-setuid1.c.jj	2004-11-10 16:07:54.000000000 +0100
+++ libc/nptl/tst-setuid1.c	2004-11-11 20:38:27.009498340 +0100
@@ -0,0 +1,1085 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jaku@redhat.com>, 2004.
+
+   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 <pwd.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t b3, b4;
+static uid_t prev_ruid, prev_euid, prev_suid, nobody_uid;
+static gid_t prev_rgid, prev_egid, prev_sgid, nobody_gid;
+enum ACTION { PREPARE, SET, CHECK_BEFORE, CHECK_AFTER };
+#define TESTNO(arg) ((long int) (arg) & 0xff)
+#define THREADNO(arg) ((long int) (arg) >> 8)
+
+
+static void
+check_prev_uid (int tno)
+{
+  uid_t ruid, euid, suid;
+  if (getresuid (&ruid, &euid, &suid) < 0)
+    {
+      printf ("getresuid failed: %d %m\n", tno);
+      exit (1);
+    }
+
+  if (ruid != prev_ruid || euid != prev_euid || suid != prev_suid)
+    {
+      printf ("uids before in %d (%d %d %d) != (%d %d %d)\n", tno,
+	      ruid, euid, suid, prev_ruid, prev_euid, prev_suid);
+      exit (1);
+    }
+}
+
+
+static void
+check_prev_gid (int tno)
+{
+  gid_t rgid, egid, sgid;
+  if (getresgid (&rgid, &egid, &sgid) < 0)
+    {
+      printf ("getresgid failed: %d %m\n", tno);
+      exit (1);
+    }
+
+  if (rgid != prev_rgid || egid != prev_egid || sgid != prev_sgid)
+    {
+      printf ("gids before in %d (%d %d %d) != (%d %d %d)\n", tno,
+	      rgid, egid, sgid, prev_rgid, prev_egid, prev_sgid);
+      exit (1);
+    }
+}
+
+
+static void
+test_setuid1 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && setuid (nobody_uid) < 0)
+    {
+       printf ("setuid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
+	{
+	  printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setuid2 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    {
+      if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+	{
+	  printf ("setresuid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_ruid = nobody_uid;
+      prev_euid = nobody_uid;
+      return;
+    }
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && setuid (prev_suid) < 0)
+    {
+      printf ("setuid failed: %m\n");
+      exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (ruid != nobody_uid || euid != prev_suid || suid != prev_suid)
+	{
+	  printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, nobody_uid, prev_suid, prev_suid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_seteuid1 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && seteuid (nobody_uid) < 0)
+    {
+       printf ("seteuid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid)
+	{
+	  printf ("after seteuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, prev_ruid, nobody_uid, prev_suid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_seteuid2 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    {
+      if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+	{
+	  printf ("setresuid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_ruid = nobody_uid;
+      prev_euid = nobody_uid;
+      nobody_uid = prev_suid;
+      return;
+    }
+
+  test_seteuid1 (action, tno);
+}
+
+
+static void
+test_setreuid1 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && setreuid (-1, nobody_uid) < 0)
+    {
+       printf ("setreuid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid, esuid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (prev_ruid != nobody_uid)
+	esuid = nobody_uid;
+      else
+	esuid = prev_suid;
+
+      if (ruid != prev_ruid || euid != nobody_uid || suid != esuid)
+	{
+	  printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, prev_ruid, nobody_uid, esuid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setreuid2 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && setreuid (nobody_uid, -1) < 0)
+    {
+       printf ("setreuid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (ruid != nobody_uid || euid != prev_euid || suid != prev_euid)
+	{
+	  printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, nobody_uid, prev_euid, prev_euid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setreuid3 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && setreuid (nobody_uid, nobody_uid) < 0)
+    {
+       printf ("setreuid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
+	{
+	  printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setreuid4 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    {
+      if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+	{
+	  printf ("setresuid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_ruid = nobody_uid;
+      prev_euid = nobody_uid;
+      nobody_uid = prev_suid;
+      return;
+    }
+
+  test_setreuid1 (action, tno);
+}
+
+
+static void
+test_setresuid1 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && setresuid (-1, nobody_uid, -1) < 0)
+    {
+       printf ("setresuid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid)
+	{
+	  printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, prev_ruid, nobody_uid, prev_suid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setresuid2 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && setresuid (prev_euid, nobody_uid, nobody_uid) < 0)
+    {
+       printf ("setresuid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (ruid != prev_euid || euid != nobody_uid || suid != nobody_uid)
+	{
+	  printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, prev_euid, nobody_uid, nobody_uid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setresuid3 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_uid (tno);
+
+  if (action == SET && setresuid (nobody_uid, nobody_uid, nobody_uid) < 0)
+    {
+       printf ("setresuid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      uid_t ruid, euid, suid;
+      if (getresuid (&ruid, &euid, &suid) < 0)
+	{
+	  printf ("getresuid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
+	{
+	  printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setresuid4 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    {
+      if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+	{
+	  printf ("setresuid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_ruid = nobody_uid;
+      prev_euid = nobody_uid;
+      nobody_uid = prev_suid;
+      return;
+    }
+
+  test_setresuid1 (action, tno);
+}
+
+
+static void
+test_setgid1 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setgid (nobody_gid) < 0)
+    {
+       printf ("setgid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
+	{
+	  printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setgid2 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    {
+      if (setresgid (nobody_gid, nobody_gid, -1) < 0)
+	{
+	  printf ("setresgid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_rgid = nobody_gid;
+      prev_egid = nobody_gid;
+
+      if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+	{
+	  printf ("setresuid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_ruid = nobody_uid;
+      prev_euid = nobody_uid;
+      return;
+    }
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setgid (prev_sgid) < 0)
+    {
+      printf ("setgid failed: %m\n");
+      exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (rgid != nobody_gid || egid != prev_sgid || sgid != prev_sgid)
+	{
+	  printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, nobody_gid, prev_sgid, prev_sgid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setegid1 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setegid (nobody_gid) < 0)
+    {
+       printf ("setegid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid)
+	{
+	  printf ("after setegid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setegid2 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    {
+      if (setresgid (nobody_gid, nobody_gid, -1) < 0)
+	{
+	  printf ("setresgid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_rgid = nobody_gid;
+      prev_egid = nobody_gid;
+      nobody_gid = prev_sgid;
+      return;
+    }
+
+  test_setegid1 (action, tno);
+}
+
+
+static void
+test_setregid1 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setregid (-1, nobody_gid) < 0)
+    {
+       printf ("setregid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid, esgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (prev_rgid != nobody_gid)
+	esgid = nobody_gid;
+      else
+	esgid = prev_sgid;
+
+      if (rgid != prev_rgid || egid != nobody_gid || sgid != esgid)
+	{
+	  printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, prev_rgid, nobody_gid, esgid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setregid2 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setregid (nobody_gid, -1) < 0)
+    {
+       printf ("setregid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (rgid != nobody_gid || egid != prev_egid || sgid != prev_egid)
+	{
+	  printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, nobody_gid, prev_egid, prev_egid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setregid3 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setregid (nobody_gid, nobody_gid) < 0)
+    {
+       printf ("setregid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
+	{
+	  printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setregid4 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    {
+      if (setresgid (nobody_gid, nobody_gid, -1) < 0)
+	{
+	  printf ("setresgid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_rgid = nobody_gid;
+      prev_egid = nobody_gid;
+      nobody_gid = prev_sgid;
+      return;
+    }
+
+  test_setregid1 (action, tno);
+}
+
+
+static void
+test_setresgid1 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setresgid (-1, nobody_gid, -1) < 0)
+    {
+       printf ("setresgid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid)
+	{
+	  printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setresgid2 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setresgid (prev_egid, nobody_gid, nobody_gid) < 0)
+    {
+       printf ("setresgid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (rgid != prev_egid || egid != nobody_gid || sgid != nobody_gid)
+	{
+	  printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, prev_egid, nobody_gid, nobody_gid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setresgid3 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    return;
+
+  if (action != CHECK_AFTER)
+    check_prev_gid (tno);
+
+  if (action == SET && setresgid (nobody_gid, nobody_gid, nobody_gid) < 0)
+    {
+       printf ("setresgid failed: %m\n");
+       exit (1);
+    }
+
+  if (action != CHECK_BEFORE)
+    {
+      gid_t rgid, egid, sgid;
+      if (getresgid (&rgid, &egid, &sgid) < 0)
+	{
+	  printf ("getresgid failed: %d %m\n", tno);
+	  exit (1);
+	}
+
+      if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
+	{
+	  printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
+		  rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+test_setresgid4 (enum ACTION action, int tno)
+{
+  if (action == PREPARE)
+    {
+      if (setresgid (nobody_gid, nobody_gid, -1) < 0)
+	{
+	  printf ("setresgid failed: %m\n");
+	  exit (1);
+	}
+
+      prev_rgid = nobody_gid;
+      prev_egid = nobody_gid;
+      nobody_gid = prev_sgid;
+      return;
+    }
+
+  test_setresgid1 (action, tno);
+}
+
+
+static struct setuid_test
+{
+  const char *name;
+  void (*test) (enum ACTION, int tno);
+} setuid_tests[] =
+{
+  { "setuid1", test_setuid1 },
+  { "setuid2", test_setuid2 },
+  { "seteuid1", test_seteuid1 },
+  { "seteuid2", test_seteuid2 },
+  { "setreuid1", test_setreuid1 },
+  { "setreuid2", test_setreuid2 },
+  { "setreuid3", test_setreuid3 },
+  { "setreuid4", test_setreuid4 },
+  { "setresuid1", test_setresuid1 },
+  { "setresuid2", test_setresuid2 },
+  { "setresuid3", test_setresuid3 },
+  { "setresuid4", test_setresuid4 },
+  { "setgid1", test_setgid1 },
+  { "setgid2", test_setgid2 },
+  { "setegid1", test_setegid1 },
+  { "setegid2", test_setegid2 },
+  { "setregid1", test_setregid1 },
+  { "setregid2", test_setregid2 },
+  { "setregid3", test_setregid3 },
+  { "setregid4", test_setregid4 },
+  { "setresgid1", test_setresgid1 },
+  { "setresgid2", test_setresgid2 },
+  { "setresgid3", test_setresgid3 },
+  { "setresgid4", test_setresgid4 }
+};
+
+
+static void *
+tf2 (void *arg)
+{
+  int e = pthread_barrier_wait (&b4);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  setuid_tests[TESTNO (arg)].test (CHECK_AFTER, THREADNO (arg));
+  return NULL;
+}
+
+
+static void *
+tf (void *arg)
+{
+  setuid_tests[TESTNO (arg)].test (CHECK_BEFORE, THREADNO (arg));
+
+  int e = pthread_barrier_wait (&b3);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  return tf2 (arg);
+}
+
+
+static int
+do_one_test (long int testno)
+{
+  printf ("%s test\n", setuid_tests[testno].name);
+
+  pid_t pid = fork ();
+  if (pid == 0)
+    {
+      setuid_tests[testno].test (PREPARE, 0);
+      setuid_tests[testno].test (SET, 0);
+      exit (0);
+    }
+
+  if (pid < 0)
+    {
+      printf ("fork failed: %m\n");
+      exit (1);
+    }
+
+  int status;
+  if (waitpid (pid, &status, 0) < 0)
+    {
+      printf ("waitpid failed: %m\n");
+      exit (1);
+    }
+
+  if (!WIFEXITED (status))
+    {
+      puts ("child did not exit");
+      exit (1);
+    }
+
+  if (WEXITSTATUS (status))
+    {
+      printf ("skipping %s test\n", setuid_tests[testno].name);
+      return 0;
+    }
+
+  pid = fork ();
+  if (pid == 0)
+    {
+      setuid_tests[testno].test (PREPARE, 0);
+
+      pthread_t th;
+      int e = pthread_create (&th, NULL, tf, (void *) (testno | 0x100L));
+      if (e != 0)
+	{
+	  printf ("create failed: %m\n");
+	  exit (1);
+	}
+
+      pthread_t th2;
+      e = pthread_create (&th2, NULL, tf, (void *) (testno | 0x200L));
+      if (e != 0)
+	{
+	  printf ("create failed: %m\n");
+	  exit (1);
+	}
+
+      e = pthread_barrier_wait (&b3);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("barrier_wait failed");
+	  exit (1);
+	}
+
+      setuid_tests[testno].test (SET, 0);
+
+      pthread_t th3;
+      e = pthread_create (&th3, NULL, tf2, (void *) (testno | 0x300L));
+      if (e != 0)
+	{
+	  printf ("create failed: %m\n");
+	  exit (1);
+	}
+
+      e = pthread_barrier_wait (&b4);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("barrier_wait failed");
+	  exit (1);
+	}
+
+      exit (0);
+    }
+
+  if (pid < 0)
+    {
+      printf ("fork failed: %m\n");
+      exit (1);
+    }
+
+  if (waitpid (pid, &status, 0) < 0)
+    {
+      printf ("waitpid failed: %m\n");
+      exit (1);
+    }
+
+  if (!WIFEXITED (status))
+    {
+      puts ("second child did not exit");
+      exit (1);
+    }
+
+  if (WEXITSTATUS (status))
+    exit (WEXITSTATUS (status));
+
+  return 0;
+}
+
+
+static int
+do_test (void)
+{
+  struct passwd *pwd = getpwnam ("nobody");
+  if (pwd == NULL)
+    {
+      puts ("User nobody doesn't exist");
+      return 0;
+    }
+  nobody_uid = pwd->pw_uid;
+  nobody_gid = pwd->pw_gid;
+
+  if (getresuid (&prev_ruid, &prev_euid, &prev_suid) < 0)
+    {
+      printf ("getresuid failed: %m\n");
+      exit (1);
+    }
+
+  if (getresgid (&prev_rgid, &prev_egid, &prev_sgid) < 0)
+    {
+      printf ("getresgid failed: %m\n");
+      exit (1);
+    }
+
+  if (prev_ruid == nobody_uid || prev_euid == nobody_uid
+      || prev_suid == nobody_uid)
+    {
+      puts ("already running as user nobody, skipping tests");
+      exit (0);
+    }
+
+  if (prev_rgid == nobody_gid || prev_egid == nobody_gid
+      || prev_sgid == nobody_gid)
+    {
+      puts ("already running as group nobody, skipping tests");
+      exit (0);
+    }
+
+  if (pthread_barrier_init (&b3, NULL, 3) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (pthread_barrier_init (&b4, NULL, 4) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  for (unsigned long int testno = 0;
+       testno < sizeof (setuid_tests) / sizeof (setuid_tests[0]);
+       ++testno)
+    do_one_test (testno);
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/nptl/Makefile.jj	2004-11-10 10:30:30.000000000 +0100
+++ libc/nptl/Makefile	2004-11-11 17:53:11.246458388 +0100
@@ -242,6 +242,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
 	tst-backtrace1 \
 	tst-oddstacklimit \
 	tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x
+xtests = tst-setuid1 tst-setuid1-static
 
 # Files which must not be linked with libpthread.
 tests-nolibpthread = tst-unload
@@ -342,6 +343,7 @@ link-libc-static := $(common-objpfx)libc
 
 ifeq ($(build-static),yes)
 tests-static += tst-locale1 tst-locale2
+xtests-static += tst-setuid1-static
 endif
 # These tests are linked with libc before libpthread
 tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x
@@ -499,9 +501,10 @@ $(objpfx)libpthread.so: $(common-objpfx)
 # Make sure we link with the thread library.
 ifeq ($(build-shared),yes)
 $(addprefix $(objpfx), \
-  $(filter-out $(tests-static) $(tests-reverse) $(tests-nolibpthread), \
-    $(tests) $(test-srcs))): $(objpfx)libpthread.so \
-			     $(objpfx)libpthread_nonshared.a
+  $(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \
+    $(tests-nolibpthread), \
+    $(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \
+				       $(objpfx)libpthread_nonshared.a
 $(objpfx)tst-unload: $(common-objpfx)dlfcn/libdl.so
 # $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
 # since otherwise libpthread.so comes before libc.so when linking.
@@ -509,7 +512,7 @@ $(addprefix $(objpfx), $(tests-reverse))
   $(objpfx)../libc.so $(objpfx)libpthread.so \
   $(objpfx)libpthread_nonshared.a
 $(objpfx)../libc.so: $(common-objpfx)libc.so ;
-$(addprefix $(objpfx),$(tests-static)): $(objpfx)libpthread.a
+$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
 
 $(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so
 else
--- libc/nptl/sysdeps/pthread/setxid.h.jj	2004-11-10 13:12:58.000000000 +0100
+++ libc/nptl/sysdeps/pthread/setxid.h	2004-11-11 15:45:49.344419188 +0100
@@ -0,0 +1,64 @@
+/* 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 <pthreadP.h>
+#include <sysdep.h>
+
+#define __SETXID_1(cmd, arg1) \
+  cmd.id[0] = arg1
+#define __SETXID_2(cmd, arg1, arg2) \
+  __SETXID_1 (cmd, arg1); cmd.id[1] = arg2
+#define __SETXID_3(cmd, arg1, arg2, arg3) \
+  __SETXID_2 (cmd, arg1, arg2); cmd.id[2] = arg3
+
+#ifdef SINGLE_THREAD
+# define INLINE_SETXID_SYSCALL(name, nr, args...) \
+  INLINE_SYSCALL (name, nr, args)
+#elif defined SHARED
+# define INLINE_SETXID_SYSCALL(name, nr, args...) \
+  ({									\
+    int __result;							\
+    if (__builtin_expect (__libc_pthread_functions.ptr__nptl_setxid	\
+			  != NULL, 0))					\
+      {									\
+	struct xid_command __cmd;					\
+	__cmd.syscall_no = __NR_##name;					\
+	__SETXID_##nr (__cmd, args);					\
+	__result = __libc_pthread_functions.ptr__nptl_setxid (&__cmd);	\
+	}								\
+    else								\
+      __result = INLINE_SYSCALL (name, nr, args);			\
+    __result;								\
+   })
+#else
+# define INLINE_SETXID_SYSCALL(name, nr, args...) \
+  ({									\
+    extern __typeof (__nptl_setxid) __nptl_setxid __attribute__((weak));\
+    int __result;							\
+    if (__builtin_expect (__nptl_setxid	!= NULL, 0))			\
+      {									\
+	struct xid_command __cmd;					\
+	__cmd.syscall_no = __NR_##name;					\
+	__SETXID_##nr (__cmd, args);					\
+	__result =__nptl_setxid (&__cmd);				\
+      }									\
+    else								\
+      __result = INLINE_SYSCALL (name, nr, args);			\
+    __result;								\
+   })
+#endif
--- libc/nptl/sysdeps/pthread/pthread-functions.h.jj	2004-09-20 15:35:02.000000000 +0200
+++ libc/nptl/sysdeps/pthread/pthread-functions.h	2004-11-11 13:31:02.498931859 +0100
@@ -24,6 +24,7 @@
 #include <setjmp.h>
 #include <internaltypes.h>
 
+struct xid_command;
 
 /* Data type shared with libc.  The libc uses it to pass on calls to
    the thread functions.  */
@@ -93,8 +94,7 @@ 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 *);
+  int (*ptr__nptl_setxid) (struct xid_command *);
 };
 
 /* Variable in libc.so.  */
--- libc/nptl/pthreadP.h.jj	2004-09-20 15:35:01.000000000 +0200
+++ libc/nptl/pthreadP.h	2004-11-11 13:45:03.227267008 +0100
@@ -448,6 +448,6 @@ extern void _pthread_cleanup_pop_restore
 
 extern void __nptl_deallocate_tsd (void) attribute_hidden;
 
-extern void __nptl_setxid (struct xid_command *cmdp) attribute_hidden;
+extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden;
 
 #endif	/* pthreadP.h */
--- libc/nptl/allocatestack.c.jj	2004-10-12 15:51:46.000000000 +0200
+++ libc/nptl/allocatestack.c	2004-11-11 15:46:18.467235182 +0100
@@ -816,10 +816,11 @@ __find_thread_by_id (pid_t tid)
 }
 #endif
 
-void
+int
 attribute_hidden
 __nptl_setxid (struct xid_command *cmdp)
 {
+  int result;
   lll_lock (stack_cache_lock);
 
   __xidcmd = cmdp;
@@ -891,7 +892,18 @@ __nptl_setxid (struct xid_command *cmdp)
       cur = cmdp->cntr;
     }
 
+  /* This must be last, otherwise the current thread might not have
+     permissions to send SIGSETXID syscall to the other threads.  */
+  result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, err, 3,
+				 cmdp->id[0], cmdp->id[1], cmdp->id[2]);
+  if (INTERNAL_SYSCALL_ERROR_P (result, err))
+    {
+      __set_errno (INTERNAL_SYSCALL_ERRNO (result, err));
+      result = -1;
+    }
+
   lll_unlock (stack_cache_lock);
+  return result;
 }
 
 static inline void __attribute__((always_inline))
--- libc/nptl/descr.h.jj	2004-09-30 00:50:01.000000000 +0200
+++ libc/nptl/descr.h	2004-11-11 13:23:49.213038128 +0100
@@ -97,7 +97,7 @@ struct pthread_unwind_buf
 struct xid_command
 {
   int syscall_no;
-  id_t id[3];
+  long id[3];
   volatile int cntr;
 };
 
--- libc/nptl/tst-setuid1-static.c.jj	2004-11-11 17:33:48.566684467 +0100
+++ libc/nptl/tst-setuid1-static.c	2004-11-11 17:33:43.456593220 +0100
@@ -0,0 +1 @@
+#include "tst-setuid1.c"
--- libc/Rules.jj	2004-07-12 17:50:21.000000000 +0200
+++ libc/Rules	2004-11-11 17:52:12.826822203 +0100
@@ -104,7 +104,7 @@ endif
 
 ifeq ($(build-programs),yes)
 binaries-all = $(others) $(sysdep-others) $(tests) $(xtests) $(test-srcs)
-binaries-static = $(others-static) $(tests-static)
+binaries-static = $(others-static) $(tests-static) $(xtests-static)
 else
 binaries-all = $(tests) $(xtests) $(test-srcs)
 binaries-static =
--- libc/Makeconfig.jj	2004-11-09 12:26:40.000000000 +0100
+++ libc/Makeconfig	2004-11-11 17:51:44.740804308 +0100
@@ -541,7 +541,7 @@ $(subst $(empty) ,:,$(strip $(patsubst -
 				       $(filter -Wl$(comma)-rpath-link=%,\
 						$(sysdep-LDFLAGS)))))
 run-program-prefix = $(if $(filter $(notdir $(built-program-file)),\
-				   $(tests-static)),, \
+				   $(tests-static) $(xtests-static)),, \
 			  $(elf-objpfx)$(rtld-installed-name) \
 			  --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)))
 else

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]