1 From 92c63984fc28ea1bb0939acfcb551f65d7bfddf7 Mon Sep 17 00:00:00 2001
2 From: Dennis Groenen <tj.groenen@gmail.com>
3 Date: Fri, 23 Dec 2011 20:34:22 +0100
4 Subject: [PATCH] appletlib: parse /etc/environment prior to applet launch
7 libbb/appletlib.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++
8 1 files changed, 117 insertions(+), 0 deletions(-)
10 diff --git a/libbb/appletlib.c b/libbb/appletlib.c
11 index 8157b4f..d13aee5 100644
12 --- a/libbb/appletlib.c
13 +++ b/libbb/appletlib.c
14 @@ -474,6 +474,121 @@ static inline void parse_config_file(void)
16 # endif /* FEATURE_SUID_CONFIG */
18 +/* We do not want to allow all characters in environment variables.
19 + * Function based on patch by Tito.
20 + * http://lists.busybox.net/pipermail/busybox/2011-August/076364.html */
21 +static bool bad_env_var(const char *name)
23 + const char *s = name;
26 + /* We don't use isalnum as it will allow locale-specific non-ASCII */
27 + /* letters in legacy 8-bit locales. */
28 + if (((*name >= 48 && *name <= 57) && name != s) /* no numeric values as first char */
29 + || *name == '_' /* allow underscores */
30 + || (*name >= 65 && *name <= 90) /* allow A-Z */
31 + || (*name >= 97 && *name <= 122) /* allow a-z */
40 +static void load_env_vars(void)
42 + /* Don't depend on the tools to combine strings. */
43 + static const char config_file[] ALIGN1 = "/etc/environment";
50 + if ((stat(config_file, &st) != 0) /* No config file? */
51 + || !S_ISREG(st.st_mode) /* Not a regular file? */
52 + || (st.st_uid != 0) /* Not owned by root? */
53 + || (st.st_mode & (S_IWGRP | S_IWOTH)) /* Writable by non-root? */
54 + || !(f = fopen_for_read(config_file)) /* Cannot open? */
67 + if (!fgets(buffer, sizeof(buffer), f)) { /* Are we done? */
73 + lc++; /* Got a (partial) line. */
75 + /* If a line is too long for our buffer, we consider it an error.
76 + * The following test does mistreat one corner case though.
77 + * If the final line of the file does not end with a newline and
78 + * yet exactly fills the buffer, it will be treated as too long
79 + * even though there isn't really a problem. But it isn't really
80 + * worth adding code to deal with such an unlikely situation, and
81 + * we do err on the side of caution. Besides, the line would be
82 + * too long if it did end with a newline. */
83 + if (!strchr(key, '\n') && !feof(f)) {
84 + errmsg = "line too long";
88 + /* Trim leading and trailing whitespace, ignoring comments, and
89 + * check if the resulting string is empty. */
90 + key = get_trimmed_slice(key, strchrnul(key, '#'));
96 + e = strchr(key, '=');
99 + key = get_trimmed_slice(key, e);
102 + if (!e || !*key) { /* Missing '=' or empty key. */
103 + errmsg = "keyword";
106 + if (bad_env_var(key)) { /* Check for illegal characters */
107 + errmsg = "illegal character";
111 + /* Get the value */
112 + val = skip_whitespace(e+1); /* What's after the equal sign? */
114 + if (!*val) { /* Empty value */
118 + if (*val == '"' && val[(strlen(val)-1)] == '"') {
119 + /* We do not want to pass quoted strings to setenv. */
121 + val[strlen(val)-1] = 0;
124 + if (!getenv(key)) /* User vars > config vars */
131 + bb_error_msg("parse error in %s, line %u: %s", config_file, lc, errmsg);
134 # if ENABLE_FEATURE_SUID
135 static void check_suid(int applet_no)
136 @@ -802,9 +917,11 @@ int main(int argc UNUSED_PARAM, char **argv)
138 /* applet_names in this case is just "applet\0\0" */
139 lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv));
141 return SINGLE_APPLET_MAIN(argc, argv);
143 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
146 applet_name = argv[0];
147 if (applet_name[0] == '-')