diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-12-30 05:05:31 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-12-30 05:05:31 +0000 |
commit | 76ddc2e3e4837d0557fb6626394f87648e5f8c3b (patch) | |
tree | f545fe36c1ebc20c743ab28bc0df2b0f1d28b59d | |
parent | d6e8f9450cf055f0abfa424c5aa9e5a7c30d6593 (diff) | |
download | busybox-w32-76ddc2e3e4837d0557fb6626394f87648e5f8c3b.tar.gz busybox-w32-76ddc2e3e4837d0557fb6626394f87648e5f8c3b.tar.bz2 busybox-w32-76ddc2e3e4837d0557fb6626394f87648e5f8c3b.zip |
libbb: add bb_unsetenv (taken from hush).
udhcpc: stop filtering environment passed to the script.
crond: fix uncovered potential bug (failing unsetenv)
mdev: fix uncovered potential bug (failing unsetenv)
tcp, udpsvd: fix uncovered potential bug (failing unsetenv)
function old new delta
safe_setenv - 58 +58
bb_unsetenv - 55 +55
builtin_unset 139 138 -1
tcpudpsvd_main 1843 1830 -13
free_strings_and_unsetenv 87 53 -34
udhcp_run_script 1186 1133 -53
safe_setenv4 62 - -62
------------------------------------------------------------------------------
(add/remove: 2/1 grow/shrink: 0/4 up/down: 113/-163) Total: -50 bytes
-rw-r--r-- | include/libbb.h | 1 | ||||
-rw-r--r-- | libbb/xfuncs_printf.c | 23 | ||||
-rw-r--r-- | miscutils/crond.c | 12 | ||||
-rw-r--r-- | networking/tcpudp.c | 3 | ||||
-rw-r--r-- | networking/udhcp/script.c | 66 | ||||
-rw-r--r-- | shell/hush.c | 14 | ||||
-rw-r--r-- | util-linux/mdev.c | 3 |
7 files changed, 65 insertions, 57 deletions
diff --git a/include/libbb.h b/include/libbb.h index e0541a731..e1a6d120b 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -377,6 +377,7 @@ void xsetuid(uid_t uid) FAST_FUNC; | |||
377 | void xchdir(const char *path) FAST_FUNC; | 377 | void xchdir(const char *path) FAST_FUNC; |
378 | void xchroot(const char *path) FAST_FUNC; | 378 | void xchroot(const char *path) FAST_FUNC; |
379 | void xsetenv(const char *key, const char *value) FAST_FUNC; | 379 | void xsetenv(const char *key, const char *value) FAST_FUNC; |
380 | void bb_unsetenv(const char *key) FAST_FUNC; | ||
380 | void xunlink(const char *pathname) FAST_FUNC; | 381 | void xunlink(const char *pathname) FAST_FUNC; |
381 | void xstat(const char *pathname, struct stat *buf) FAST_FUNC; | 382 | void xstat(const char *pathname, struct stat *buf) FAST_FUNC; |
382 | int xopen(const char *pathname, int flags) FAST_FUNC FAST_FUNC; | 383 | int xopen(const char *pathname, int flags) FAST_FUNC FAST_FUNC; |
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 108e14043..46ae7ac60 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -333,6 +333,29 @@ void FAST_FUNC xsetenv(const char *key, const char *value) | |||
333 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 333 | bb_error_msg_and_die(bb_msg_memory_exhausted); |
334 | } | 334 | } |
335 | 335 | ||
336 | /* Handles "VAR=VAL" strings, even those which are part of environ | ||
337 | * _right now_ | ||
338 | */ | ||
339 | void FAST_FUNC bb_unsetenv(const char *var) | ||
340 | { | ||
341 | char *tp = strchr(var, '='); | ||
342 | |||
343 | if (!tp) { | ||
344 | unsetenv(var); | ||
345 | return; | ||
346 | } | ||
347 | |||
348 | /* In case var was putenv'ed, we can't replace '=' | ||
349 | * with NUL and unsetenv(var) - it won't work, | ||
350 | * env is modified by the replacement, unsetenv | ||
351 | * sees "VAR" instead of "VAR=VAL" and does not remove it! | ||
352 | * horror :( */ | ||
353 | tp = xstrndup(var, tp - var); | ||
354 | unsetenv(tp); | ||
355 | free(tp); | ||
356 | } | ||
357 | |||
358 | |||
336 | // Die with an error message if we can't set gid. (Because resource limits may | 359 | // Die with an error message if we can't set gid. (Because resource limits may |
337 | // limit this user to a given number of processes, and if that fills up the | 360 | // limit this user to a given number of processes, and if that fills up the |
338 | // setgid() will fail and we'll _still_be_root_, which is bad.) | 361 | // setgid() will fail and we'll _still_be_root_, which is bad.) |
diff --git a/miscutils/crond.c b/miscutils/crond.c index 732fbb147..12560fa36 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
@@ -252,14 +252,12 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
252 | /* We set environment *before* vfork (because we want to use vfork), | 252 | /* We set environment *before* vfork (because we want to use vfork), |
253 | * so we cannot use setenv() - repeated calls to setenv() may leak memory! | 253 | * so we cannot use setenv() - repeated calls to setenv() may leak memory! |
254 | * Using putenv(), and freeing memory after unsetenv() won't leak */ | 254 | * Using putenv(), and freeing memory after unsetenv() won't leak */ |
255 | static void safe_setenv4(char **pvar_val, const char *var, const char *val /*, int len*/) | 255 | static void safe_setenv(char **pvar_val, const char *var, const char *val) |
256 | { | 256 | { |
257 | const int len = 4; /* both var names are 4 char long */ | ||
258 | char *var_val = *pvar_val; | 257 | char *var_val = *pvar_val; |
259 | 258 | ||
260 | if (var_val) { | 259 | if (var_val) { |
261 | var_val[len] = '\0'; /* nuke '=' */ | 260 | bb_unsetenv(var_val); |
262 | unsetenv(var_val); | ||
263 | free(var_val); | 261 | free(var_val); |
264 | } | 262 | } |
265 | *pvar_val = xasprintf("%s=%s", var, val); | 263 | *pvar_val = xasprintf("%s=%s", var, val); |
@@ -270,10 +268,10 @@ static void safe_setenv4(char **pvar_val, const char *var, const char *val /*, i | |||
270 | static void SetEnv(struct passwd *pas) | 268 | static void SetEnv(struct passwd *pas) |
271 | { | 269 | { |
272 | #if SETENV_LEAKS | 270 | #if SETENV_LEAKS |
273 | safe_setenv4(&env_var_user, "USER", pas->pw_name); | 271 | safe_setenv(&env_var_user, "USER", pas->pw_name); |
274 | safe_setenv4(&env_var_home, "HOME", pas->pw_dir); | 272 | safe_setenv(&env_var_home, "HOME", pas->pw_dir); |
275 | /* if we want to set user's shell instead: */ | 273 | /* if we want to set user's shell instead: */ |
276 | /*safe_setenv(env_var_user, "SHELL", pas->pw_shell, 5);*/ | 274 | /*safe_setenv(env_var_user, "SHELL", pas->pw_shell);*/ |
277 | #else | 275 | #else |
278 | xsetenv("USER", pas->pw_name); | 276 | xsetenv("USER", pas->pw_name); |
279 | xsetenv("HOME", pas->pw_dir); | 277 | xsetenv("HOME", pas->pw_dir); |
diff --git a/networking/tcpudp.c b/networking/tcpudp.c index 3b73f213f..55a3e0899 100644 --- a/networking/tcpudp.c +++ b/networking/tcpudp.c | |||
@@ -85,8 +85,7 @@ static void undo_xsetenv(void) | |||
85 | char **pp = env_cur = &env_var[0]; | 85 | char **pp = env_cur = &env_var[0]; |
86 | while (*pp) { | 86 | while (*pp) { |
87 | char *var = *pp; | 87 | char *var = *pp; |
88 | *strchrnul(var, '=') = '\0'; | 88 | bb_unsetenv(var); |
89 | unsetenv(var); | ||
90 | free(var); | 89 | free(var); |
91 | *pp++ = NULL; | 90 | *pp++ = NULL; |
92 | } | 91 | } |
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c index 4ae17fb8d..5d42a45db 100644 --- a/networking/udhcp/script.c +++ b/networking/udhcp/script.c | |||
@@ -119,7 +119,8 @@ static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p, | |||
119 | } | 119 | } |
120 | option += optlen; | 120 | option += optlen; |
121 | len -= optlen; | 121 | len -= optlen; |
122 | if (len <= 0) break; | 122 | if (len <= 0) |
123 | break; | ||
123 | dest += sprintf(dest, " "); | 124 | dest += sprintf(dest, " "); |
124 | } | 125 | } |
125 | return ret; | 126 | return ret; |
@@ -130,9 +131,8 @@ static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p, | |||
130 | static char **fill_envp(struct dhcpMessage *packet) | 131 | static char **fill_envp(struct dhcpMessage *packet) |
131 | { | 132 | { |
132 | int num_options = 0; | 133 | int num_options = 0; |
133 | int i, j; | 134 | int i; |
134 | char **envp; | 135 | char **envp, **curr; |
135 | char *var; | ||
136 | const char *opt_name; | 136 | const char *opt_name; |
137 | uint8_t *temp; | 137 | uint8_t *temp; |
138 | char over = 0; | 138 | char over = 0; |
@@ -156,21 +156,16 @@ static char **fill_envp(struct dhcpMessage *packet) | |||
156 | num_options++; | 156 | num_options++; |
157 | } | 157 | } |
158 | 158 | ||
159 | envp = xzalloc(sizeof(char *) * (num_options + 5)); | 159 | curr = envp = xzalloc(sizeof(char *) * (num_options + 3)); |
160 | j = 0; | 160 | *curr = xasprintf("interface=%s", client_config.interface); |
161 | envp[j++] = xasprintf("interface=%s", client_config.interface); | 161 | putenv(*curr++); |
162 | var = getenv("PATH"); | ||
163 | if (var) | ||
164 | envp[j++] = xasprintf("PATH=%s", var); | ||
165 | var = getenv("HOME"); | ||
166 | if (var) | ||
167 | envp[j++] = xasprintf("HOME=%s", var); | ||
168 | 162 | ||
169 | if (packet == NULL) | 163 | if (packet == NULL) |
170 | return envp; | 164 | return envp; |
171 | 165 | ||
172 | envp[j] = xmalloc(sizeof("ip=255.255.255.255")); | 166 | *curr = xmalloc(sizeof("ip=255.255.255.255")); |
173 | sprintip(envp[j++], "ip=", (uint8_t *) &packet->yiaddr); | 167 | sprintip(*curr, "ip=", (uint8_t *) &packet->yiaddr); |
168 | putenv(*curr++); | ||
174 | 169 | ||
175 | opt_name = dhcp_option_strings; | 170 | opt_name = dhcp_option_strings; |
176 | i = 0; | 171 | i = 0; |
@@ -178,31 +173,36 @@ static char **fill_envp(struct dhcpMessage *packet) | |||
178 | temp = get_option(packet, dhcp_options[i].code); | 173 | temp = get_option(packet, dhcp_options[i].code); |
179 | if (!temp) | 174 | if (!temp) |
180 | goto next; | 175 | goto next; |
181 | envp[j++] = alloc_fill_opts(temp, &dhcp_options[i], opt_name); | 176 | *curr = alloc_fill_opts(temp, &dhcp_options[i], opt_name); |
177 | putenv(*curr++); | ||
182 | 178 | ||
183 | /* Fill in a subnet bits option for things like /24 */ | 179 | /* Fill in a subnet bits option for things like /24 */ |
184 | if (dhcp_options[i].code == DHCP_SUBNET) { | 180 | if (dhcp_options[i].code == DHCP_SUBNET) { |
185 | uint32_t subnet; | 181 | uint32_t subnet; |
186 | move_from_unaligned32(subnet, temp); | 182 | move_from_unaligned32(subnet, temp); |
187 | envp[j++] = xasprintf("mask=%d", mton(subnet)); | 183 | *curr = xasprintf("mask=%d", mton(subnet)); |
184 | putenv(*curr++); | ||
188 | } | 185 | } |
189 | next: | 186 | next: |
190 | opt_name += strlen(opt_name) + 1; | 187 | opt_name += strlen(opt_name) + 1; |
191 | i++; | 188 | i++; |
192 | } | 189 | } |
193 | if (packet->siaddr) { | 190 | if (packet->siaddr) { |
194 | envp[j] = xmalloc(sizeof("siaddr=255.255.255.255")); | 191 | *curr = xmalloc(sizeof("siaddr=255.255.255.255")); |
195 | sprintip(envp[j++], "siaddr=", (uint8_t *) &packet->siaddr); | 192 | sprintip(*curr, "siaddr=", (uint8_t *) &packet->siaddr); |
193 | putenv(*curr++); | ||
196 | } | 194 | } |
197 | if (!(over & FILE_FIELD) && packet->file[0]) { | 195 | if (!(over & FILE_FIELD) && packet->file[0]) { |
198 | /* watch out for invalid packets */ | 196 | /* watch out for invalid packets */ |
199 | packet->file[sizeof(packet->file) - 1] = '\0'; | 197 | packet->file[sizeof(packet->file) - 1] = '\0'; |
200 | envp[j++] = xasprintf("boot_file=%s", packet->file); | 198 | *curr = xasprintf("boot_file=%s", packet->file); |
199 | putenv(*curr++); | ||
201 | } | 200 | } |
202 | if (!(over & SNAME_FIELD) && packet->sname[0]) { | 201 | if (!(over & SNAME_FIELD) && packet->sname[0]) { |
203 | /* watch out for invalid packets */ | 202 | /* watch out for invalid packets */ |
204 | packet->sname[sizeof(packet->sname) - 1] = '\0'; | 203 | packet->sname[sizeof(packet->sname) - 1] = '\0'; |
205 | envp[j++] = xasprintf("sname=%s", packet->sname); | 204 | *curr = xasprintf("sname=%s", packet->sname); |
205 | putenv(*curr++); | ||
206 | } | 206 | } |
207 | return envp; | 207 | return envp; |
208 | } | 208 | } |
@@ -211,29 +211,25 @@ static char **fill_envp(struct dhcpMessage *packet) | |||
211 | /* Call a script with a par file and env vars */ | 211 | /* Call a script with a par file and env vars */ |
212 | void FAST_FUNC udhcp_run_script(struct dhcpMessage *packet, const char *name) | 212 | void FAST_FUNC udhcp_run_script(struct dhcpMessage *packet, const char *name) |
213 | { | 213 | { |
214 | int pid; | ||
215 | char **envp, **curr; | 214 | char **envp, **curr; |
215 | char *argv[3]; | ||
216 | 216 | ||
217 | if (client_config.script == NULL) | 217 | if (client_config.script == NULL) |
218 | return; | 218 | return; |
219 | 219 | ||
220 | DEBUG("vfork'ing and execle'ing %s", client_config.script); | 220 | DEBUG("vfork'ing and exec'ing %s", client_config.script); |
221 | 221 | ||
222 | envp = fill_envp(packet); | 222 | envp = fill_envp(packet); |
223 | 223 | ||
224 | /* call script */ | 224 | /* call script */ |
225 | // can we use wait4pid(spawn(...)) here? | 225 | argv[0] = (char*) client_config.script; |
226 | pid = vfork(); | 226 | argv[1] = (char*) name; |
227 | if (pid < 0) return; | 227 | argv[2] = NULL; |
228 | if (pid == 0) { | 228 | wait4pid(spawn(argv)); |
229 | /* close fd's? */ | 229 | |
230 | /* exec script */ | 230 | for (curr = envp; *curr; curr++) { |
231 | execle(client_config.script, client_config.script, | 231 | bb_unsetenv(*curr); |
232 | name, NULL, envp); | ||
233 | bb_perror_msg_and_die("exec %s", client_config.script); | ||
234 | } | ||
235 | safe_waitpid(pid, NULL, 0); | ||
236 | for (curr = envp; *curr; curr++) | ||
237 | free(*curr); | 232 | free(*curr); |
233 | } | ||
238 | free(envp); | 234 | free(envp); |
239 | } | 235 | } |
diff --git a/shell/hush.c b/shell/hush.c index eafcbb4c9..3b87855b6 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -730,16 +730,8 @@ static void free_strings_and_unsetenv(char **strings, int unset) | |||
730 | v = strings; | 730 | v = strings; |
731 | while (*v) { | 731 | while (*v) { |
732 | if (unset) { | 732 | if (unset) { |
733 | char *copy; | 733 | debug_printf_env("unsetenv '%s'\n", *v); |
734 | /* *strchrnul(*v, '=') = '\0'; -- BAD | 734 | bb_unsetenv(*v); |
735 | * In case *v was putenv'ed, we can't | ||
736 | * unsetenv(*v) after taking out '=': | ||
737 | * it won't work, env is modified by taking out! | ||
738 | * horror :( */ | ||
739 | copy = xstrndup(*v, strchrnul(*v, '=') - *v); | ||
740 | debug_printf_env("unsetenv '%s'\n", copy); | ||
741 | unsetenv(copy); | ||
742 | free(copy); | ||
743 | } | 735 | } |
744 | free(*v++); | 736 | free(*v++); |
745 | } | 737 | } |
@@ -2937,7 +2929,7 @@ static void unset_local_var(const char *name) | |||
2937 | * is ro, and we cannot reach this code on the 1st pass */ | 2929 | * is ro, and we cannot reach this code on the 1st pass */ |
2938 | prev->next = cur->next; | 2930 | prev->next = cur->next; |
2939 | debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr); | 2931 | debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr); |
2940 | unsetenv(cur->varstr); | 2932 | bb_unsetenv(cur->varstr); |
2941 | if (!cur->max_len) | 2933 | if (!cur->max_len) |
2942 | free(cur->varstr); | 2934 | free(cur->varstr); |
2943 | free(cur); | 2935 | free(cur); |
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 34cabc934..956de15ae 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
@@ -276,8 +276,7 @@ static void make_device(char *path, int delete) | |||
276 | putenv(s); | 276 | putenv(s); |
277 | if (system(command) == -1) | 277 | if (system(command) == -1) |
278 | bb_perror_msg_and_die("can't run '%s'", command); | 278 | bb_perror_msg_and_die("can't run '%s'", command); |
279 | s[4] = '\0'; | 279 | unsetenv("MDEV"); |
280 | unsetenv(s); | ||
281 | free(s); | 280 | free(s); |
282 | free(command); | 281 | free(command); |
283 | } | 282 | } |