diff options
author | Ron Yorston <rmy@pobox.com> | 2012-03-22 15:21:20 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-03-22 15:21:20 +0000 |
commit | 0d8b2c4a929ea9d3ac37499319fe0d8e7941a0c2 (patch) | |
tree | 6709ddd6071a9c238ba69233540bbcfe560c6a44 /libbb | |
parent | 67758035a4fe040c6ac69b39d61bcd6bddd7b827 (diff) | |
parent | 56a3b82e9692a25ef9c9269e88feac0d579ce8e8 (diff) | |
download | busybox-w32-0d8b2c4a929ea9d3ac37499319fe0d8e7941a0c2.tar.gz busybox-w32-0d8b2c4a929ea9d3ac37499319fe0d8e7941a0c2.tar.bz2 busybox-w32-0d8b2c4a929ea9d3ac37499319fe0d8e7941a0c2.zip |
Merge commit '56a3b82e9692a25ef9c9269e88feac0d579ce8e8' into merge
Conflicts:
coreutils/ls.c
include/platform.h
libbb/bb_basename.c
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/Kbuild.src | 1 | ||||
-rw-r--r-- | libbb/appletlib.c | 213 | ||||
-rw-r--r-- | libbb/bb_basename.c | 23 | ||||
-rw-r--r-- | libbb/dump.c | 7 | ||||
-rw-r--r-- | libbb/get_last_path_component.c | 15 | ||||
-rw-r--r-- | libbb/getopt32.c | 4 | ||||
-rw-r--r-- | libbb/lineedit.c | 24 | ||||
-rw-r--r-- | libbb/llist.c | 2 | ||||
-rw-r--r-- | libbb/pw_encrypt.c | 25 | ||||
-rw-r--r-- | libbb/read_printf.c | 17 |
10 files changed, 165 insertions, 166 deletions
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 3c9493f7e..d110a3265 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -13,7 +13,6 @@ INSERT | |||
13 | lib-y += appletlib.o | 13 | lib-y += appletlib.o |
14 | lib-y += ask_confirmation.o | 14 | lib-y += ask_confirmation.o |
15 | lib-y += bb_askpass.o | 15 | lib-y += bb_askpass.o |
16 | lib-y += bb_basename.o | ||
17 | lib-y += bb_bswap_64.o | 16 | lib-y += bb_bswap_64.o |
18 | lib-y += bb_do_delay.o | 17 | lib-y += bb_do_delay.o |
19 | lib-y += bb_pwd.o | 18 | lib-y += bb_pwd.o |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index a934f11bb..d4025b9c7 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -27,12 +27,13 @@ | |||
27 | * FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :( | 27 | * FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :( |
28 | */ | 28 | */ |
29 | #include "busybox.h" | 29 | #include "busybox.h" |
30 | #include <assert.h> | 30 | |
31 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ | 31 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ |
32 | || defined(__APPLE__) \ | 32 | || defined(__APPLE__) \ |
33 | ) | 33 | ) |
34 | # include <malloc.h> /* for mallopt */ | 34 | # include <malloc.h> /* for mallopt */ |
35 | #endif | 35 | #endif |
36 | |||
36 | /* Try to pull in PAGE_SIZE */ | 37 | /* Try to pull in PAGE_SIZE */ |
37 | #ifdef __linux__ | 38 | #ifdef __linux__ |
38 | # include <sys/user.h> | 39 | # include <sys/user.h> |
@@ -40,6 +41,9 @@ | |||
40 | #ifdef __GNU__ /* Hurd */ | 41 | #ifdef __GNU__ /* Hurd */ |
41 | # include <mach/vm_param.h> | 42 | # include <mach/vm_param.h> |
42 | #endif | 43 | #endif |
44 | #ifndef PAGE_SIZE | ||
45 | # define PAGE_SIZE (4*1024) /* guess */ | ||
46 | #endif | ||
43 | 47 | ||
44 | 48 | ||
45 | /* Declare <applet>_main() */ | 49 | /* Declare <applet>_main() */ |
@@ -47,7 +51,6 @@ | |||
47 | #include "applets.h" | 51 | #include "applets.h" |
48 | #undef PROTOTYPES | 52 | #undef PROTOTYPES |
49 | 53 | ||
50 | |||
51 | /* Include generated applet names, pointers to <applet>_main, etc */ | 54 | /* Include generated applet names, pointers to <applet>_main, etc */ |
52 | #include "applet_tables.h" | 55 | #include "applet_tables.h" |
53 | /* ...and if applet_tables generator says we have only one applet... */ | 56 | /* ...and if applet_tables generator says we have only one applet... */ |
@@ -58,9 +61,9 @@ | |||
58 | # define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__ | 61 | # define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__ |
59 | #endif | 62 | #endif |
60 | 63 | ||
61 | |||
62 | #include "usage_compressed.h" | 64 | #include "usage_compressed.h" |
63 | 65 | ||
66 | |||
64 | #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE | 67 | #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE |
65 | static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; | 68 | static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; |
66 | #else | 69 | #else |
@@ -233,13 +236,12 @@ IF_FEATURE_SUID(static uid_t ruid;) /* real uid */ | |||
233 | 236 | ||
234 | # if ENABLE_FEATURE_SUID_CONFIG | 237 | # if ENABLE_FEATURE_SUID_CONFIG |
235 | 238 | ||
236 | /* applets[] is const, so we have to define this "override" structure */ | 239 | static struct suid_config_t { |
237 | static struct BB_suid_config { | 240 | /* next ptr must be first: this struct needs to be llist-compatible */ |
241 | struct suid_config_t *m_next; | ||
242 | struct bb_uidgid_t m_ugid; | ||
238 | int m_applet; | 243 | int m_applet; |
239 | uid_t m_uid; | ||
240 | gid_t m_gid; | ||
241 | mode_t m_mode; | 244 | mode_t m_mode; |
242 | struct BB_suid_config *m_next; | ||
243 | } *suid_config; | 245 | } *suid_config; |
244 | 246 | ||
245 | static bool suid_cfg_readable; | 247 | static bool suid_cfg_readable; |
@@ -248,13 +250,10 @@ static bool suid_cfg_readable; | |||
248 | static int ingroup(uid_t u, gid_t g) | 250 | static int ingroup(uid_t u, gid_t g) |
249 | { | 251 | { |
250 | struct group *grp = getgrgid(g); | 252 | struct group *grp = getgrgid(g); |
251 | |||
252 | if (grp) { | 253 | if (grp) { |
253 | char **mem; | 254 | char **mem; |
254 | |||
255 | for (mem = grp->gr_mem; *mem; mem++) { | 255 | for (mem = grp->gr_mem; *mem; mem++) { |
256 | struct passwd *pwd = getpwnam(*mem); | 256 | struct passwd *pwd = getpwnam(*mem); |
257 | |||
258 | if (pwd && (pwd->pw_uid == u)) | 257 | if (pwd && (pwd->pw_uid == u)) |
259 | return 1; | 258 | return 1; |
260 | } | 259 | } |
@@ -262,9 +261,7 @@ static int ingroup(uid_t u, gid_t g) | |||
262 | return 0; | 261 | return 0; |
263 | } | 262 | } |
264 | 263 | ||
265 | /* This should probably be a libbb routine. In that case, | 264 | /* libbb candidate */ |
266 | * I'd probably rename it to something like bb_trimmed_slice. | ||
267 | */ | ||
268 | static char *get_trimmed_slice(char *s, char *e) | 265 | static char *get_trimmed_slice(char *s, char *e) |
269 | { | 266 | { |
270 | /* First, consider the value at e to be nul and back up until we | 267 | /* First, consider the value at e to be nul and back up until we |
@@ -282,38 +279,19 @@ static char *get_trimmed_slice(char *s, char *e) | |||
282 | return skip_whitespace(s); | 279 | return skip_whitespace(s); |
283 | } | 280 | } |
284 | 281 | ||
285 | /* Don't depend on the tools to combine strings. */ | ||
286 | static const char config_file[] ALIGN1 = "/etc/busybox.conf"; | ||
287 | |||
288 | /* We don't supply a value for the nul, so an index adjustment is | ||
289 | * necessary below. Also, we use unsigned short here to save some | ||
290 | * space even though these are really mode_t values. */ | ||
291 | static const unsigned short mode_mask[] ALIGN2 = { | ||
292 | /* SST sst xxx --- */ | ||
293 | S_ISUID, S_ISUID|S_IXUSR, S_IXUSR, 0, /* user */ | ||
294 | S_ISGID, S_ISGID|S_IXGRP, S_IXGRP, 0, /* group */ | ||
295 | 0, S_IXOTH, S_IXOTH, 0 /* other */ | ||
296 | }; | ||
297 | |||
298 | #define parse_error(x) do { errmsg = x; goto pe_label; } while (0) | ||
299 | |||
300 | static void parse_config_file(void) | 282 | static void parse_config_file(void) |
301 | { | 283 | { |
302 | struct BB_suid_config *sct_head; | 284 | /* Don't depend on the tools to combine strings. */ |
303 | struct BB_suid_config *sct; | 285 | static const char config_file[] ALIGN1 = "/etc/busybox.conf"; |
286 | |||
287 | struct suid_config_t *sct_head; | ||
304 | int applet_no; | 288 | int applet_no; |
305 | FILE *f; | 289 | FILE *f; |
306 | const char *errmsg; | 290 | const char *errmsg; |
307 | char *s; | ||
308 | char *e; | ||
309 | int i; | ||
310 | unsigned lc; | 291 | unsigned lc; |
311 | smallint section; | 292 | smallint section; |
312 | char buffer[256]; | ||
313 | struct stat st; | 293 | struct stat st; |
314 | 294 | ||
315 | assert(!suid_config); /* Should be set to NULL by bss init. */ | ||
316 | |||
317 | ruid = getuid(); | 295 | ruid = getuid(); |
318 | if (ruid == 0) /* run by root - don't need to even read config file */ | 296 | if (ruid == 0) /* run by root - don't need to even read config file */ |
319 | return; | 297 | return; |
@@ -322,7 +300,7 @@ static void parse_config_file(void) | |||
322 | || !S_ISREG(st.st_mode) /* Not a regular file? */ | 300 | || !S_ISREG(st.st_mode) /* Not a regular file? */ |
323 | || (st.st_uid != 0) /* Not owned by root? */ | 301 | || (st.st_uid != 0) /* Not owned by root? */ |
324 | || (st.st_mode & (S_IWGRP | S_IWOTH)) /* Writable by non-root? */ | 302 | || (st.st_mode & (S_IWGRP | S_IWOTH)) /* Writable by non-root? */ |
325 | || !(f = fopen_for_read(config_file)) /* Cannot open? */ | 303 | || !(f = fopen_for_read(config_file)) /* Cannot open? */ |
326 | ) { | 304 | ) { |
327 | return; | 305 | return; |
328 | } | 306 | } |
@@ -332,18 +310,21 @@ static void parse_config_file(void) | |||
332 | section = lc = 0; | 310 | section = lc = 0; |
333 | 311 | ||
334 | while (1) { | 312 | while (1) { |
335 | s = buffer; | 313 | char buffer[256]; |
336 | 314 | char *s; | |
337 | if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */ | 315 | |
338 | // why? | 316 | if (!fgets(buffer, sizeof(buffer), f)) { /* Are we done? */ |
339 | if (ferror(f)) { /* Make sure it wasn't a read error. */ | 317 | // Looks like bloat |
340 | parse_error("reading"); | 318 | //if (ferror(f)) { /* Make sure it wasn't a read error. */ |
341 | } | 319 | // errmsg = "reading"; |
320 | // goto pe_label; | ||
321 | //} | ||
342 | fclose(f); | 322 | fclose(f); |
343 | suid_config = sct_head; /* Success, so set the pointer. */ | 323 | suid_config = sct_head; /* Success, so set the pointer. */ |
344 | return; | 324 | return; |
345 | } | 325 | } |
346 | 326 | ||
327 | s = buffer; | ||
347 | lc++; /* Got a (partial) line. */ | 328 | lc++; /* Got a (partial) line. */ |
348 | 329 | ||
349 | /* If a line is too long for our buffer, we consider it an error. | 330 | /* If a line is too long for our buffer, we consider it an error. |
@@ -355,7 +336,8 @@ static void parse_config_file(void) | |||
355 | * we do err on the side of caution. Besides, the line would be | 336 | * we do err on the side of caution. Besides, the line would be |
356 | * too long if it did end with a newline. */ | 337 | * too long if it did end with a newline. */ |
357 | if (!strchr(s, '\n') && !feof(f)) { | 338 | if (!strchr(s, '\n') && !feof(f)) { |
358 | parse_error("line too long"); | 339 | errmsg = "line too long"; |
340 | goto pe_label; | ||
359 | } | 341 | } |
360 | 342 | ||
361 | /* Trim leading and trailing whitespace, ignoring comments, and | 343 | /* Trim leading and trailing whitespace, ignoring comments, and |
@@ -371,12 +353,13 @@ static void parse_config_file(void) | |||
371 | /* Unlike the old code, we ignore leading and trailing | 353 | /* Unlike the old code, we ignore leading and trailing |
372 | * whitespace for the section name. We also require that | 354 | * whitespace for the section name. We also require that |
373 | * there are no stray characters after the closing bracket. */ | 355 | * there are no stray characters after the closing bracket. */ |
374 | e = strchr(s, ']'); | 356 | char *e = strchr(s, ']'); |
375 | if (!e /* Missing right bracket? */ | 357 | if (!e /* Missing right bracket? */ |
376 | || e[1] /* Trailing characters? */ | 358 | || e[1] /* Trailing characters? */ |
377 | || !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */ | 359 | || !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */ |
378 | ) { | 360 | ) { |
379 | parse_error("section header"); | 361 | errmsg = "section header"; |
362 | goto pe_label; | ||
380 | } | 363 | } |
381 | /* Right now we only have one section so just check it. | 364 | /* Right now we only have one section so just check it. |
382 | * If more sections are added in the future, please don't | 365 | * If more sections are added in the future, please don't |
@@ -401,12 +384,13 @@ static void parse_config_file(void) | |||
401 | * where both key and value could contain inner whitespace. */ | 384 | * where both key and value could contain inner whitespace. */ |
402 | 385 | ||
403 | /* First get the key (an applet name in our case). */ | 386 | /* First get the key (an applet name in our case). */ |
404 | e = strchr(s, '='); | 387 | char *e = strchr(s, '='); |
405 | if (e) { | 388 | if (e) { |
406 | s = get_trimmed_slice(s, e); | 389 | s = get_trimmed_slice(s, e); |
407 | } | 390 | } |
408 | if (!e || !*s) { /* Missing '=' or empty key. */ | 391 | if (!e || !*s) { /* Missing '=' or empty key. */ |
409 | parse_error("keyword"); | 392 | errmsg = "keyword"; |
393 | goto pe_label; | ||
410 | } | 394 | } |
411 | 395 | ||
412 | /* Ok, we have an applet name. Process the rhs if this | 396 | /* Ok, we have an applet name. Process the rhs if this |
@@ -415,13 +399,16 @@ static void parse_config_file(void) | |||
415 | * up when the busybox configuration is changed. */ | 399 | * up when the busybox configuration is changed. */ |
416 | applet_no = find_applet_by_name(s); | 400 | applet_no = find_applet_by_name(s); |
417 | if (applet_no >= 0) { | 401 | if (applet_no >= 0) { |
402 | unsigned i; | ||
403 | struct suid_config_t *sct; | ||
404 | |||
418 | /* Note: We currently don't check for duplicates! | 405 | /* Note: We currently don't check for duplicates! |
419 | * The last config line for each applet will be the | 406 | * The last config line for each applet will be the |
420 | * one used since we insert at the head of the list. | 407 | * one used since we insert at the head of the list. |
421 | * I suppose this could be considered a feature. */ | 408 | * I suppose this could be considered a feature. */ |
422 | sct = xmalloc(sizeof(struct BB_suid_config)); | 409 | sct = xzalloc(sizeof(*sct)); |
423 | sct->m_applet = applet_no; | 410 | sct->m_applet = applet_no; |
424 | sct->m_mode = 0; | 411 | /*sct->m_mode = 0;*/ |
425 | sct->m_next = sct_head; | 412 | sct->m_next = sct_head; |
426 | sct_head = sct; | 413 | sct_head = sct; |
427 | 414 | ||
@@ -430,48 +417,41 @@ static void parse_config_file(void) | |||
430 | e = skip_whitespace(e+1); | 417 | e = skip_whitespace(e+1); |
431 | 418 | ||
432 | for (i = 0; i < 3; i++) { | 419 | for (i = 0; i < 3; i++) { |
433 | /* There are 4 chars + 1 nul for each of user/group/other. */ | 420 | /* There are 4 chars for each of user/group/other. |
434 | static const char mode_chars[] ALIGN1 = "Ssx-\0" "Ssx-\0" "Ttx-"; | 421 | * "x-xx" instead of "x-" are to make |
435 | 422 | * "idx > 3" check catch invalid chars. | |
436 | const char *q; | 423 | */ |
437 | q = strchrnul(mode_chars + 5*i, *e++); | 424 | static const char mode_chars[] ALIGN1 = "Ssx-" "Ssx-" "x-xx"; |
438 | if (!*q) { | 425 | static const unsigned short mode_mask[] ALIGN2 = { |
439 | parse_error("mode"); | 426 | S_ISUID, S_ISUID|S_IXUSR, S_IXUSR, 0, /* Ssx- */ |
427 | S_ISGID, S_ISGID|S_IXGRP, S_IXGRP, 0, /* Ssx- */ | ||
428 | S_IXOTH, 0 /* x- */ | ||
429 | }; | ||
430 | const char *q = strchrnul(mode_chars + 4*i, *e); | ||
431 | unsigned idx = q - (mode_chars + 4*i); | ||
432 | if (idx > 3) { | ||
433 | errmsg = "mode"; | ||
434 | goto pe_label; | ||
440 | } | 435 | } |
441 | /* Adjust by -i to account for nul. */ | 436 | sct->m_mode |= mode_mask[q - mode_chars]; |
442 | sct->m_mode |= mode_mask[(q - mode_chars) - i]; | 437 | e++; |
443 | } | 438 | } |
444 | 439 | ||
445 | /* Now get the user/group info. */ | 440 | /* Now get the user/group info. */ |
446 | 441 | ||
447 | s = skip_whitespace(e); | 442 | s = skip_whitespace(e); |
448 | 443 | /* Default is 0.0, else parse USER.GROUP: */ | |
449 | /* Note: we require whitespace between the mode and the | 444 | if (*s) { |
450 | * user/group info. */ | 445 | /* We require whitespace between mode and USER.GROUP */ |
451 | if ((s == e) || !(e = strchr(s, '.'))) { | 446 | if ((s == e) || !(e = strchr(s, '.'))) { |
452 | parse_error("<uid>.<gid>"); | 447 | errmsg = "uid.gid"; |
453 | } | 448 | goto pe_label; |
454 | *e++ = '\0'; | ||
455 | |||
456 | /* We can't use get_ug_id here since it would exit() | ||
457 | * if a uid or gid was not found. Oh well... */ | ||
458 | sct->m_uid = bb_strtoul(s, NULL, 10); | ||
459 | if (errno) { | ||
460 | struct passwd *pwd = getpwnam(s); | ||
461 | if (!pwd) { | ||
462 | parse_error("user"); | ||
463 | } | 449 | } |
464 | sct->m_uid = pwd->pw_uid; | 450 | *e = ':'; /* get_uidgid needs USER:GROUP syntax */ |
465 | } | 451 | if (get_uidgid(&sct->m_ugid, s, /*allow_numeric:*/ 1) == 0) { |
466 | 452 | errmsg = "unknown user/group"; | |
467 | sct->m_gid = bb_strtoul(e, NULL, 10); | 453 | goto pe_label; |
468 | if (errno) { | ||
469 | struct group *grp; | ||
470 | grp = getgrnam(e); | ||
471 | if (!grp) { | ||
472 | parse_error("group"); | ||
473 | } | 454 | } |
474 | sct->m_gid = grp->gr_gid; | ||
475 | } | 455 | } |
476 | } | 456 | } |
477 | continue; | 457 | continue; |
@@ -485,22 +465,18 @@ static void parse_config_file(void) | |||
485 | * We may want to simply ignore such lines in case they | 465 | * We may want to simply ignore such lines in case they |
486 | * are used in some future version of busybox. */ | 466 | * are used in some future version of busybox. */ |
487 | if (!section) { | 467 | if (!section) { |
488 | parse_error("keyword outside section"); | 468 | errmsg = "keyword outside section"; |
469 | goto pe_label; | ||
489 | } | 470 | } |
490 | 471 | ||
491 | } /* while (1) */ | 472 | } /* while (1) */ |
492 | 473 | ||
493 | pe_label: | 474 | pe_label: |
494 | fprintf(stderr, "Parse error in %s, line %d: %s\n", | ||
495 | config_file, lc, errmsg); | ||
496 | |||
497 | fclose(f); | 475 | fclose(f); |
476 | bb_error_msg("parse error in %s, line %u: %s", config_file, lc, errmsg); | ||
477 | |||
498 | /* Release any allocated memory before returning. */ | 478 | /* Release any allocated memory before returning. */ |
499 | while (sct_head) { | 479 | llist_free((llist_t*)sct_head, NULL); |
500 | sct = sct_head->m_next; | ||
501 | free(sct_head); | ||
502 | sct_head = sct; | ||
503 | } | ||
504 | } | 480 | } |
505 | # else | 481 | # else |
506 | static inline void parse_config_file(void) | 482 | static inline void parse_config_file(void) |
@@ -522,7 +498,7 @@ static void check_suid(int applet_no) | |||
522 | # if ENABLE_FEATURE_SUID_CONFIG | 498 | # if ENABLE_FEATURE_SUID_CONFIG |
523 | if (suid_cfg_readable) { | 499 | if (suid_cfg_readable) { |
524 | uid_t uid; | 500 | uid_t uid; |
525 | struct BB_suid_config *sct; | 501 | struct suid_config_t *sct; |
526 | mode_t m; | 502 | mode_t m; |
527 | 503 | ||
528 | for (sct = suid_config; sct; sct = sct->m_next) { | 504 | for (sct = suid_config; sct; sct = sct->m_next) { |
@@ -531,36 +507,40 @@ static void check_suid(int applet_no) | |||
531 | } | 507 | } |
532 | goto check_need_suid; | 508 | goto check_need_suid; |
533 | found: | 509 | found: |
510 | /* Is this user allowed to run this applet? */ | ||
534 | m = sct->m_mode; | 511 | m = sct->m_mode; |
535 | if (sct->m_uid == ruid) | 512 | if (sct->m_ugid.uid == ruid) |
536 | /* same uid */ | 513 | /* same uid */ |
537 | m >>= 6; | 514 | m >>= 6; |
538 | else if ((sct->m_gid == rgid) || ingroup(ruid, sct->m_gid)) | 515 | else if ((sct->m_ugid.gid == rgid) || ingroup(ruid, sct->m_ugid.gid)) |
539 | /* same group / in group */ | 516 | /* same group / in group */ |
540 | m >>= 3; | 517 | m >>= 3; |
541 | 518 | if (!(m & S_IXOTH)) /* is x bit not set? */ | |
542 | if (!(m & S_IXOTH)) /* is x bit not set ? */ | 519 | bb_error_msg_and_die("you have no permission to run this applet"); |
543 | bb_error_msg_and_die("you have no permission to run this applet!"); | ||
544 | |||
545 | /* _both_ sgid and group_exec have to be set for setegid */ | ||
546 | if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) | ||
547 | rgid = sct->m_gid; | ||
548 | /* else (no setegid) we will set egid = rgid */ | ||
549 | 520 | ||
550 | /* We set effective AND saved ids. If saved-id is not set | 521 | /* We set effective AND saved ids. If saved-id is not set |
551 | * like we do below, seteiud(0) can still later succeed! */ | 522 | * like we do below, seteuid(0) can still later succeed! */ |
523 | |||
524 | /* Are we directed to change gid | ||
525 | * (APPLET = *s* USER.GROUP or APPLET = *S* USER.GROUP)? | ||
526 | */ | ||
527 | if (sct->m_mode & S_ISGID) | ||
528 | rgid = sct->m_ugid.gid; | ||
529 | /* else: we will set egid = rgid, thus dropping sgid effect */ | ||
552 | if (setresgid(-1, rgid, rgid)) | 530 | if (setresgid(-1, rgid, rgid)) |
553 | bb_perror_msg_and_die("setresgid"); | 531 | bb_perror_msg_and_die("setresgid"); |
554 | 532 | ||
555 | /* do we have to set effective uid? */ | 533 | /* Are we directed to change uid |
534 | * (APPLET = s** USER.GROUP or APPLET = S** USER.GROUP)? | ||
535 | */ | ||
556 | uid = ruid; | 536 | uid = ruid; |
557 | if (sct->m_mode & S_ISUID) | 537 | if (sct->m_mode & S_ISUID) |
558 | uid = sct->m_uid; | 538 | uid = sct->m_ugid.uid; |
559 | /* else (no seteuid) we will set euid = ruid */ | 539 | /* else: we will set euid = ruid, thus dropping suid effect */ |
560 | |||
561 | if (setresuid(-1, uid, uid)) | 540 | if (setresuid(-1, uid, uid)) |
562 | bb_perror_msg_and_die("setresuid"); | 541 | bb_perror_msg_and_die("setresuid"); |
563 | return; | 542 | |
543 | goto ret; | ||
564 | } | 544 | } |
565 | # if !ENABLE_FEATURE_SUID_CONFIG_QUIET | 545 | # if !ENABLE_FEATURE_SUID_CONFIG_QUIET |
566 | { | 546 | { |
@@ -568,7 +548,7 @@ static void check_suid(int applet_no) | |||
568 | 548 | ||
569 | if (!onetime) { | 549 | if (!onetime) { |
570 | onetime = 1; | 550 | onetime = 1; |
571 | fprintf(stderr, "Using fallback suid method\n"); | 551 | bb_error_msg("using fallback suid method"); |
572 | } | 552 | } |
573 | } | 553 | } |
574 | # endif | 554 | # endif |
@@ -583,6 +563,10 @@ static void check_suid(int applet_no) | |||
583 | xsetgid(rgid); /* drop all privileges */ | 563 | xsetgid(rgid); /* drop all privileges */ |
584 | xsetuid(ruid); | 564 | xsetuid(ruid); |
585 | } | 565 | } |
566 | # if ENABLE_FEATURE_SUID_CONFIG | ||
567 | ret: ; | ||
568 | llist_free((llist_t*)suid_config, NULL); | ||
569 | # endif | ||
586 | } | 570 | } |
587 | # else | 571 | # else |
588 | # define check_suid(x) ((void)0) | 572 | # define check_suid(x) ((void)0) |
@@ -799,9 +783,6 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
799 | #endif | 783 | #endif |
800 | { | 784 | { |
801 | /* Tweak malloc for reduced memory consumption */ | 785 | /* Tweak malloc for reduced memory consumption */ |
802 | #ifndef PAGE_SIZE | ||
803 | # define PAGE_SIZE (4*1024) /* guess */ | ||
804 | #endif | ||
805 | #ifdef M_TRIM_THRESHOLD | 786 | #ifdef M_TRIM_THRESHOLD |
806 | /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory | 787 | /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory |
807 | * to keep before releasing to the OS | 788 | * to keep before releasing to the OS |
diff --git a/libbb/bb_basename.c b/libbb/bb_basename.c deleted file mode 100644 index 92fdb6545..000000000 --- a/libbb/bb_basename.c +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Copyright (C) 2007 Denys Vlasenko | ||
6 | * | ||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
8 | */ | ||
9 | |||
10 | #include "libbb.h" | ||
11 | |||
12 | const char* FAST_FUNC bb_basename(const char *name) | ||
13 | { | ||
14 | const char *cp = strrchr(name, '/'); | ||
15 | if (cp) | ||
16 | return cp + 1; | ||
17 | if (ENABLE_PLATFORM_MINGW32) { | ||
18 | cp = strrchr(name, '\\'); | ||
19 | if (cp) | ||
20 | return cp + 1; | ||
21 | } | ||
22 | return name; | ||
23 | } | ||
diff --git a/libbb/dump.c b/libbb/dump.c index 1b1d03a66..919fe135c 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -99,7 +99,7 @@ static NOINLINE int bb_dump_size(FS *fs) | |||
99 | static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) | 99 | static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) |
100 | { | 100 | { |
101 | enum { NOTOKAY, USEBCNT, USEPREC } sokay; | 101 | enum { NOTOKAY, USEBCNT, USEPREC } sokay; |
102 | PR *pr, **nextpr = NULL; | 102 | PR *pr; |
103 | FU *fu; | 103 | FU *fu; |
104 | char *p1, *p2, *p3; | 104 | char *p1, *p2, *p3; |
105 | char savech, *fmtp; | 105 | char savech, *fmtp; |
@@ -111,15 +111,12 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) | |||
111 | * break each format unit into print units; each | 111 | * break each format unit into print units; each |
112 | * conversion character gets its own. | 112 | * conversion character gets its own. |
113 | */ | 113 | */ |
114 | for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) { | 114 | for (nconv = 0, fmtp = fu->fmt; *fmtp; ) { |
115 | /* NOSTRICT */ | 115 | /* NOSTRICT */ |
116 | /* DBU:[dvae@cray.com] zalloc so that forward ptrs start out NULL*/ | 116 | /* DBU:[dvae@cray.com] zalloc so that forward ptrs start out NULL*/ |
117 | pr = xzalloc(sizeof(PR)); | 117 | pr = xzalloc(sizeof(PR)); |
118 | if (!fu->nextpr) | 118 | if (!fu->nextpr) |
119 | fu->nextpr = pr; | 119 | fu->nextpr = pr; |
120 | /* ignore nextpr -- its unused inside the loop and is | ||
121 | * uninitialized 1st time through. | ||
122 | */ | ||
123 | 120 | ||
124 | /* skip preceding text and up to the next % sign */ | 121 | /* skip preceding text and up to the next % sign */ |
125 | for (p1 = fmtp; *p1 && *p1 != '%'; ++p1) | 122 | for (p1 = fmtp; *p1 && *p1 != '%'; ++p1) |
diff --git a/libbb/get_last_path_component.c b/libbb/get_last_path_component.c index 72598d22e..db4be68ad 100644 --- a/libbb/get_last_path_component.c +++ b/libbb/get_last_path_component.c | |||
@@ -6,8 +6,21 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | |||
10 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | |||
11 | const char* FAST_FUNC bb_basename(const char *name) | ||
12 | { | ||
13 | const char *cp = strrchr(name, '/'); | ||
14 | if (cp) | ||
15 | return cp + 1; | ||
16 | #if ENABLE_PLATFORM_MINGW32 | ||
17 | cp = strrchr(name, '\\'); | ||
18 | if (cp) | ||
19 | return cp + 1; | ||
20 | #endif | ||
21 | return name; | ||
22 | } | ||
23 | |||
11 | /* | 24 | /* |
12 | * "/" -> "/" | 25 | * "/" -> "/" |
13 | * "abc" -> "abc" | 26 | * "abc" -> "abc" |
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index 8087b3ba6..02cbefec9 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c | |||
@@ -7,7 +7,9 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <getopt.h> | 10 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG |
11 | # include <getopt.h> | ||
12 | #endif | ||
11 | #include "libbb.h" | 13 | #include "libbb.h" |
12 | 14 | ||
13 | /* Documentation | 15 | /* Documentation |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 67c5e0baa..e443c7a3e 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -41,6 +41,10 @@ | |||
41 | */ | 41 | */ |
42 | #include "libbb.h" | 42 | #include "libbb.h" |
43 | #include "unicode.h" | 43 | #include "unicode.h" |
44 | #ifndef _POSIX_VDISABLE | ||
45 | # define _POSIX_VDISABLE '\0' | ||
46 | #endif | ||
47 | |||
44 | 48 | ||
45 | #ifdef TEST | 49 | #ifdef TEST |
46 | # define ENABLE_FEATURE_EDITING 0 | 50 | # define ENABLE_FEATURE_EDITING 0 |
@@ -184,6 +188,7 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics; | |||
184 | IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines = 1;) \ | 188 | IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines = 1;) \ |
185 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \ | 189 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \ |
186 | } while (0) | 190 | } while (0) |
191 | |||
187 | static void deinit_S(void) | 192 | static void deinit_S(void) |
188 | { | 193 | { |
189 | #if ENABLE_FEATURE_EDITING_FANCY_PROMPT | 194 | #if ENABLE_FEATURE_EDITING_FANCY_PROMPT |
@@ -1684,7 +1689,7 @@ static void ask_terminal(void) | |||
1684 | * write(1, "~/srcdevel/bbox/fix/busybox.t4 # ", 33) = 33 | 1689 | * write(1, "~/srcdevel/bbox/fix/busybox.t4 # ", 33) = 33 |
1685 | * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout) <-- no input exists | 1690 | * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout) <-- no input exists |
1686 | * write(1, "\33[6n", 4) = 4 <-- send the ESC sequence, quick! | 1691 | * write(1, "\33[6n", 4) = 4 <-- send the ESC sequence, quick! |
1687 | * poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1 ([{fd=0, revents=POLLIN}]) | 1692 | * poll([{fd=0, events=POLLIN}], 1, -1) = 1 ([{fd=0, revents=POLLIN}]) |
1688 | * read(0, "\n", 1) = 1 <-- oh crap, user's input got in first | 1693 | * read(0, "\n", 1) = 1 <-- oh crap, user's input got in first |
1689 | */ | 1694 | */ |
1690 | struct pollfd pfd; | 1695 | struct pollfd pfd; |
@@ -1842,10 +1847,11 @@ static void win_changed(int nsig) | |||
1842 | { | 1847 | { |
1843 | int sv_errno = errno; | 1848 | int sv_errno = errno; |
1844 | unsigned width; | 1849 | unsigned width; |
1850 | |||
1845 | get_terminal_width_height(0, &width, NULL); | 1851 | get_terminal_width_height(0, &width, NULL); |
1846 | cmdedit_setwidth(width, nsig /* - just a yes/no flag */); | 1852 | //FIXME: cmdedit_setwidth() -> redraw() -> printf() -> KABOOM! (we are in signal handler!) |
1847 | if (nsig == SIGWINCH) | 1853 | cmdedit_setwidth(width, /*redraw_flg:*/ nsig); |
1848 | signal(SIGWINCH, win_changed); /* rearm ourself */ | 1854 | |
1849 | errno = sv_errno; | 1855 | errno = sv_errno; |
1850 | } | 1856 | } |
1851 | 1857 | ||
@@ -2031,14 +2037,9 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2031 | new_settings.c_cc[VMIN] = 1; | 2037 | new_settings.c_cc[VMIN] = 1; |
2032 | new_settings.c_cc[VTIME] = 0; | 2038 | new_settings.c_cc[VTIME] = 0; |
2033 | /* Turn off CTRL-C, so we can trap it */ | 2039 | /* Turn off CTRL-C, so we can trap it */ |
2034 | #ifndef _POSIX_VDISABLE | ||
2035 | # define _POSIX_VDISABLE '\0' | ||
2036 | #endif | ||
2037 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; | 2040 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; |
2038 | tcsetattr_stdin_TCSANOW(&new_settings); | 2041 | tcsetattr_stdin_TCSANOW(&new_settings); |
2039 | 2042 | ||
2040 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); | ||
2041 | win_changed(0); /* do initial resizing */ | ||
2042 | #if ENABLE_USERNAME_OR_HOMEDIR | 2043 | #if ENABLE_USERNAME_OR_HOMEDIR |
2043 | { | 2044 | { |
2044 | struct passwd *entry; | 2045 | struct passwd *entry; |
@@ -2061,6 +2062,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2061 | parse_and_put_prompt(prompt); | 2062 | parse_and_put_prompt(prompt); |
2062 | ask_terminal(); | 2063 | ask_terminal(); |
2063 | 2064 | ||
2065 | /* Install window resize handler (NB: after *all* init is complete) */ | ||
2066 | //FIXME: save entire sigaction! | ||
2067 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); | ||
2068 | win_changed(0); /* get initial window size */ | ||
2069 | |||
2064 | read_key_buffer[0] = 0; | 2070 | read_key_buffer[0] = 0; |
2065 | while (1) { | 2071 | while (1) { |
2066 | /* | 2072 | /* |
diff --git a/libbb/llist.c b/libbb/llist.c index ed84e6472..032e9fac8 100644 --- a/libbb/llist.c +++ b/libbb/llist.c | |||
@@ -62,7 +62,7 @@ void FAST_FUNC llist_unlink(llist_t **head, llist_t *elm) | |||
62 | 62 | ||
63 | /* Recursively free all elements in the linked list. If freeit != NULL | 63 | /* Recursively free all elements in the linked list. If freeit != NULL |
64 | * call it on each datum in the list */ | 64 | * call it on each datum in the list */ |
65 | void FAST_FUNC llist_free(llist_t *elm, void (*freeit) (void *data)) | 65 | void FAST_FUNC llist_free(llist_t *elm, void (*freeit)(void *data)) |
66 | { | 66 | { |
67 | while (elm) { | 67 | while (elm) { |
68 | void *data = llist_pop(&elm); | 68 | void *data = llist_pop(&elm); |
diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c index c6c04d44a..39ffa084f 100644 --- a/libbb/pw_encrypt.c +++ b/libbb/pw_encrypt.c | |||
@@ -27,9 +27,10 @@ static int i64c(int i) | |||
27 | return ('a' - 38 + i); | 27 | return ('a' - 38 + i); |
28 | } | 28 | } |
29 | 29 | ||
30 | int FAST_FUNC crypt_make_salt(char *p, int cnt, int x) | 30 | int FAST_FUNC crypt_make_salt(char *p, int cnt /*, int x */) |
31 | { | 31 | { |
32 | x += getpid() + time(NULL); | 32 | /* was: x += ... */ |
33 | int x = getpid() + monotonic_us(); | ||
33 | do { | 34 | do { |
34 | /* x = (x*1664525 + 1013904223) % 2^32 generator is lame | 35 | /* x = (x*1664525 + 1013904223) % 2^32 generator is lame |
35 | * (low-order bit is not "random", etc...), | 36 | * (low-order bit is not "random", etc...), |
@@ -47,6 +48,26 @@ int FAST_FUNC crypt_make_salt(char *p, int cnt, int x) | |||
47 | return x; | 48 | return x; |
48 | } | 49 | } |
49 | 50 | ||
51 | char* FAST_FUNC crypt_make_pw_salt(char salt[MAX_PW_SALT_LEN], const char *algo) | ||
52 | { | ||
53 | int len = 2/2; | ||
54 | char *salt_ptr = salt; | ||
55 | if (algo[0] != 'd') { /* not des */ | ||
56 | len = 8/2; /* so far assuming md5 */ | ||
57 | *salt_ptr++ = '$'; | ||
58 | *salt_ptr++ = '1'; | ||
59 | *salt_ptr++ = '$'; | ||
60 | #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA | ||
61 | if (algo[0] == 's') { /* sha */ | ||
62 | salt[1] = '5' + (strcmp(algo, "sha512") == 0); | ||
63 | len = 16/2; | ||
64 | } | ||
65 | #endif | ||
66 | } | ||
67 | crypt_make_salt(salt_ptr, len); | ||
68 | return salt_ptr; | ||
69 | } | ||
70 | |||
50 | #if ENABLE_USE_BB_CRYPT | 71 | #if ENABLE_USE_BB_CRYPT |
51 | 72 | ||
52 | static char* | 73 | static char* |
diff --git a/libbb/read_printf.c b/libbb/read_printf.c index 8664bc625..192f83d6e 100644 --- a/libbb/read_printf.c +++ b/libbb/read_printf.c | |||
@@ -55,32 +55,35 @@ | |||
55 | * which detects EAGAIN and uses poll() to wait on the fd. | 55 | * which detects EAGAIN and uses poll() to wait on the fd. |
56 | * Thankfully, poll() doesn't care about O_NONBLOCK flag. | 56 | * Thankfully, poll() doesn't care about O_NONBLOCK flag. |
57 | */ | 57 | */ |
58 | ssize_t FAST_FUNC nonblock_safe_read(int fd, void *buf, size_t count) | 58 | ssize_t FAST_FUNC nonblock_immune_read(int fd, void *buf, size_t count, int loop_on_EINTR) |
59 | { | 59 | { |
60 | struct pollfd pfd[1]; | 60 | struct pollfd pfd[1]; |
61 | ssize_t n; | 61 | ssize_t n; |
62 | 62 | ||
63 | while (1) { | 63 | while (1) { |
64 | n = safe_read(fd, buf, count); | 64 | n = loop_on_EINTR ? safe_read(fd, buf, count) : read(fd, buf, count); |
65 | if (n >= 0 || errno != EAGAIN) | 65 | if (n >= 0 || errno != EAGAIN) |
66 | return n; | 66 | return n; |
67 | /* fd is in O_NONBLOCK mode. Wait using poll and repeat */ | 67 | /* fd is in O_NONBLOCK mode. Wait using poll and repeat */ |
68 | pfd[0].fd = fd; | 68 | pfd[0].fd = fd; |
69 | pfd[0].events = POLLIN; | 69 | pfd[0].events = POLLIN; |
70 | safe_poll(pfd, 1, -1); /* note: this pulls in printf */ | 70 | /* note: safe_poll pulls in printf */ |
71 | loop_on_EINTR ? safe_poll(pfd, 1, -1) : poll(pfd, 1, -1); | ||
71 | } | 72 | } |
72 | } | 73 | } |
73 | 74 | ||
74 | // Reads one line a-la fgets (but doesn't save terminating '\n'). | 75 | // Reads one line a-la fgets (but doesn't save terminating '\n'). |
75 | // Reads byte-by-byte. Useful when it is important to not read ahead. | 76 | // Reads byte-by-byte. Useful when it is important to not read ahead. |
76 | // Bytes are appended to pfx (which must be malloced, or NULL). | 77 | // Bytes are appended to pfx (which must be malloced, or NULL). |
77 | char* FAST_FUNC xmalloc_reads(int fd, char *buf, size_t *maxsz_p) | 78 | char* FAST_FUNC xmalloc_reads(int fd, size_t *maxsz_p) |
78 | { | 79 | { |
79 | char *p; | 80 | char *p; |
80 | size_t sz = buf ? strlen(buf) : 0; | 81 | char *buf = NULL; |
82 | size_t sz = 0; | ||
81 | size_t maxsz = maxsz_p ? *maxsz_p : (INT_MAX - 4095); | 83 | size_t maxsz = maxsz_p ? *maxsz_p : (INT_MAX - 4095); |
82 | 84 | ||
83 | goto jump_in; | 85 | goto jump_in; |
86 | |||
84 | while (sz < maxsz) { | 87 | while (sz < maxsz) { |
85 | if ((size_t)(p - buf) == sz) { | 88 | if ((size_t)(p - buf) == sz) { |
86 | jump_in: | 89 | jump_in: |
@@ -88,8 +91,8 @@ char* FAST_FUNC xmalloc_reads(int fd, char *buf, size_t *maxsz_p) | |||
88 | p = buf + sz; | 91 | p = buf + sz; |
89 | sz += 128; | 92 | sz += 128; |
90 | } | 93 | } |
91 | /* nonblock_safe_read() because we are used by e.g. shells */ | 94 | if (nonblock_immune_read(fd, p, 1, /*loop_on_EINTR:*/ 1) != 1) { |
92 | if (nonblock_safe_read(fd, p, 1) != 1) { /* EOF/error */ | 95 | /* EOF/error */ |
93 | if (p == buf) { /* we read nothing */ | 96 | if (p == buf) { /* we read nothing */ |
94 | free(buf); | 97 | free(buf); |
95 | return NULL; | 98 | return NULL; |