This is the mail archive of the libc-alpha@sourceware.org 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] Define secure_getenv (v3)


On 07/20/2012 06:43 PM, Roland McGrath wrote:
Oh, will fix. Is this about static linking?

Today in practice in most cases it only makes a difference for static linking. That's only because of our arcane PLT avoidance techniques. It's still not the case for references between shared libraries, like a libc function called by libm or librt, etc.

The existing sources do not follow this rule in all cases, so I assumed
it was expendable.

The actual rule is more subtle than this. So it may be that what you've observed are cases that are actually kosher. If not, then those are bugs and we'd appreciate your reporting (or fixing!) any such cases you noticed.

Thanks for the explanation.


ptsname_r (_GNU_SOURCE) is used from openpty (not conditionally defined, but BSDish I think). Would this qualify as treif?

Anyway, I'm attaching version 3 of the patch, which uses __libc_secure_getenv internally. Testing passes on x86_64-redhat-linux-gnu. I've verified that existing binaries linked against __secure_getenv still run with this version.

--
Florian Weimer / Red Hat Product Security Team


2012-07-23  Florian Weimer  <fweimer@redhat.com>

	* Versions.def: Add GLIBC_2.17.

	* stdlib/stdlib.h: Rename __secure_getenv to secure_getenv.
	* include/stdlib.h: Rename __secure_getenv to secure_getenv.
	Introduce __libc_secure_getenv.
	* stdlib/Versions: Add secure_getenv and __libc_secure_getenv.
	* stdlib/secure-getenv.c: Likewise.  Update copyright years.
	* stdlib/tst-secure-getenv.c: New.
	* stdlib/Makefile (tests): Add testcase.

	* manual/startup.texi (Environment Access): Document
	secure_getenv.

	* hesiod/hesiod.c (hesiod_init): Rename __secure_getenv to
	__libc_secure_getenv.
	* inet/ruserpass.c (ruserpass): Likewise.
	* malloc/mtrace.c (mtrace): Likewise.
	* sysdeps/mach/hurd/tmpfile.c (__tmpfile): Likewise.
	* sysdeps/posix/libc_fatal.c (__libc_fatal): Likewise.  Update
	copyright years.
	* sysdeps/posix/sysconf.c (__sysconf__check_spec): Likewise.
	* sysdeps/posix/tempname.c: Likewise.  Evaluate
	HAVE_SECURE_GETENV.
	* sysdeps/unix/sysv/linux/libc_fatal.c (__libc_message): Rename
	__secure_getenv to __libc_secure_getenv.  Update copyright years.

	* sysdeps/unix/sysv/linux/i386/nptl/libc.abilist: Add secure_getenv.
	* sysdeps/unix/sysv/linux/libc_fatal.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/nptl/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/nptl/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/nptl/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/nptl/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/nptl/libc.abilist: Likewise.
	* ports/sysdeps/unix/sysv/linux/alpha/nptl/libc.abilist: Likewise.
	* ports/sysdeps/unix/sysv/linux/arm/nptl/libc.abilist: Likewise.
	* ports/sysdeps/unix/sysv/linux/ia64/nptl/libc.abilist: Likewise.
	* ports/sysdeps/unix/sysv/linux/m68k/coldfire/nptl/libc.abilist:
	Likewise.
	* ports/sysdeps/unix/sysv/linux/m68k/m680x0/nptl/libc.abilist:
	Likewise.
	* ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist:
	Likewise.
	* ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist:
	Likewise.
	* ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist:
	Likewise.
	* ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist:
	Likewise.
	* ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/nptl/libc.abilist:
	Likewise.
	* ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/nptl/libc.abilist:
	Likewise.
	* ports/sysdeps/unix/sysv/linux/tile/tilepro/nptl/libc.abilist:
	Likewise.

