about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--sysdeps/generic/dl-sysdep.c32
-rw-r--r--sysdeps/unix/sysv/linux/kernel-features.h6
-rw-r--r--sysdeps/unix/sysv/linux/ldsodefs.h6
4 files changed, 31 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 33dd055d1f..f93e5b6827 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2002-07-20  Ulrich Drepper  <drepper@redhat.com>
 
+	* sysdeps/unix/sysv/linux/ldsodefs.h (HAVE_AUX_XID): Define if
+	__ASSUME_AT_XID is defined.
+	* sysdeps/unix/sysv/linux/kernel-features.h (__ASSUME_AT_XID): Define
+	for 2.4.1 and up.
+	* sysdeps/generic/dl-sysdep.c (_dl_sysdep_start): Optimize handling
+	of AT_UID, AT_EUID, AT_GID, and AT_EGID.
+
 	* wcsmbs/Makefile (CFLAGS-wcstod.c): Add -I../stdlib.
 	(CFLAGS-wcstof.c): Likewise.
 	(CFLAGS-wcstold.c): Likewise.
diff --git a/sysdeps/generic/dl-sysdep.c b/sysdeps/generic/dl-sysdep.c
index 0f5f0fcdab..17e8f4dcf2 100644
--- a/sysdeps/generic/dl-sysdep.c
+++ b/sysdeps/generic/dl-sysdep.c
@@ -79,9 +79,7 @@ _dl_sysdep_start (void **start_argptr,
   ElfW(Addr) user_entry;
   ElfW(auxv_t) *av;
   uid_t uid = 0;
-  uid_t euid = 0;
   gid_t gid = 0;
-  gid_t egid = 0;
 #ifdef HAVE_AUX_XID
 # define set_seen(tag) (tag) /* Evaluate for the side effects.  */
 #else
@@ -117,16 +115,12 @@ _dl_sysdep_start (void **start_argptr,
 	break;
 #endif
       case AT_UID:
-	uid = av->a_un.a_val;
-	break;
-      case AT_GID:
-	gid = av->a_un.a_val;
-	break;
       case AT_EUID:
-	euid = av->a_un.a_val;
+	uid ^= av->a_un.a_val;
 	break;
+      case AT_GID:
       case AT_EGID:
-	egid = av->a_un.a_val;
+	gid ^= av->a_un.a_val;
 	break;
       case AT_PLATFORM:
 	GL(dl_platform) = av->a_un.a_ptr;
@@ -146,18 +140,20 @@ _dl_sysdep_start (void **start_argptr,
   DL_SYSDEP_OSCHECK (dl_fatal);
 #endif
 
-  /* Linux doesn't provide us with any of these values on the stack
-     when the dynamic linker is run directly as a program.  */
-
+  /* Fill in the values we have not gotten from the kernel through the
+     auxiliary vector.  */
 #ifndef HAVE_AUX_XID
-# define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
-  SEE (UID, uid);
-  SEE (GID, gid);
-  SEE (EUID, euid);
-  SEE (EGID, egid);
+# define SEE(UID, var, uid) \
+   if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
+  SEE (UID, uid, uid);
+  SEE (EUID, uid, euid);
+  SEE (GID, gid, gid);
+  SEE (EGID, gid, egid);
 #endif
 
-  INTUSE(__libc_enable_secure) = uid != euid || gid != egid;
+  /* If one of the two pairs of IDs does not mattch this is a setuid
+     or setgid run.  */
+  INTUSE(__libc_enable_secure) = uid | gid;
 
 #ifndef HAVE_AUX_PAGESIZE
   if (GL(dl_pagesize) == 0)
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index 562a6c7654..927701a662 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -171,6 +171,12 @@
 # define __ASSUME_AT_PAGESIZE		1
 #endif
 
+/* Starting with at least 2.4.0 the kernel passes the uid/gid unconditionally
+   up to the child.  */
+#if __LINUX_KERNEL_VERSION >= 132097
+# define __ASSUME_AT_XID		1
+#endif
+
 /* Starting with 2.4.5 kernels PPC passes the AUXV in the standard way
    and the mmap2 syscall made it into the official kernel.  */
 #if __LINUX_KERNEL_VERSION >= (132096+5) && defined __powerpc__
diff --git a/sysdeps/unix/sysv/linux/ldsodefs.h b/sysdeps/unix/sysv/linux/ldsodefs.h
index 8e37f4df6a..a3c97c4731 100644
--- a/sysdeps/unix/sysv/linux/ldsodefs.h
+++ b/sysdeps/unix/sysv/linux/ldsodefs.h
@@ -36,8 +36,10 @@ extern void _dl_aux_init (ElfW(auxv_t) *av) internal_function;
 extern void _dl_non_dynamic_init (void) internal_function;
 
 /* We can assume that the kernel always provides the AT_UID, AT_EUID,
-   AT_GID, and AT_EGID values in the auxiliary vector.  */
-#define HAVE_AUX_XID
+   AT_GID, and AT_EGID values in the auxiliary vector from 2.4.0 or so on.  */
+#if __ASSUME_AT_XID
+# define HAVE_AUX_XID
+#endif
 
 /* Starting with one of the 2.4.0 pre-releases the Linux kernel passes
    up the page size information.  */