aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-05-08 23:26:16 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-05-08 23:26:16 +0200
commit19afe848eca8d3baf149cd7ed715489403360287 (patch)
treeaf410f580b86bcb37b463828e3bc60c03a855df6
parent7b48eb4372c0b639bcb1eaedd63795c2dc0d9820 (diff)
downloadbusybox-w32-19afe848eca8d3baf149cd7ed715489403360287.tar.gz
busybox-w32-19afe848eca8d3baf149cd7ed715489403360287.tar.bz2
busybox-w32-19afe848eca8d3baf149cd7ed715489403360287.zip
ifplugd: replace potentially-leaking setenv with malloc/putenv/free
text data bss dec hex filename 842657 453 6828 849938 cf812 busybox_old 842722 453 6828 850003 cf853 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ifplugd.c103
1 files changed, 20 insertions, 83 deletions
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index 41b04c4ed..01a7a49e5 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -93,6 +93,7 @@ enum { // constant fds
93 93
94struct globals { 94struct globals {
95 smallint iface_last_status; 95 smallint iface_last_status;
96 smallint iface_prev_status;
96 smallint iface_exists; 97 smallint iface_exists;
97 98
98 /* Used in getopt32, must have sizeof == sizeof(int) */ 99 /* Used in getopt32, must have sizeof == sizeof(int) */
@@ -121,97 +122,42 @@ struct globals {
121} while (0) 122} while (0)
122 123
123 124
125static const char *strstatus(int status)
126{
127 if (status == IFSTATUS_ERR)
128 return "error";
129 return "down\0up" + (status * 5);
130}
131
124static int run_script(const char *action) 132static int run_script(const char *action)
125{ 133{
134 char *env_PREVIOUS, *env_CURRENT;
126 char *argv[5]; 135 char *argv[5];
127 int r; 136 int r;
128 137
129 bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action); 138 bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action);
130 139
131#if 1
132
133 argv[0] = (char*) G.script_name; 140 argv[0] = (char*) G.script_name;
134 argv[1] = (char*) G.iface; 141 argv[1] = (char*) G.iface;
135 argv[2] = (char*) action; 142 argv[2] = (char*) action;
136 argv[3] = (char*) G.extra_arg; 143 argv[3] = (char*) G.extra_arg;
137 argv[4] = NULL; 144 argv[4] = NULL;
138 145
146 env_PREVIOUS = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_prev_status));
147 putenv(env_PREVIOUS);
148 env_CURRENT = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_last_status));
149 putenv(env_CURRENT);
150
139 /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */ 151 /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */
140 r = spawn_and_wait(argv); 152 r = spawn_and_wait(argv);
141 153
154 unsetenv(IFPLUGD_ENV_PREVIOUS);
155 unsetenv(IFPLUGD_ENV_CURRENT);
156 free(env_PREVIOUS);
157 free(env_CURRENT);
158
142 bb_error_msg("exit code: %d", r & 0xff); 159 bb_error_msg("exit code: %d", r & 0xff);
143 return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r; 160 return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r;
144
145#else /* insanity */
146
147 struct fd_pair pipe_pair;
148 char buf[256];
149 int i = 0;
150
151 xpiped_pair(pipe_pair);
152
153 pid = vfork();
154 if (pid < 0) {
155 bb_perror_msg("fork");
156 return -1;
157 }
158
159 /* child */
160 if (pid == 0) {
161 xmove_fd(pipe_pair.wr, 1);
162 xdup2(1, 2);
163 if (pipe_pair.rd > 2)
164 close(pipe_pair.rd);
165
166 // umask(0022); // Set up a sane umask
167
168 execlp(G.script_name, G.script_name, G.iface, action, G.extra_arg, NULL);
169 _exit(EXIT_FAILURE);
170 }
171
172 /* parent */
173 close(pipe_pair.wr);
174
175 while (1) {
176 if (bb_got_signal && bb_got_signal != SIGCHLD) {
177 bb_error_msg("killing child");
178 kill(pid, SIGTERM);
179 bb_got_signal = 0;
180 break;
181 }
182
183 r = read(pipe_pair.rd, &buf[i], 1);
184
185 if (buf[i] == '\n' || i == sizeof(buf)-2 || r != 1) {
186 if (r == 1 && buf[i] != '\n')
187 i++;
188
189 buf[i] = '\0';
190
191 if (i > 0)
192 bb_error_msg("client: %s", buf);
193
194 i = 0;
195 } else {
196 i++;
197 }
198
199 if (r != 1)
200 break;
201 }
202
203 close(pipe_pair.rd);
204
205 wait(&r);
206
207 if (!WIFEXITED(r) || WEXITSTATUS(r) != 0) {
208 bb_error_msg("program execution failed, return value is %i",
209 WEXITSTATUS(r));
210 return option_mask32 & FLAG_IGNORE_RETVAL ? 0 : WEXITSTATUS(r);
211 }
212 bb_error_msg("program executed successfully");
213 return 0;
214#endif
215} 161}
216 162
217static int network_ioctl(int request, void* data, const char *errmsg) 163static int network_ioctl(int request, void* data, const char *errmsg)
@@ -228,13 +174,6 @@ static void set_ifreq_to_ifname(struct ifreq *ifreq)
228 strncpy_IFNAMSIZ(ifreq->ifr_name, G.iface); 174 strncpy_IFNAMSIZ(ifreq->ifr_name, G.iface);
229} 175}
230 176
231static const char *strstatus(int status)
232{
233 if (status == IFSTATUS_ERR)
234 return "error";
235 return "down\0up" + (status * 5);
236}
237
238static void up_iface(void) 177static void up_iface(void)
239{ 178{
240 struct ifreq ifrequest; 179 struct ifreq ifrequest;
@@ -474,9 +413,7 @@ static smallint detect_link(void)
474 } 413 }
475 414
476 if (status != G.iface_last_status) { 415 if (status != G.iface_last_status) {
477//TODO: is it safe to repeatedly do this? 416 G.iface_prev_status = G.iface_last_status;
478 setenv(IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_last_status), 1);
479 setenv(IFPLUGD_ENV_CURRENT, strstatus(status), 1);
480 G.iface_last_status = status; 417 G.iface_last_status = status;
481 } 418 }
482 419