This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
Need help in writing a ChangeLog
- From: Pavel Labushev <p dot labushev at gmail dot com>
- To: libc-help at sourceware dot org
- Date: Fri, 19 Nov 2010 14:51:51 +0700
- Subject: 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"