diff --git a/Versions.def b/Versions.def
index 2b44f5e..3c9e0ae 100644
--- a/Versions.def
+++ b/Versions.def
@@ -33,6 +33,7 @@ libc {
   GLIBC_2.14
   GLIBC_2.15
   GLIBC_2.16
+  GLIBC_2.17
   HURD_CTHREADS_0.3
 %ifdef EXPORT_UNWIND_FIND_FDE
   GCC_3.0
diff --git a/hesiod/hesiod.c b/hesiod/hesiod.c
index a3f22e5..657dabe 100644
--- a/hesiod/hesiod.c
+++ b/hesiod/hesiod.c
@@ -87,7 +87,7 @@ hesiod_init(void **context) {
 	ctx->classes[0] = C_IN;
 	ctx->classes[1] = C_HS;
 
-	configname = __secure_getenv("HESIOD_CONFIG");
+	configname = __libc_secure_getenv("HESIOD_CONFIG");
 	if (!configname)
 	  configname = _PATH_HESIOD_CONF;
 	if (parse_config_file(ctx, configname) < 0) {
@@ -109,7 +109,7 @@ hesiod_init(void **context) {
 	 * The default RHS can be overridden by an environment
 	 * variable.
 	 */
-	if ((cp = __secure_getenv("HES_DOMAIN")) != NULL) {
+	if ((cp = __libc_secure_getenv("HES_DOMAIN")) != NULL) {
 		free(ctx->RHS);
 		ctx->RHS = malloc(strlen(cp)+2);
 		if (!ctx->RHS)
diff --git a/include/stdlib.h b/include/stdlib.h
index de0b414..d45b2f0 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -33,12 +33,13 @@ libc_hidden_proto (__strtold_l)
 libc_hidden_proto (exit)
 libc_hidden_proto (abort)
 libc_hidden_proto (getenv)
+extern __typeof (secure_getenv) __libc_secure_getenv;
+libc_hidden_proto (__libc_secure_getenv)
 libc_hidden_proto (bsearch)
 libc_hidden_proto (qsort)
 libc_hidden_proto (qsort_r)
 libc_hidden_proto (lrand48_r)
 libc_hidden_proto (wctomb)
-libc_hidden_proto (__secure_getenv)
 
 extern long int __random (void);
 extern void __srandom (unsigned int __seed);
diff --git a/inet/ruserpass.c b/inet/ruserpass.c
index df423ba..71a734d 100644
--- a/inet/ruserpass.c
+++ b/inet/ruserpass.c
@@ -102,7 +102,7 @@ ruserpass(host, aname, apass)
 	int t, usedefault = 0;
 	struct stat64 stb;
 
-	hdir = __secure_getenv("HOME");
+	hdir = __libc_secure_getenv("HOME");
 	if (hdir == NULL) {
 		/* If we can't get HOME, fail instead of trying ".",
 		   which is no improvement. This really should call
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
index d1049c9..d7a032a 100644
--- a/malloc/mtrace.c
+++ b/malloc/mtrace.c
@@ -309,7 +309,7 @@ mtrace ()
   /* When compiling the GNU libc we use the secure getenv function
      which prevents the misuse in case of SUID or SGID enabled
      programs.  */
-  mallfile = __secure_getenv (mallenv);
+  mallfile = __libc_secure_getenv (mallenv);
 #else
   mallfile = getenv (mallenv);
 #endif
diff --git a/manual/startup.texi b/manual/startup.texi
index 0420e93..d0be5e6 100644
--- a/manual/startup.texi
+++ b/manual/startup.texi
@@ -310,11 +310,15 @@ character, since this is assumed to terminate the string.
 
 The value of an environment variable can be accessed with the
 @code{getenv} function.  This is declared in the header file
-@file{stdlib.h}.  Modifications of enviroment variables are not
-allowed in Multi-threaded programs.  The @code{getenv} function
-can be safely used in multi-threaded programs
+@file{stdlib.h}.
 @pindex stdlib.h
 
+Libraries should use @code{secure_getenv} instead of @code{getenv}, so
+that they do not accidentally use untrusted environment variables.
+Modifications of environment variables are not allowed in
+multi-threaded programs.  The @code{getenv} and @code{secure_getenv}
+functions can be safely used in multi-threaded programs.
+
 @comment stdlib.h
 @comment ISO
 @deftypefun {char *} getenv (const char *@var{name})
@@ -326,6 +330,18 @@ environment variable @var{name} is not defined, the value is a null
 pointer.
 @end deftypefun
 
+@comment stdlib.h
+@comment GNU
+@deftypefun {char *} secure_getenv (const char *@var{name})
+This function is similar to @code{getenv}, but it returns a null
+pointer if the environment is untrusted.  This happens when the
+program file has SUID or SGID bits set.  General-purpose libraries
+should always prefer this function over @code{getenv} to avoid
+vulnerabilities if the library is referenced from a SUID/SGID program.
+
+This function is a GNU extension.
+@end deftypefun
+
 
 @comment stdlib.h
 @comment SVID
diff --git a/ports/sysdeps/unix/sysv/linux/alpha/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/alpha/nptl/libc.abilist
index 6d333aa..f8a3295 100644
--- a/ports/sysdeps/unix/sysv/linux/alpha/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/alpha/nptl/libc.abilist
@@ -1811,6 +1811,9 @@ GLIBC_2.16
  sys_errlist D 0x460
  sys_nerr D 0x4
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/ports/sysdeps/unix/sysv/linux/arm/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/arm/nptl/libc.abilist
index 1f496fb..5523fdd 100644
--- a/ports/sysdeps/unix/sysv/linux/arm/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/libc.abilist
@@ -78,6 +78,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.4
  GLIBC_2.4 A
  _Exit F
diff --git a/ports/sysdeps/unix/sysv/linux/ia64/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/ia64/nptl/libc.abilist
index 6939ad7..b73f5ca 100644
--- a/ports/sysdeps/unix/sysv/linux/ia64/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/ia64/nptl/libc.abilist
@@ -78,6 +78,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/ports/sysdeps/unix/sysv/linux/m68k/coldfire/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/m68k/coldfire/nptl/libc.abilist
index ca31ead..9a92457 100644
--- a/ports/sysdeps/unix/sysv/linux/m68k/coldfire/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/m68k/coldfire/nptl/libc.abilist
@@ -79,6 +79,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.4
  GLIBC_2.4 A
  _Exit F
diff --git a/ports/sysdeps/unix/sysv/linux/m68k/m680x0/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/m68k/m680x0/nptl/libc.abilist
index c2706f1..fbcd208 100644
--- a/ports/sysdeps/unix/sysv/linux/m68k/m680x0/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/m68k/m680x0/nptl/libc.abilist
@@ -1767,6 +1767,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist
index 80f7d33..54e8d1a 100644
--- a/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist
@@ -2242,3 +2242,6 @@ GLIBC_2.9
  pipe2 F
 _gp_disp
  _gp_disp A
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist
index 6d64e1d..2a0e2a2 100644
--- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist
@@ -1390,6 +1390,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist
index 701152e..0e21194 100644
--- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist
@@ -1388,6 +1388,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist
index 43015f4..11ad6a5 100644
--- a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist
@@ -1772,6 +1772,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/nptl/libc.abilist
index eed3b49..48f0c69 100644
--- a/ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/nptl/libc.abilist
@@ -2080,3 +2080,6 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
diff --git a/ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/nptl/libc.abilist
index 2dbce23..3aa70a1 100644
--- a/ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/nptl/libc.abilist
@@ -2080,3 +2080,6 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
diff --git a/ports/sysdeps/unix/sysv/linux/tile/tilepro/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/tile/tilepro/nptl/libc.abilist
index eed3b49..48f0c69 100644
--- a/ports/sysdeps/unix/sysv/linux/tile/tilepro/nptl/libc.abilist
+++ b/ports/sysdeps/unix/sysv/linux/tile/tilepro/nptl/libc.abilist
@@ -2080,3 +2080,6 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
diff --git a/stdlib/Makefile b/stdlib/Makefile
index f7811c5..10674f2 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -68,7 +68,9 @@ tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
 		   tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
 		   tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2	    \
 		   tst-makecontext2 tst-strtod6 tst-unsetenv1		    \
-		   tst-makecontext3 bug-getcontext bug-fmtmsg1
+		   tst-makecontext3 bug-getcontext bug-fmtmsg1		    \
+		   tst-secure-getenv
+tests-static	:= tst-secure-getenv
 
 include ../Makeconfig
 
diff --git a/stdlib/Versions b/stdlib/Versions
index 2aa396e..250bd5f 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -6,7 +6,7 @@ libc {
     # functions used in inline functions or macros
     __strto*_internal;
 
-    # functions used in other libraries
+    # compatibility symbol
     __secure_getenv;
 
     # a*
@@ -103,11 +103,16 @@ libc {
   GLIBC_2.13 {
     __fentry__;
   }
+  GLIBC_2.17 {
+    secure_getenv;
+  }
   GLIBC_PRIVATE {
     # functions which have an additional interface since they are
     # are cancelable.
     __libc_system;
     # Variable which needs a dynamic symbol table entry.
     __abort_msg;
+    # Used from other libraries
+    __libc_secure_getenv;
   }
 }
diff --git a/stdlib/secure-getenv.c b/stdlib/secure-getenv.c
index f64759f..2e696e9 100644
--- a/stdlib/secure-getenv.c
+++ b/stdlib/secure-getenv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1994, 1996, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 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
@@ -18,13 +18,20 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <shlib-compat.h>
+
 /* Some programs and especially the libc itself have to be careful
    what values to accept from the environment.  This special version
    checks for SUID or SGID first before doing any work.  */
 char *
-__secure_getenv (name)
+__libc_secure_getenv (name)
      const char *name;
 {
   return __libc_enable_secure ? NULL : getenv (name);
 }
-libc_hidden_def (__secure_getenv)
+weak_alias (__libc_secure_getenv, secure_getenv)
+libc_hidden_weak (__libc_secure_getenv)
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_16)
+compat_symbol (libc, __libc_secure_getenv, __secure_getenv, GLIBC_2_0);
+#endif
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index f652eda..cf3f39c 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -568,10 +568,12 @@ __BEGIN_NAMESPACE_STD
 extern char *getenv (const char *__name) __THROW __nonnull ((1)) __wur;
 __END_NAMESPACE_STD
 
+#ifdef __USE_GNU
 /* This function is similar to the above but returns NULL if the
    programs is running with SUID or SGID enabled.  */
-extern char *__secure_getenv (const char *__name)
+extern char *secure_getenv (const char *__name)
      __THROW __nonnull ((1)) __wur;
+#endif
 
 #if defined __USE_SVID || defined __USE_XOPEN
 /* The SVID says this is in <stdio.h>, but this seems a better place.	*/
diff --git a/stdlib/tst-secure-getenv.c b/stdlib/tst-secure-getenv.c
new file mode 100644
index 0000000..76d8de6
--- /dev/null
+++ b/stdlib/tst-secure-getenv.c
@@ -0,0 +1,250 @@
+/* Copyright (C) 2012 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Test that secure_getenv works by invoking the test as a SGID
+   program with a group ID from the supplementary group list.  This
+   test can fail spuriously if the user is not a member of a suitable
+   supplementary group. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+static char MAGIC_ARGUMENT[] = "run-actual-test";
+#define MAGIC_STATUS 19
+
+static const char *test_dir;
+
+/* Return a GID which is not our current GID, but is present in the
+   supplementary group list. */
+static gid_t
+choose_gid (void)
+{
+  const int count = 64;
+  gid_t groups[count];
+  int ret = getgroups (count, groups);
+  if (ret < 0)
+    {
+      perror ("getgroups");
+      exit (1);
+    }
+  gid_t current = getgid ();
+  for (int i = 0; i < ret; ++i)
+    {
+      if (groups[i] != current)
+	return groups[i];
+    }
+  return 0;
+}
+
+
+/* Copies the executable into a restricted directory, so that we can
+   safely make it SGID with the TARGET group ID.  Then runs the
+   executable. */
+static int
+run_executable_sgid (gid_t target)
+{
+  char *dirname = 0;
+  char *execname = 0;
+  int infd = -1;
+  int outfd = -1;
+  int ret = -1;
+  if (asprintf (&dirname, "%s/secure-getenv.%jd",
+		test_dir, (intmax_t) getpid ()) < 0)
+    {
+      perror ("asprintf");
+      goto err;
+    }
+  if (mkdir (dirname, 0700) < 0)
+    {
+      perror ("mkdir");
+      goto err;
+    }
+  if (asprintf (&execname, "%s/bin", dirname) < 0)
+    {
+      perror ("asprintf");
+      goto err;
+    }
+  infd = open ("/proc/self/exe", O_RDONLY);
+  if (infd < 0)
+    {
+      perror ("open");
+      goto err;
+    }
+  outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
+  if (outfd < 0)
+    {
+      perror ("open");
+      goto err;
+    }
+  char buf[4096];
+  for (;;)
+    {
+      ssize_t rdcount = read (infd, buf, sizeof (buf));
+      if (rdcount < 0)
+	{
+	  perror ("read");
+	  goto err;
+	}
+      if (rdcount == 0)
+	break;
+      char *p = buf;
+      char *end = buf + rdcount;
+      while (p != end)
+	{
+	  ssize_t wrcount = write (outfd, buf, end - p);
+	  if (wrcount == 0)
+	    errno = ENOSPC;
+	  if (wrcount <= 0)
+	    {
+	      perror ("write");
+	      goto err;
+	    }
+	  p += wrcount;
+	}
+    }
+  if (fchown (outfd, getuid (), target) < 0)
+    {
+      perror ("fchown");
+      goto err;
+    }
+  if (fchmod (outfd, 02750) < 0)
+    {
+      perror ("fchmod");
+      goto err;
+    }
+  if (close (outfd) < 0)
+    {
+      perror ("close");
+      goto err;
+    }
+  if (close (infd) < 0)
+    {
+      perror ("close");
+      goto err;
+    }
+
+  int kid = fork ();
+  if (kid < 0)
+    {
+      perror ("fork");
+      goto err;
+    }
+  if (kid == 0)
+    {
+      /* Child process. */
+      char *args[] = { execname, MAGIC_ARGUMENT, NULL };
+      execve (execname, args, environ);
+      perror ("execve");
+      _exit (1);
+    }
+  int status;
+  if (waitpid (kid, &status, 0) < 0)
+    {
+      perror ("waitpid");
+      goto err;
+    }
+  if (!WIFEXITED (status) || WEXITSTATUS (status) != MAGIC_STATUS)
+    {
+      fprintf (stderr, "Unexpected exit status %d from child process\n",
+	       status);
+      goto err;
+    }
+  ret = 0;
+
+err:
+  if (outfd >= 0)
+    close (outfd);
+  if (infd >= 0)
+    close (infd);
+  if (execname)
+    {
+      unlink (execname);
+      free (execname);
+    }
+  if (dirname)
+    {
+      rmdir (dirname);
+      free (dirname);
+    }
+  return ret;
+}
+
+static int
+do_test (void)
+{
+  if (getenv ("PATH") == NULL)
+    {
+      fprintf (stderr, "PATH not set\n");
+      exit (1);
+    }
+  if (secure_getenv ("PATH") == NULL)
+    {
+      fprintf (stderr, "PATH not set according to secure_getenv\n");
+      exit (1);
+    }
+  if (strcmp (getenv ("PATH"), secure_getenv ("PATH")) != 0)
+    {
+      fprintf (stderr, "PATH mismatch (%s, %s)\n",
+	       getenv ("PATH"), secure_getenv ("PATH"));
+      exit (1);
+    }
+
+  gid_t target = choose_gid ();
+  if (target == 0)
+    {
+      fprintf (stderr, "Could not find a suitable GID user %jd\n",
+	       (intmax_t) getuid ());
+      exit (1);
+    }
+  return run_executable_sgid (target);
+}
+
+static void
+alternative_main (int argc, char **argv)
+{
+  if (argc == 2 && strcmp (argv[1], MAGIC_ARGUMENT) == 0)
+    {
+      if (getgid () == getegid ())
+	{
+	  fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n",
+		   (intmax_t) getgid ());
+	  exit (2);
+	}
+      if (getenv ("PATH") == NULL)
+	{
+	  fprintf (stderr, "PATH variable not present\n");
+	  exit (3);
+	}
+      if (secure_getenv ("PATH") != NULL)
+	{
+	  fprintf (stderr, "PATH variable not filtered out\n");
+	  exit (4);
+	}
+      exit (MAGIC_STATUS);
+    }
+}
+
+#define PREPARE(argc, argv) alternative_main(argc, argv)
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/mach/hurd/tmpfile.c b/sysdeps/mach/hurd/tmpfile.c
index 94b1380..c2aa764 100644
--- a/sysdeps/mach/hurd/tmpfile.c
+++ b/sysdeps/mach/hurd/tmpfile.c
@@ -37,7 +37,7 @@ __tmpfile (void)
   FILE *f;
 
   /* Get a port to the directory that will contain the file.  */
-  const char *dirname = __secure_getenv ("TMPDIR") ?: P_tmpdir;
+  const char *dirname = __libc_secure_getenv ("TMPDIR") ?: P_tmpdir;
   file_t dir = __file_name_lookup (dirname, 0, 0);
   if (dir == MACH_PORT_NULL)
     return NULL;
diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c
index 62acb9b..6b74129 100644
--- a/sysdeps/posix/libc_fatal.c
+++ b/sysdeps/posix/libc_fatal.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1993-1995,1997,2000,2004,2005,2009,2011
-	Free Software Foundation, Inc.
+/* Copyright (C) 1993-2012 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
@@ -61,7 +60,7 @@ __libc_message (int do_abort, const char *fmt, ...)
 
   /* Open a descriptor for /dev/tty unless the user explicitly
      requests errors on standard error.  */
-  const char *on_2 = __secure_getenv ("LIBC_FATAL_STDERR_");
+  const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_");
   if (on_2 == NULL || *on_2 == '\0')
     fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);
 
diff --git a/sysdeps/posix/sysconf.c b/sysdeps/posix/sysconf.c
index 1f988d5..d9b3c83 100644
--- a/sysdeps/posix/sysconf.c
+++ b/sysdeps/posix/sysconf.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1991,1993,1995-1997,1999-2003,2004,2006,2009
-	Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 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
@@ -1259,7 +1258,7 @@ __sysconf_check_spec (const char *spec)
 {
   int save_errno = errno;
 
-  const char *getconf_dir = __secure_getenv ("GETCONF_DIR") ?: GETCONF_DIR;
+  const char *getconf_dir = __libc_secure_getenv ("GETCONF_DIR") ?: GETCONF_DIR;
   size_t getconf_dirlen = strlen (getconf_dir);
   size_t speclen = strlen (spec);
 
diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c
index a98f1d6..2f0bfef 100644
--- a/sysdeps/posix/tempname.c
+++ b/sysdeps/posix/tempname.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2001, 2006, 2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 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
@@ -101,8 +101,12 @@
 # define __xstat64(version, path, buf) stat (path, buf)
 #endif
 
-#if ! (HAVE___SECURE_GETENV || _LIBC)
-# define __secure_getenv getenv
+#if ! (HAVE_SECURE_GETENV || _LIBC)
+# ifdef HAVE___SECURE_GETENV
+#  define __libc_secure_getenv __secure_getenv
+# else
+#  define __libc_secure_getenv getenv
+# endif
 #endif
 
 #ifdef _LIBC
@@ -168,7 +172,7 @@ __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
 
   if (try_tmpdir)
     {
-      d = __secure_getenv ("TMPDIR");
+      d = __libc_secure_getenv ("TMPDIR");
       if (d != NULL && direxists (d))
 	dir = d;
       else if (dir != NULL && direxists (dir))
diff --git a/sysdeps/unix/sysv/linux/i386/nptl/libc.abilist b/sysdeps/unix/sysv/linux/i386/nptl/libc.abilist
index d6695eb..0e8576f 100644
--- a/sysdeps/unix/sysv/linux/i386/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/nptl/libc.abilist
@@ -1811,6 +1811,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/sysdeps/unix/sysv/linux/libc_fatal.c b/sysdeps/unix/sysv/linux/libc_fatal.c
index 58a5a7f8..6cc96d7 100644
--- a/sysdeps/unix/sysv/linux/libc_fatal.c
+++ b/sysdeps/unix/sysv/linux/libc_fatal.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1993-1995,1997,2000,2002-2005,2009,2011
-   Free Software Foundation, Inc.
+/* Copyright (C) 1993-2012 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
@@ -64,7 +63,7 @@ __libc_message (int do_abort, const char *fmt, ...)
 
   /* Open a descriptor for /dev/tty unless the user explicitly
      requests errors on standard error.  */
-  const char *on_2 = __secure_getenv ("LIBC_FATAL_STDERR_");
+  const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_");
   if (on_2 == NULL || *on_2 == '\0')
     fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/nptl/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/nptl/libc.abilist
index 706d2a9..75123b9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/nptl/libc.abilist
@@ -1772,6 +1772,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc.abilist
index a0d362e..e2484d3 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc.abilist
@@ -78,6 +78,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.3
  GLIBC_2.3 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
index d565601..ff0b82f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
@@ -1763,6 +1763,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
index f161a51..2fb0786 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
@@ -84,6 +84,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/sh/nptl/libc.abilist b/sysdeps/unix/sysv/linux/sh/nptl/libc.abilist
index c474f41..3fd150e 100644
--- a/sysdeps/unix/sysv/linux/sh/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/nptl/libc.abilist
@@ -84,6 +84,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/nptl/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/nptl/libc.abilist
index 1804348..7d5a342 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/nptl/libc.abilist
@@ -1768,6 +1768,9 @@ GLIBC_2.16
  sys_errlist D 0x220
  sys_nerr D 0x4
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist
index 8571fa8..6d6e57c 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist
@@ -89,6 +89,9 @@ GLIBC_2.16
  sys_errlist D 0x440
  sys_nerr D 0x4
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/nptl/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/nptl/libc.abilist
index 2a1b8e9..d6ab153 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/nptl/libc.abilist
@@ -80,6 +80,9 @@ GLIBC_2.16
  mbrtoc16 F
  mbrtoc32 F
  timespec_get F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F
 GLIBC_2.2.5
  GLIBC_2.2.5 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/nptl/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/nptl/libc.abilist
index 13b1d91..65bcead 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/nptl/libc.abilist
@@ -2078,3 +2078,6 @@ GLIBC_2.16
  xencrypt F
  xprt_register F
  xprt_unregister F
+GLIBC_2.17
+ GLIBC_2.17 A
+ secure_getenv F

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