diff options
author | Ron Yorston <rmy@pobox.com> | 2018-02-13 11:54:43 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-02-13 11:54:43 +0000 |
commit | 834805db9fe525dff26267fb7ba2794cee3ed51a (patch) | |
tree | 3354ca2d465dce743685d0a4b41936d91a2b4d37 | |
parent | 5bf7067e61f202f023d70f38d14bb66799a27074 (diff) | |
download | busybox-w32-834805db9fe525dff26267fb7ba2794cee3ed51a.tar.gz busybox-w32-834805db9fe525dff26267fb7ba2794cee3ed51a.tar.bz2 busybox-w32-834805db9fe525dff26267fb7ba2794cee3ed51a.zip |
win32: always use safe API calls to manipulate environment
It turns out that with the new toolchain safe API calls work on all
all platforms. Even the original code from commit fa147bd7e works
on Windows XP when built with the new tools.
- Remove the unsafe environment manipulation via the environ array
- Microsoft's putenv takes a copy of its argument so the string
can be freed
- Rewrite some routines and add more error checking
-rw-r--r-- | Config.in | 10 | ||||
-rw-r--r-- | configs/mingw32_defconfig | 1 | ||||
-rw-r--r-- | configs/mingw64_defconfig | 1 | ||||
-rw-r--r-- | include/mingw.h | 6 | ||||
-rw-r--r-- | win32/env.c | 126 |
5 files changed, 26 insertions, 118 deletions
@@ -134,16 +134,6 @@ config GLOBBING | |||
134 | the BusyBox binary to handle wildcard expansion using the C runtime | 134 | the BusyBox binary to handle wildcard expansion using the C runtime |
135 | set this to 'Y'. | 135 | set this to 'Y'. |
136 | 136 | ||
137 | config SAFE_ENV | ||
138 | bool "Manipulate the environment through safe API calls" | ||
139 | default n | ||
140 | depends on PLATFORM_MINGW32 | ||
141 | help | ||
142 | Enable this option to use safe API calls when clearing environment | ||
143 | variables. This is necessary if BusyBox is to run on ReactOS or | ||
144 | 64-bit Windows. The default is 'N', which must be used if BusyBox | ||
145 | is to run on Windows XP. | ||
146 | |||
147 | config PAM | 137 | config PAM |
148 | bool "Support PAM (Pluggable Authentication Modules)" | 138 | bool "Support PAM (Pluggable Authentication Modules)" |
149 | default n | 139 | default n |
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index 4adc4471e..5ed8cd41f 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig | |||
@@ -20,7 +20,6 @@ CONFIG_FEATURE_VERBOSE_USAGE=y | |||
20 | CONFIG_FEATURE_COMPRESS_USAGE=y | 20 | CONFIG_FEATURE_COMPRESS_USAGE=y |
21 | CONFIG_LFS=y | 21 | CONFIG_LFS=y |
22 | # CONFIG_GLOBBING is not set | 22 | # CONFIG_GLOBBING is not set |
23 | # CONFIG_SAFE_ENV is not set | ||
24 | # CONFIG_PAM is not set | 23 | # CONFIG_PAM is not set |
25 | # CONFIG_FEATURE_DEVPTS is not set | 24 | # CONFIG_FEATURE_DEVPTS is not set |
26 | # CONFIG_FEATURE_UTMP is not set | 25 | # CONFIG_FEATURE_UTMP is not set |
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig index fdc755d93..2c189700a 100644 --- a/configs/mingw64_defconfig +++ b/configs/mingw64_defconfig | |||
@@ -20,7 +20,6 @@ CONFIG_FEATURE_VERBOSE_USAGE=y | |||
20 | CONFIG_FEATURE_COMPRESS_USAGE=y | 20 | CONFIG_FEATURE_COMPRESS_USAGE=y |
21 | CONFIG_LFS=y | 21 | CONFIG_LFS=y |
22 | # CONFIG_GLOBBING is not set | 22 | # CONFIG_GLOBBING is not set |
23 | CONFIG_SAFE_ENV=y | ||
24 | # CONFIG_PAM is not set | 23 | # CONFIG_PAM is not set |
25 | # CONFIG_FEATURE_DEVPTS is not set | 24 | # CONFIG_FEATURE_DEVPTS is not set |
26 | # CONFIG_FEATURE_UTMP is not set | 25 | # CONFIG_FEATURE_UTMP is not set |
diff --git a/include/mingw.h b/include/mingw.h index 87abd077b..6f69913d6 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -195,16 +195,10 @@ char *mingw_mktemp(char *template); | |||
195 | int mkstemp(char *template); | 195 | int mkstemp(char *template); |
196 | char *realpath(const char *path, char *resolved_path); | 196 | char *realpath(const char *path, char *resolved_path); |
197 | int setenv(const char *name, const char *value, int replace); | 197 | int setenv(const char *name, const char *value, int replace); |
198 | #if ENABLE_SAFE_ENV | ||
199 | int unsetenv(const char *env); | 198 | int unsetenv(const char *env); |
200 | #else | ||
201 | void unsetenv(const char *env); | ||
202 | #endif | ||
203 | 199 | ||
204 | #define getenv mingw_getenv | 200 | #define getenv mingw_getenv |
205 | #if ENABLE_SAFE_ENV | ||
206 | #define putenv mingw_putenv | 201 | #define putenv mingw_putenv |
207 | #endif | ||
208 | #define mktemp mingw_mktemp | 202 | #define mktemp mingw_mktemp |
209 | 203 | ||
210 | /* | 204 | /* |
diff --git a/win32/env.c b/win32/env.c index eab3c1708..2837c0720 100644 --- a/win32/env.c +++ b/win32/env.c | |||
@@ -1,19 +1,8 @@ | |||
1 | #include "libbb.h" | 1 | #include "libbb.h" |
2 | 2 | ||
3 | static int lookup_env(char **env, const char *name, size_t nmln) | ||
4 | { | ||
5 | int i; | ||
6 | |||
7 | for (i = 0; env[i]; i++) { | ||
8 | if (0 == strncmp(env[i], name, nmln) | ||
9 | && '=' == env[i][nmln]) | ||
10 | /* matches */ | ||
11 | return i; | ||
12 | } | ||
13 | return -1; | ||
14 | } | ||
15 | |||
16 | #undef getenv | 3 | #undef getenv |
4 | #undef putenv | ||
5 | |||
17 | char *mingw_getenv(const char *name) | 6 | char *mingw_getenv(const char *name) |
18 | { | 7 | { |
19 | char *result = getenv(name); | 8 | char *result = getenv(name); |
@@ -29,70 +18,21 @@ char *mingw_getenv(const char *name) | |||
29 | int setenv(const char *name, const char *value, int replace) | 18 | int setenv(const char *name, const char *value, int replace) |
30 | { | 19 | { |
31 | int out; | 20 | int out; |
32 | size_t namelen, valuelen; | ||
33 | char *envstr; | 21 | char *envstr; |
34 | 22 | ||
35 | if (!name || !value) return -1; | 23 | if (!name || !*name || strchr(name, '=') || !value) return -1; |
36 | if (!replace) { | 24 | if (!replace) { |
37 | char *oldval = NULL; | 25 | if (getenv(name)) return 0; |
38 | oldval = getenv(name); | ||
39 | if (oldval) return 0; | ||
40 | } | 26 | } |
41 | 27 | ||
42 | namelen = strlen(name); | 28 | envstr = xasprintf("%s=%s", name, value); |
43 | valuelen = strlen(value); | 29 | out = mingw_putenv(envstr); |
44 | envstr = malloc((namelen + valuelen + 2)); | 30 | free(envstr); |
45 | if (!envstr) return -1; | ||
46 | |||
47 | memcpy(envstr, name, namelen); | ||
48 | envstr[namelen] = '='; | ||
49 | memcpy(envstr + namelen + 1, value, valuelen); | ||
50 | envstr[namelen + valuelen + 1] = 0; | ||
51 | |||
52 | out = putenv(envstr); | ||
53 | /* putenv(3) makes the argument string part of the environment, | ||
54 | * and changing that string modifies the environment --- which | ||
55 | * means we do not own that storage anymore. Do not free | ||
56 | * envstr. | ||
57 | */ | ||
58 | 31 | ||
59 | return out; | 32 | return out; |
60 | } | 33 | } |
61 | 34 | ||
62 | /* | 35 | /* |
63 | * If name contains '=', then sets the variable, otherwise it unsets it | ||
64 | */ | ||
65 | char **env_setenv(char **env, const char *name) | ||
66 | { | ||
67 | char *eq = strchrnul(name, '='); | ||
68 | int i = lookup_env(env, name, eq-name); | ||
69 | |||
70 | if (i < 0) { | ||
71 | if (*eq) { | ||
72 | for (i = 0; env[i]; i++) | ||
73 | ; | ||
74 | env = xrealloc(env, (i+2)*sizeof(*env)); | ||
75 | env[i] = xstrdup(name); | ||
76 | env[i+1] = NULL; | ||
77 | } | ||
78 | } | ||
79 | else { | ||
80 | free(env[i]); | ||
81 | if (*eq) | ||
82 | env[i] = xstrdup(name); | ||
83 | else { | ||
84 | for (; env[i]; i++) | ||
85 | env[i] = env[i+1]; | ||
86 | #if !ENABLE_SAFE_ENV | ||
87 | SetEnvironmentVariable(name, NULL); | ||
88 | #endif | ||
89 | } | ||
90 | } | ||
91 | return env; | ||
92 | } | ||
93 | |||
94 | #if ENABLE_SAFE_ENV | ||
95 | /* | ||
96 | * Removing an environment variable with WIN32 putenv requires an argument | 36 | * Removing an environment variable with WIN32 putenv requires an argument |
97 | * like "NAME="; glibc omits the '='. The implementations of unsetenv and | 37 | * like "NAME="; glibc omits the '='. The implementations of unsetenv and |
98 | * clearenv allow for this. | 38 | * clearenv allow for this. |
@@ -100,28 +40,34 @@ char **env_setenv(char **env, const char *name) | |||
100 | * It isn't possible to create an environment variable with an empty value | 40 | * It isn't possible to create an environment variable with an empty value |
101 | * using WIN32 putenv. | 41 | * using WIN32 putenv. |
102 | */ | 42 | */ |
103 | #undef putenv | 43 | int unsetenv(const char *name) |
104 | int unsetenv(const char *env) | ||
105 | { | 44 | { |
106 | char *name; | 45 | char *envstr; |
107 | int ret; | 46 | int ret; |
108 | 47 | ||
109 | name = xmalloc(strlen(env)+2); | 48 | if (!name || !*name || strchr(name, '=') ) { |
110 | strcat(strcpy(name, env), "="); | 49 | return -1; |
111 | ret = putenv(name); | 50 | } |
112 | free(name); | 51 | |
52 | envstr = xmalloc(strlen(name)+2); | ||
53 | strcat(strcpy(envstr, name), "="); | ||
54 | ret = putenv(envstr); | ||
55 | free(envstr); | ||
113 | 56 | ||
114 | return ret; | 57 | return ret; |
115 | } | 58 | } |
116 | 59 | ||
117 | int clearenv(void) | 60 | int clearenv(void) |
118 | { | 61 | { |
119 | char *name, *s; | 62 | char *envp, *name, *s; |
120 | 63 | ||
121 | while ( environ && *environ ) { | 64 | while ( environ && (envp=*environ) ) { |
122 | if ( (s=strchr(*environ, '=')) != NULL ) { | 65 | if ( (s=strchr(envp, '=')) != NULL ) { |
123 | name = xstrndup(*environ, s-*environ+1); | 66 | name = xstrndup(envp, s-envp+1); |
124 | putenv(name); | 67 | if ( putenv(name) == -1 ) { |
68 | free(name); | ||
69 | return -1; | ||
70 | } | ||
125 | free(name); | 71 | free(name); |
126 | } | 72 | } |
127 | else { | 73 | else { |
@@ -146,23 +92,3 @@ int mingw_putenv(const char *env) | |||
146 | /* can't set empty value */ | 92 | /* can't set empty value */ |
147 | return 0; | 93 | return 0; |
148 | } | 94 | } |
149 | #else | ||
150 | void unsetenv(const char *env) | ||
151 | { | ||
152 | env_setenv(environ, env); | ||
153 | } | ||
154 | |||
155 | int clearenv(void) | ||
156 | { | ||
157 | char **env = environ; | ||
158 | if (!env) | ||
159 | return 0; | ||
160 | while (*env) { | ||
161 | free(*env); | ||
162 | env++; | ||
163 | } | ||
164 | free(env); | ||
165 | environ = NULL; | ||
166 | return 0; | ||
167 | } | ||
168 | #endif | ||