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

Need help in writing a ChangeLog


Hello.

I want to send a patch to libc-alpha@ and I need to write a proper ChangeLog.

This is my current draft:

2010-11-19  Pavel Labushev  <p.labushev@gmail.com>

	* elf/dl-environ.c (_dl_env_sanitize): New function.
	* elf/dl-support.c (_dl_non_dynamic_init): If __libc_enable_secure
	is true, sanitize the environment of privileged process using the
	system whitelist or blacklist file containing environment variable
	names.
	* elf/Makefile: add environ to dl-routines list.
	* elf/rtld.c (process_envvars): If __libc_enable_secure is true,
	sanitize the environment of privileged process using the system
	whitelist or blacklist file containing environment variable names.
	* sysdeps/generic/ldsodefs.h: Add prototype for _dl_env_sanitize.
	* sysdeps/generic/unsecvars.h: Define PRIVENV_WHITELIST_FILE and
	PRIVENV_BLACKLIST_FILE.

Could you give me some advise if I should add or change anything, please?
(Note that there's no bugzilla entry associated with the patch.)

The patch:

--- glibc-2.11.2.orig/elf/dl-environ.c
+++ glibc-2.11.2/elf/dl-environ.c
@@ -84,3 +84,141 @@

   return 0;
 }
+
+
+void
+internal_function
+_dl_env_sanitize (char *file, size_t file_size, int file_is_whitelist)
+{
+  if (file != NULL)
+    {
+      /* Parse the file.  It contains names of environment variables
+         separated by white spaces, '\t' or '\n'. It may also contain
+         comments introduced by `#'.  */
+      char *problem;
+      char *runp;
+      size_t rest;
+
+      /* Eliminate comments.  */
+      runp = file;
+      rest = file_size;
+      while (rest > 0)
+        {
+          char *comment = memchr (runp, '#', rest);
+          if (comment == NULL)
+            break;
+
+          rest -= comment - runp;
+          do
+            *comment = ' ';
+          while (--rest > 0 && *++comment != '\n');
+        }
+
+      /* We have one problematic case: if we have a name at the end of
+         the file without trailing terminating characters, we cannot
+         place the \0.  Handle the case separately.  */
+      if (file[file_size - 1] != ' ' && file[file_size - 1] != '\t'
+          && file[file_size - 1] != '\n')
+        {
+          problem = &file[file_size];
+          while (problem > file && problem[-1] != ' ' && problem[-1] != '\t'
+                 && problem[-1] != '\n')
+            --problem;
+
+          if (problem > file)
+            problem[-1] = '\0';
+        }
+      else
+        {
+          problem = NULL;
+          file[file_size - 1] = '\0';
+        }
+
+      char *pname = NULL;
+      if (problem != NULL)
+        pname = strndupa (problem, file_size - (problem - file));
+
+      if (file_is_whitelist)
+        {
+          char **ep;
+          ep = __environ;
+
+          while (*ep != NULL)
+            {
+              int listed = 0;
+
+              if (file != problem)
+                {
+                  runp = file;
+                  while (*runp != '\0')
+                    {
+                      /* Skip any whitespace chars before variable name.  */
+                      if (*runp == ' ' || *runp == '\t' || *runp == '\n')
+                        {
+                          ++runp;
+                          continue;
+                        }
+
+                      size_t cnt = 0;
+                      while ((*ep)[cnt] == runp[cnt] && runp[cnt] != '\0'
+                             && runp[cnt] != ' ' && runp[cnt] != '\t'
+                             && runp[cnt] != '\n')
+                        ++cnt;
+
+                      if ((*ep)[cnt] == '=')
+                        {
+                          listed = 1;
+                          break;
+                        }
+
+                      /* Skip the rest of current variable name characters.  */
+                      runp = &runp[cnt];
+                      while (*runp != '\0' && *runp != ' ' && *runp != '\t'
+                             && *runp != '\n')
+                        ++runp;
+                    }
+                }
+
+              if (!listed && pname != NULL)
+                {
+                  size_t cnt = 0;
+                  while ((*ep)[cnt] == pname[cnt] && pname[cnt] != '\0'
+                         && pname[cnt] != ' ' && pname[cnt] != '\t'
+                         && pname[cnt] != '\n')
+                    ++cnt;
+                  if ((*ep)[cnt] == '=')
+                    listed = 1;
+                }
+
+              if (listed)
+                ++ep;
+              else
+                {
+                  /* Remove this pointer by moving later ones to the front.  */
+                  char **dp = ep;
+
+                  do
+                    dp[0] = dp[1];
+                  while (*dp++);
+                }
+            }
+        }
+      else
+        /* The file is blacklist.  */
+        {
+          if (file != problem)
+            {
+              char *p;
+              runp = file;
+              while ((p = strsep (&runp, " \t\n")) != NULL)
+                if (p[0] != '\0')
+                  unsetenv (p);
+            }
+
+          if (pname != NULL)
+            {
+              unsetenv (pname);
+            }
+        }
+    }
+}
--- glibc-2.11.2.orig/elf/dl-support.c
+++ glibc-2.11.2/elf/dl-support.c
@@ -246,6 +246,41 @@
   if (!_dl_pagesize)
     _dl_pagesize = __getpagesize ();

