diff options
-rw-r--r-- | applets/applets.c | 159 | ||||
-rw-r--r-- | libbb/xfuncs.c | 16 |
2 files changed, 88 insertions, 87 deletions
diff --git a/applets/applets.c b/applets/applets.c index 7245ecedc..b4580a5b4 100644 --- a/applets/applets.c +++ b/applets/applets.c | |||
@@ -48,16 +48,14 @@ static const char usage_messages[] = | |||
48 | 48 | ||
49 | static struct BB_applet *applet_using; | 49 | static struct BB_applet *applet_using; |
50 | 50 | ||
51 | /* The -1 arises because of the {0,NULL,0,-1} entry above. */ | 51 | /* The -1 arises because of the {0,NULL,0,-1} entry. */ |
52 | const unsigned short NUM_APPLETS = (sizeof (applets) / sizeof (struct BB_applet) - 1); | 52 | const unsigned short NUM_APPLETS = (sizeof(applets) / sizeof(struct BB_applet) - 1); |
53 | 53 | ||
54 | 54 | ||
55 | #ifdef CONFIG_FEATURE_SUID_CONFIG | 55 | #if ENABLE_FEATURE_SUID_CONFIG |
56 | 56 | ||
57 | #include <ctype.h> | 57 | #include <ctype.h> |
58 | 58 | ||
59 | #define CONFIG_FILE "/etc/busybox.conf" | ||
60 | |||
61 | /* applets [] is const, so we have to define this "override" structure */ | 59 | /* applets [] is const, so we have to define this "override" structure */ |
62 | static struct BB_suid_config | 60 | static struct BB_suid_config |
63 | { | 61 | { |
@@ -114,7 +112,7 @@ static char *get_trimmed_slice(char *s, char *e) | |||
114 | #define parse_error(x) do { errmsg = x; goto pe_label; } while(0) | 112 | #define parse_error(x) do { errmsg = x; goto pe_label; } while(0) |
115 | 113 | ||
116 | /* Don't depend on the tools to combine strings. */ | 114 | /* Don't depend on the tools to combine strings. */ |
117 | static const char config_file[] = CONFIG_FILE; | 115 | static const char config_file[] = "/etc/busybox.conf"; |
118 | 116 | ||
119 | /* There are 4 chars + 1 nul for each of user/group/other. */ | 117 | /* There are 4 chars + 1 nul for each of user/group/other. */ |
120 | static const char mode_chars[] = "Ssx-\0Ssx-\0Ttx-"; | 118 | static const char mode_chars[] = "Ssx-\0Ssx-\0Ttx-"; |
@@ -142,14 +140,14 @@ static void parse_config_file(void) | |||
142 | char buffer[256]; | 140 | char buffer[256]; |
143 | struct stat st; | 141 | struct stat st; |
144 | 142 | ||
145 | assert(!suid_config); /* Should be set to NULL by bss init. */ | 143 | assert(!suid_config); /* Should be set to NULL by bss init. */ |
146 | 144 | ||
147 | if ((stat(config_file, &st) != 0) /* No config file? */ | 145 | if ((stat(config_file, &st) != 0) /* No config file? */ |
148 | || !S_ISREG(st.st_mode) /* Not a regular file? */ | 146 | || !S_ISREG(st.st_mode) /* Not a regular file? */ |
149 | || (st.st_uid != 0) /* Not owned by root? */ | 147 | || (st.st_uid != 0) /* Not owned by root? */ |
150 | || (st.st_mode & (S_IWGRP | S_IWOTH)) /* Writable by non-root? */ | 148 | || (st.st_mode & (S_IWGRP | S_IWOTH)) /* Writable by non-root? */ |
151 | || !(f = fopen(config_file, "r")) /* Cannot open? */ | 149 | || !(f = fopen(config_file, "r")) /* Cannot open? */ |
152 | ) { | 150 | ) { |
153 | return; | 151 | return; |
154 | } | 152 | } |
155 | 153 | ||
@@ -185,7 +183,8 @@ static void parse_config_file(void) | |||
185 | 183 | ||
186 | /* Trim leading and trailing whitespace, ignoring comments, and | 184 | /* Trim leading and trailing whitespace, ignoring comments, and |
187 | * check if the resulting string is empty. */ | 185 | * check if the resulting string is empty. */ |
188 | if (!*(s = get_trimmed_slice(s, strchrnul(s, '#')))) { | 186 | s = get_trimmed_slice(s, strchrnul(s, '#')); |
187 | if (!*s) { | ||
189 | continue; | 188 | continue; |
190 | } | 189 | } |
191 | 190 | ||
@@ -195,10 +194,11 @@ static void parse_config_file(void) | |||
195 | /* Unlike the old code, we ignore leading and trailing | 194 | /* Unlike the old code, we ignore leading and trailing |
196 | * whitespace for the section name. We also require that | 195 | * whitespace for the section name. We also require that |
197 | * there are no stray characters after the closing bracket. */ | 196 | * there are no stray characters after the closing bracket. */ |
198 | if (!(e = strchr(s, ']')) /* Missing right bracket? */ | 197 | e = strchr(s, ']'); |
199 | || e[1] /* Trailing characters? */ | 198 | if (!e /* Missing right bracket? */ |
200 | || !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */ | 199 | || e[1] /* Trailing characters? */ |
201 | ) { | 200 | || !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */ |
201 | ) { | ||
202 | parse_error("section header"); | 202 | parse_error("section header"); |
203 | } | 203 | } |
204 | /* Right now we only have one section so just check it. | 204 | /* Right now we only have one section so just check it. |
@@ -224,7 +224,8 @@ static void parse_config_file(void) | |||
224 | * where both key and value could contain inner whitespace. */ | 224 | * where both key and value could contain inner whitespace. */ |
225 | 225 | ||
226 | /* First get the key (an applet name in our case). */ | 226 | /* First get the key (an applet name in our case). */ |
227 | if (!!(e = strchr(s, '='))) { | 227 | e = strchr(s, '='); |
228 | if (e) { | ||
228 | s = get_trimmed_slice(s, e); | 229 | s = get_trimmed_slice(s, e); |
229 | } | 230 | } |
230 | if (!e || !*s) { /* Missing '=' or empty key. */ | 231 | if (!e || !*s) { /* Missing '=' or empty key. */ |
@@ -235,7 +236,8 @@ static void parse_config_file(void) | |||
235 | * applet is currently built in and ignore it otherwise. | 236 | * applet is currently built in and ignore it otherwise. |
236 | * Note: This can hide config file bugs which only pop | 237 | * Note: This can hide config file bugs which only pop |
237 | * up when the busybox configuration is changed. */ | 238 | * up when the busybox configuration is changed. */ |
238 | if ((applet = find_applet_by_name(s))) { | 239 | applet = find_applet_by_name(s); |
240 | if (applet) { | ||
239 | /* Note: We currently don't check for duplicates! | 241 | /* Note: We currently don't check for duplicates! |
240 | * The last config line for each applet will be the | 242 | * The last config line for each applet will be the |
241 | * one used since we insert at the head of the list. | 243 | * one used since we insert at the head of the list. |
@@ -250,9 +252,10 @@ static void parse_config_file(void) | |||
250 | 252 | ||
251 | e = skip_whitespace(e+1); | 253 | e = skip_whitespace(e+1); |
252 | 254 | ||
253 | for (i=0 ; i < 3 ; i++) { | 255 | for (i = 0; i < 3; i++) { |
254 | const char *q; | 256 | const char *q; |
255 | if (!*(q = strchrnul(mode_chars + 5*i, *e++))) { | 257 | q = strchrnul(mode_chars + 5*i, *e++); |
258 | if (!*q) { | ||
256 | parse_error("mode"); | 259 | parse_error("mode"); |
257 | } | 260 | } |
258 | /* Adjust by -i to account for nul. */ | 261 | /* Adjust by -i to account for nul. */ |
@@ -268,30 +271,27 @@ static void parse_config_file(void) | |||
268 | if ((s == e) || !(e = strchr(s, '.'))) { | 271 | if ((s == e) || !(e = strchr(s, '.'))) { |
269 | parse_error("<uid>.<gid>"); | 272 | parse_error("<uid>.<gid>"); |
270 | } | 273 | } |
271 | *e++ = 0; | 274 | *e++ = '\0'; |
272 | 275 | ||
273 | /* We can't use get_ug_id here since it would exit() | 276 | /* We can't use get_ug_id here since it would exit() |
274 | * if a uid or gid was not found. Oh well... */ | 277 | * if a uid or gid was not found. Oh well... */ |
275 | { | 278 | sct->m_uid = bb_strtoul(s, NULL, 10); |
276 | char *e2; | 279 | if (errno) { |
277 | 280 | struct passwd *pwd = getpwnam(s); | |
278 | sct->m_uid = strtoul(s, &e2, 10); | 281 | if (!pwd) { |
279 | if (*e2 || (s == e2)) { | 282 | parse_error("user"); |
280 | struct passwd *pwd = getpwnam(s); | ||
281 | if (!pwd) { | ||
282 | parse_error("user"); | ||
283 | } | ||
284 | sct->m_uid = pwd->pw_uid; | ||
285 | } | 283 | } |
284 | sct->m_uid = pwd->pw_uid; | ||
285 | } | ||
286 | 286 | ||
287 | sct->m_gid = strtoul(e, &e2, 10); | 287 | sct->m_gid = bb_strtoul(e, NULL, 10); |
288 | if (*e2 || (e == e2)) { | 288 | if (errno) { |
289 | struct group *grp; | 289 | struct group *grp; |
290 | if (!(grp = getgrnam(e))) { | 290 | grp = getgrnam(e); |
291 | parse_error("group"); | 291 | if (!grp) { |
292 | } | 292 | parse_error("group"); |
293 | sct->m_gid = grp->gr_gid; | ||
294 | } | 293 | } |
294 | sct->m_gid = grp->gr_gid; | ||
295 | } | 295 | } |
296 | } | 296 | } |
297 | continue; | 297 | continue; |
@@ -327,63 +327,64 @@ static void parse_config_file(void) | |||
327 | #define parse_config_file() ((void)0) | 327 | #define parse_config_file() ((void)0) |
328 | #endif /* CONFIG_FEATURE_SUID_CONFIG */ | 328 | #endif /* CONFIG_FEATURE_SUID_CONFIG */ |
329 | 329 | ||
330 | #ifdef CONFIG_FEATURE_SUID | 330 | #if ENABLE_FEATURE_SUID |
331 | static void check_suid(struct BB_applet *applet) | 331 | static void check_suid(struct BB_applet *applet) |
332 | { | 332 | { |
333 | uid_t ruid = getuid(); /* real [ug]id */ | 333 | uid_t ruid = getuid(); /* real [ug]id */ |
334 | uid_t rgid = getgid(); | 334 | uid_t rgid = getgid(); |
335 | 335 | ||
336 | #ifdef CONFIG_FEATURE_SUID_CONFIG | 336 | #if ENABLE_FEATURE_SUID_CONFIG |
337 | if (suid_cfg_readable) { | 337 | if (suid_cfg_readable) { |
338 | struct BB_suid_config *sct; | 338 | struct BB_suid_config *sct; |
339 | mode_t m; | ||
339 | 340 | ||
340 | for (sct = suid_config; sct; sct = sct->m_next) { | 341 | for (sct = suid_config; sct; sct = sct->m_next) { |
341 | if (sct->m_applet == applet) | 342 | if (sct->m_applet == applet) |
342 | break; | 343 | goto found; |
343 | } | 344 | } |
344 | if (sct) { | 345 | /* default: drop all privileges */ |
345 | mode_t m = sct->m_mode; | 346 | xsetgid(rgid); |
346 | 347 | xsetuid(ruid); | |
347 | if (sct->m_uid == ruid) | 348 | return; |
348 | /* same uid */ | 349 | found: |
349 | m >>= 6; | 350 | m = sct->m_mode; |
350 | else if ((sct->m_gid == rgid) || ingroup(ruid, sct->m_gid)) | 351 | if (sct->m_uid == ruid) |
351 | /* same group / in group */ | 352 | /* same uid */ |
352 | m >>= 3; | 353 | m >>= 6; |
353 | 354 | else if ((sct->m_gid == rgid) || ingroup(ruid, sct->m_gid)) | |
354 | if (!(m & S_IXOTH)) /* is x bit not set ? */ | 355 | /* same group / in group */ |
355 | bb_error_msg_and_die("you have no permission to run this applet!"); | 356 | m >>= 3; |
356 | 357 | ||
357 | if (sct->m_gid != 0) { | 358 | if (!(m & S_IXOTH)) /* is x bit not set ? */ |
358 | /* _both_ have to be set for sgid */ | 359 | bb_error_msg_and_die("you have no permission to run this applet!"); |
359 | if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { | 360 | |
360 | xsetgid(sct->m_gid); | 361 | if (sct->m_gid != 0) { |
361 | } else xsetgid(rgid); /* no sgid -> drop */ | 362 | /* _both_ have to be set for sgid */ |
362 | } | 363 | if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { |
363 | if (sct->m_uid != 0) { | 364 | xsetgid(sct->m_gid); |
364 | if (sct->m_mode & S_ISUID) xsetuid(sct->m_uid); | 365 | } else xsetgid(rgid); /* no sgid -> drop */ |
365 | else xsetuid(ruid); /* no suid -> drop */ | 366 | } |
366 | } | 367 | if (sct->m_uid != 0) { |
367 | } else { | 368 | if (sct->m_mode & S_ISUID) xsetuid(sct->m_uid); |
368 | /* default: drop all privileges */ | 369 | else xsetuid(ruid); /* no suid -> drop */ |
369 | xsetgid(rgid); | ||
370 | xsetuid(ruid); | ||
371 | } | 370 | } |
372 | return; | 371 | return; |
373 | } else { | 372 | } |
374 | #ifndef CONFIG_FEATURE_SUID_CONFIG_QUIET | 373 | #if !ENABLE_FEATURE_SUID_CONFIG_QUIET |
375 | static int onetime = 0; | 374 | { |
375 | static smallint onetime = 0; | ||
376 | 376 | ||
377 | if (!onetime) { | 377 | if (!onetime) { |
378 | onetime = 1; | 378 | onetime = 1; |
379 | fprintf(stderr, "Using fallback suid method\n"); | 379 | fprintf(stderr, "Using fallback suid method\n"); |
380 | } | 380 | } |
381 | #endif | ||
382 | } | 381 | } |
383 | #endif | 382 | #endif |
383 | #endif | ||
384 | 384 | ||
385 | if (applet->need_suid == _BB_SUID_ALWAYS) { | 385 | if (applet->need_suid == _BB_SUID_ALWAYS) { |
386 | if (geteuid()) bb_error_msg_and_die("applet requires root privileges!"); | 386 | if (geteuid()) |
387 | bb_error_msg_and_die("applet requires root privileges!"); | ||
387 | } else if (applet->need_suid == _BB_SUID_NEVER) { | 388 | } else if (applet->need_suid == _BB_SUID_NEVER) { |
388 | xsetgid(rgid); /* drop all privileges */ | 389 | xsetgid(rgid); /* drop all privileges */ |
389 | xsetuid(ruid); | 390 | xsetuid(ruid); |
@@ -395,7 +396,7 @@ static void check_suid(struct BB_applet *applet) | |||
395 | 396 | ||
396 | 397 | ||
397 | 398 | ||
398 | #ifdef CONFIG_FEATURE_COMPRESS_USAGE | 399 | #if ENABLE_FEATURE_COMPRESS_USAGE |
399 | 400 | ||
400 | #include "usage_compressed.h" | 401 | #include "usage_compressed.h" |
401 | #include "unarchive.h" | 402 | #include "unarchive.h" |
@@ -405,7 +406,7 @@ static const char *unpack_usage_messages(void) | |||
405 | int input[2], output[2], pid; | 406 | int input[2], output[2], pid; |
406 | char *buf; | 407 | char *buf; |
407 | 408 | ||
408 | if(pipe(input) < 0 || pipe(output) < 0) | 409 | if (pipe(input) < 0 || pipe(output) < 0) |
409 | exit(1); | 410 | exit(1); |
410 | 411 | ||
411 | pid = fork(); | 412 | pid = fork(); |
@@ -480,8 +481,6 @@ void run_applet_by_name(const char *name, int argc, char **argv) | |||
480 | if (ENABLE_FEATURE_SUID_CONFIG) | 481 | if (ENABLE_FEATURE_SUID_CONFIG) |
481 | parse_config_file(); | 482 | parse_config_file(); |
482 | 483 | ||
483 | if (!strncmp(name, "busybox", 7)) | ||
484 | exit(busybox_main(argc, argv)); | ||
485 | /* Do a binary search to find the applet entry given the name. */ | 484 | /* Do a binary search to find the applet entry given the name. */ |
486 | applet_using = find_applet_by_name(name); | 485 | applet_using = find_applet_by_name(name); |
487 | if (applet_using) { | 486 | if (applet_using) { |
@@ -492,4 +491,6 @@ void run_applet_by_name(const char *name, int argc, char **argv) | |||
492 | check_suid(applet_using); | 491 | check_suid(applet_using); |
493 | exit(applet_using->main(argc, argv)); | 492 | exit(applet_using->main(argc, argv)); |
494 | } | 493 | } |
494 | if (!strncmp(name, "busybox", 7)) | ||
495 | exit(busybox_main(argc, argv)); | ||
495 | } | 496 | } |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 2cc6a8299..c496f9a22 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -251,15 +251,15 @@ void smart_ulltoa5(unsigned long long ul, char buf[5]) | |||
251 | fmt = " 123456789"; | 251 | fmt = " 123456789"; |
252 | if (!idx) { // 9999 or less: use 1234 format | 252 | if (!idx) { // 9999 or less: use 1234 format |
253 | c = buf[0] = " 123456789"[v/10000]; | 253 | c = buf[0] = " 123456789"[v/10000]; |
254 | if (c!=' ') fmt = "0123456789"; | 254 | if (c != ' ') fmt = "0123456789"; |
255 | c = buf[1] = fmt[v/1000%10]; | 255 | c = buf[1] = fmt[v/1000%10]; |
256 | if (c!=' ') fmt = "0123456789"; | 256 | if (c != ' ') fmt = "0123456789"; |
257 | buf[2] = fmt[v/100%10]; | 257 | buf[2] = fmt[v/100%10]; |
258 | buf[3] = "0123456789"[v/10%10]; | 258 | buf[3] = "0123456789"[v/10%10]; |
259 | } else { | 259 | } else { |
260 | if (v>=10*10) { // scaled value is >=10: use 123M format | 260 | if (v >= 10*10) { // scaled value is >=10: use 123M format |
261 | c = buf[0] = " 123456789"[v/1000]; | 261 | c = buf[0] = " 123456789"[v/1000]; |
262 | if (c!=' ') fmt = "0123456789"; | 262 | if (c != ' ') fmt = "0123456789"; |
263 | buf[1] = fmt[v/100%10]; | 263 | buf[1] = fmt[v/100%10]; |
264 | buf[2] = "0123456789"[v/10%10]; | 264 | buf[2] = "0123456789"[v/10%10]; |
265 | } else { // scaled value is <10: use 1.2M format | 265 | } else { // scaled value is <10: use 1.2M format |
@@ -483,10 +483,9 @@ DIR *warn_opendir(const char *path) | |||
483 | { | 483 | { |
484 | DIR *dp; | 484 | DIR *dp; |
485 | 485 | ||
486 | if ((dp = opendir(path)) == NULL) { | 486 | dp = opendir(path); |
487 | if (!dp) | ||
487 | bb_perror_msg("cannot open '%s'", path); | 488 | bb_perror_msg("cannot open '%s'", path); |
488 | return NULL; | ||
489 | } | ||
490 | return dp; | 489 | return dp; |
491 | } | 490 | } |
492 | 491 | ||
@@ -495,7 +494,8 @@ DIR *xopendir(const char *path) | |||
495 | { | 494 | { |
496 | DIR *dp; | 495 | DIR *dp; |
497 | 496 | ||
498 | if ((dp = opendir(path)) == NULL) | 497 | dp = opendir(path); |
498 | if (!dp) | ||
499 | bb_perror_msg_and_die("cannot open '%s'", path); | 499 | bb_perror_msg_and_die("cannot open '%s'", path); |
500 | return dp; | 500 | return dp; |
501 | } | 501 | } |