From 4b5b9b7bd73ec4acedb77292a02b6ad887d9f669 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Mon, 24 Sep 2018 12:37:16 +0100
Subject: [PATCH] Compile on older glibc that didn't have secure_getenv()

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 capsule/capsule-init.c       |  4 ++++
 capsule/capsule.h            |  5 +++++
 configure.ac                 |  2 ++
 doc/Capsules.txt             |  3 ++-
 doc/capsule-init-project.xml | 11 ++++++++---
 doc/capsule-mkstublib.xml    | 15 +++++++++++----
 6 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/capsule/capsule-init.c b/capsule/capsule-init.c
index 4539edb0e..4c9d1ed2f 100644
--- a/capsule/capsule-init.c
+++ b/capsule/capsule-init.c
@@ -443,7 +443,9 @@ static void __attribute__ ((constructor)) _init_capsule (void)
 {
     _capsule_list = ptr_list_alloc( 16 );
 
+#ifdef HAVE_SECURE_GETENV
     set_debug_flags( secure_getenv("CAPSULE_DEBUG") );
+#endif
 
     // these are needed if there is > 1 libc instance:
     _capsule_original_free    = dlsym( RTLD_DEFAULT, "free"    );
@@ -490,6 +492,7 @@ capsule_get_prefix (const char *dflt, const char *soname)
 static const char *
 get_prefix_nocopy (const char *dflt, const char *soname)
 {
+#ifdef HAVE_SECURE_GETENV
     char env_var[PATH_MAX] = CAP_ENV_PREFIX;
     const size_t offs = strlen( CAP_ENV_PREFIX );
     size_t x = 0;
@@ -519,6 +522,7 @@ get_prefix_nocopy (const char *dflt, const char *soname)
                prefix );
         return prefix;
     }
+#endif
 
     if( dflt )
     {
diff --git a/capsule/capsule.h b/capsule/capsule.h
index 8b2f5d819..1435514f5 100644
--- a/capsule/capsule.h
+++ b/capsule/capsule.h
@@ -250,6 +250,11 @@ void capsule_close (capsule cap);
  * - Next: The default to the value passed in @dflt
  * - And if all that failed, NULL (which is internally equivalent to "/")
  *
+ * The environment variables are ignored if the process is privileged
+ * (setuid, setgid, given special capabilities, or marked as privileged
+ * by a LSM), or if libcapsule was compiled against a glibc version
+ * older than 2.17.
+ *
  * Although the value is newly allocated it will typically be cached
  * in a structure that needs to survive the entire lifespan of the
  * running program, so freeing it is unlikely to be a concern.
diff --git a/configure.ac b/configure.ac
index 47778bda0..39158a261 100644
--- a/configure.ac
+++ b/configure.ac
@@ -48,6 +48,8 @@ AX_COMPILER_FLAGS([], [], [], [], [ \
     -Wno-declaration-after-statement \
 ])
 
+AC_CHECK_FUNCS_ONCE([secure_getenv])
+
 AM_CONDITIONAL([ENABLE_SHARED], [test "x$enable_shared" = xyes])
 
 dnl make sure we've got the _right_ libelf (doesn't always ship a .pc)
diff --git a/doc/Capsules.txt b/doc/Capsules.txt
index 7dd6db0ce..7b5023e6c 100644
--- a/doc/Capsules.txt
+++ b/doc/Capsules.txt
@@ -94,7 +94,8 @@ The constructor for libcapsule runs, and does the following:
       - the soname specific env var (eg CAPSULE_LIBGL_SO_1_PREFIX)
       - the CAPSULE_PREFIX env var
       - the static prefix in the capsule's metadata 
-      - NOTE: env vars don't apply here to setuid/setgid processes
+      - NOTE: env vars don't apply here to setuid/setgid processes,
+        or if libcapsule was compiled using glibc older than 2.17
   - aggregates the exclude and export metadata lists, grouping
     them by prefix (and deduplicating the resulting lists)
     - eg the ‘export’ list from a namespace will be all the sonames from
diff --git a/doc/capsule-init-project.xml b/doc/capsule-init-project.xml
index f29bd03f4..781a152fa 100644
--- a/doc/capsule-init-project.xml
+++ b/doc/capsule-init-project.xml
@@ -145,9 +145,14 @@ License along with libcapsule.  If not, see <http://www.gnu.org/licenses/>.
         <listitem>
           <para>
             Find libraries to be proxied in this chroot, sysroot or
-            container at runtime if the library-specific env var (eg
-            CAPSULE_LIBGL_SO_1_PREFIX for libGL.so.1) or CAPSULE_PREFIX
-            or is unset.
+            container at runtime. The default is /host.
+          </para>
+          <para>
+            If libcapsule was compiled with glibc 2.17 or later and the
+            process is not privileged, this can be overridden at runtime
+            by setting a SONAME-specific environment variable (for
+            example CAPSULE_LIBGL_SO_1_PREFIX for libGL.so.1) or by
+            setting the generic CAPSULE_PREFIX environment variable.
           </para>
         </listitem>
       </varlistentry>
diff --git a/doc/capsule-mkstublib.xml b/doc/capsule-mkstublib.xml
index 5f6431181..56185ab66 100644
--- a/doc/capsule-mkstublib.xml
+++ b/doc/capsule-mkstublib.xml
@@ -157,7 +157,9 @@ License along with libcapsule.  If not, see <http://www.gnu.org/licenses/>.
           <para>
             The default is the soname-specific environment variable (eg
             CAPSULE_LIBGL_SO_1_PREFIX for libGL.so.1), or the CAPSULE_PREFIX
-            environment variable, or /host.
+            environment variable, or /host. The environment variables are
+            ignored if the process is privileged, or if libcapsule was
+            compiled with glibc older than 2.17.
           </para>
         </listitem>
       </varlistentry>
@@ -212,9 +214,14 @@ License along with libcapsule.  If not, see <http://www.gnu.org/licenses/>.
         <listitem>
           <para>
             Find libraries to be proxied in this chroot, sysroot or
-            container at runtime if CAPSULE_PREFIX or the
-            library-specific env var (eg CAPSULE_LIBGL_SO_1_PREFIX for
-            libGL.so.1) is unset.
+            container at runtime. The default is /host.
+          </para>
+          <para>
+            If libcapsule was compiled with glibc 2.17 or later and the
+            process is not privileged, this can be overridden at runtime
+            by setting a SONAME-specific environment variable (for
+            example CAPSULE_LIBGL_SO_1_PREFIX for libGL.so.1) or by
+            setting the generic CAPSULE_PREFIX environment variable.
           </para>
         </listitem>
       </varlistentry>
-- 
GitLab