This is the mail archive of the glibc-bugs@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]

[Bug libc/5069] New: env thread safety problem


Hi everyone,

   In the glibc-2.6.1/manual/startup.texi, it says "The value of an environment
variable can be accessed with the @code{getenv} function.  This is declared in
the header file @file{stdlib.h}.  All of the following functions can be safely
used in multi-threaded programs.  It is made sure that concurrent modifications
to the environment do not lead to errors."

   But getenv() can't be used safely with setenv(), unsetenv(), clearenv() in
multi-threaded programs on multi-cpu.
   When getenv() is being called, if "setenv(), unsetenv(), clearenv()" set
"__environ" to NULL on another cpu,  the program will result in segmentation fault.

   In glibc,  getenv() is called by many functions which are thread safety in
POSIX. So when we use the setenv(),unsetenv(), clearenv(), we can't use those
functions by multi-thread method. I think it should be modified.

   I've made a patch to fix it. It applied a read lock in getenv() and write
locks in setenv(), unsetenv(), clearenv().

   Because the read lock can't block getenv(), only to block  setenv(),
unsetenv(), clearenv().
   getenv() itself can achieve full concurrency.

   The attachment is the patch.

diff -Nurp glibc-2.6.1.org/stdlib/getenv.c glibc-2.6.1/stdlib/getenv.c
--- glibc-2.6.1.org/stdlib/getenv.c	2005-12-14 17:08:04.000000000 +0800
+++ glibc-2.6.1/stdlib/getenv.c	2007-08-30 16:44:50.000000000 +0800
@@ -23,6 +23,16 @@
 #include <string.h>
 #include <unistd.h>
 
+#if _LIBC
+/* This lock protects against simultaneous modifications of `environ'.  */
+# include <bits/libc-lock.h>
+__libc_rwlock_define (extern, envlock attribute_hidden)
+# define LOCK   __libc_rwlock_rdlock (envlock)
+# define UNLOCK __libc_rwlock_unlock (envlock)
+#else
+# define LOCK
+# define UNLOCK
+#endif
 
 /* Return the value of the environment variable NAME.  This implementation
    is tuned a bit in that it assumes no environment variable has an empty
@@ -37,9 +47,15 @@ getenv (name)
   size_t len = strlen (name);
   char **ep;
   uint16_t name_start;
+  char *env_value;
+
+  LOCK;
 
   if (__environ == NULL || name[0] == '\0')
-    return NULL;
+    {
+      UNLOCK;
+      return NULL;
+    }
 
   if (name[1] == '\0')
     {
@@ -64,7 +80,11 @@ getenv (name)
 			       | (((unsigned char *) *ep)[1] << 8));
 #endif
 	  if (name_start == ep_start)
-	    return &(*ep)[2];
+            {
+              env_value = &(*ep)[2];
+              UNLOCK;
+	      return env_value;
+            }
 	}
     }
   else
@@ -89,10 +109,15 @@ getenv (name)
 
 	  if (name_start == ep_start && !strncmp (*ep + 2, name, len)
 	      && (*ep)[len + 2] == '=')
-	    return &(*ep)[len + 3];
+            {
+              env_value = &(*ep)[len + 3];
+              UNLOCK;
+	      return env_value;
+            }
 	}
     }
 
+  UNLOCK;
   return NULL;
 }
 libc_hidden_def (getenv)
diff -Nurp glibc-2.6.1.org/stdlib/setenv.c glibc-2.6.1/stdlib/setenv.c
--- glibc-2.6.1.org/stdlib/setenv.c	2005-12-14 18:44:05.000000000 +0800
+++ glibc-2.6.1/stdlib/setenv.c	2007-08-29 17:21:50.000000000 +0800
@@ -48,9 +48,9 @@ extern char **environ;
 #if _LIBC
 /* This lock protects against simultaneous modifications of `environ'.  */
 # include <bits/libc-lock.h>
-__libc_lock_define_initialized (static, envlock)
-# define LOCK	__libc_lock_lock (envlock)
-# define UNLOCK	__libc_lock_unlock (envlock)
+__libc_rwlock_define_initialized (, envlock attribute_hidden)
+# define LOCK   __libc_rwlock_wrlock (envlock)
+# define UNLOCK __libc_rwlock_unlock (envlock)
 #else
 # define LOCK
 # define UNLOCK

-- 
           Summary: env thread safety problem
           Product: glibc
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: zhangxiliang at cn dot fujitsu dot com
                CC: glibc-bugs at sources dot redhat dot com,zhangxiliang at
                    cn dot fujitsu dot com


http://sourceware.org/bugzilla/show_bug.cgi?id=5069

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


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