+  if (__libc_enable_secure)
+    {
+      /* Sanitize environment using the system whitelist or blacklist
+         file.  */
+      char *file;
+      size_t file_size;
+      if (__access (PRIVENV_WHITELIST_FILE, R_OK) == 0)
+        {
+          file = _dl_sysdep_read_whole_file (PRIVENV_WHITELIST_FILE,
+                                             &file_size,
+                                             PROT_READ | PROT_WRITE);
+          if (__builtin_expect (file != MAP_FAILED, 0))
+            {
+              _dl_env_sanitize (file, file_size, 1);
+              __munmap (file, file_size);
+            }
+          else
+            _exit(EACCES);
+        }
+      else
+        if (__access (PRIVENV_BLACKLIST_FILE, R_OK) == 0)
+          {
+            file = _dl_sysdep_read_whole_file (PRIVENV_BLACKLIST_FILE,
+                                               &file_size,
+                                               PROT_READ | PROT_WRITE);
+            if (__builtin_expect (file != MAP_FAILED, 0))
+              {
+                _dl_env_sanitize (file, file_size, 0);
+                __munmap (file, file_size);
+              }
+            else
+              _exit(EACCES);
+          }
+    }
+
   _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;

   /* Initialize the data structures for the search paths for shared
--- glibc-2.11.2.orig/elf/Makefile
+++ glibc-2.11.2/elf/Makefile
@@ -30,7 +30,8 @@
 dl-routines	= $(addprefix dl-,load cache lookup object reloc deps \
 			          runtime error init fini debug misc \
 				  version profile conflict tls origin scope \
-				  execstack caller open close trampoline)
+				  execstack caller open close trampoline \
+				  environ)
 all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
 # But they are absent from the shared libc, because that code is in ld.so.
 elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
--- glibc-2.11.2.orig/elf/rtld.c
+++ glibc-2.11.2/elf/rtld.c
@@ -2497,6 +2497,41 @@
   enum mode mode = normal;
   char *debug_output = NULL;

+  if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
+    {
+      /* Sanitize environment using the system whitelist or blacklist
+         file.  */
+      char *file;
+      size_t file_size;
+      if (__access (PRIVENV_WHITELIST_FILE, R_OK) == 0)
+        {
+          file = _dl_sysdep_read_whole_file (PRIVENV_WHITELIST_FILE,
+                                             &file_size,
+                                             PROT_READ | PROT_WRITE);
+          if (__builtin_expect (file != MAP_FAILED, 0))
+            {
+              _dl_env_sanitize (file, file_size, 1);
+              __munmap (file, file_size);
+            }
+          else
+            _exit(EACCES);
+        }
+      else
+        if (__access (PRIVENV_BLACKLIST_FILE, R_OK) == 0)
+          {
+            file = _dl_sysdep_read_whole_file (PRIVENV_BLACKLIST_FILE,
+                                               &file_size,
+                                               PROT_READ | PROT_WRITE);
+            if (__builtin_expect (file != MAP_FAILED, 0))
+              {
+                _dl_env_sanitize (file, file_size, 0);
+                __munmap (file, file_size);
+              }
+            else
+              _exit(EACCES);
+          }
+    }
+
   /* This is the default place for profiling data file.  */
   GLRO(dl_profile_output)
     = &"/var/tmp\0/var/profile"[INTUSE(__libc_enable_secure) ? 9 : 0];
--- glibc-2.11.2.orig/sysdeps/generic/ldsodefs.h
+++ glibc-2.11.2/sysdeps/generic/ldsodefs.h
@@ -983,6 +983,11 @@
    other.  */
 extern char *_dl_next_ld_env_entry (char ***position) internal_function;

+/* Sanitize environment according to whitelist or blacklist of
+   environment variable names.  */
+extern void _dl_env_sanitize (char *file, size_t file_size,
+                              int file_is_whitelist) internal_function;
+
 /* Return an array with the names of the important hardware capabilities.  */
 extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
 							size_t paltform_len,
--- glibc-2.11.2.orig/sysdeps/generic/unsecvars.h
+++ glibc-2.11.2/sysdeps/generic/unsecvars.h
@@ -24,3 +24,6 @@
   "RES_OPTIONS\0"							      \
   "TMPDIR\0"								      \
   "TZDIR\0"
+
+#define PRIVENV_WHITELIST_FILE "/etc/privenv-allow"
+#define PRIVENV_BLACKLIST_FILE "/etc/privenv-deny"


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