From 6f7a0096496a5a9e90638dc01e947015cc776110 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 9 Jun 2020 01:33:54 +0200 Subject: awk: disallow "str"++, closes bug 12981 function old new delta parse_expr 887 896 +9 Signed-off-by: Denys Vlasenko --- editors/awk.c | 4 +++- testsuite/awk.tests | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/editors/awk.c b/editors/awk.c index 70df2fdb4..f7451ae32 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -1359,8 +1359,10 @@ static node *parse_expr(uint32_t iexp) v = cn->l.v = xzalloc(sizeof(var)); if (tc & TC_NUMBER) setvar_i(v, t_double); - else + else { setvar_s(v, t_string); + xtc &= ~TC_UOPPOST; /* "str"++ is not allowed */ + } break; case TC_REGEXP: diff --git a/testsuite/awk.tests b/testsuite/awk.tests index b5008290f..87f6b5007 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -390,5 +390,13 @@ testing 'awk negative field access' \ '' \ 'anything' +# was misinterpreted as (("str"++) i) instead of ("str" (++i)) +# (and was executed: "str"++ is "0", thus concatenating "0" and "1"): +testing 'awk do not allow "str"++' \ + 'awk -v i=1 "BEGIN {print \"str\" ++i}"' \ + "str2\n" \ + '' \ + 'anything' + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 726d0d148b5a7a21eccaf8b17d2726f56ce2ce8f Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Mon, 4 May 2020 16:59:14 -0500 Subject: dhcpc: code shrink in good_hostname Incorporated valid_domain_label into good_hostname to simplify the implementation. function old new delta static.xmalloc_optname_optval 973 958 -15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-15) Total: -15 bytes text data bss dec hex filename 993144 16915 1872 1011931 f70db busybox_old 993129 16915 1872 1011916 f70cc busybox_unstripped Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpc.c | 62 +++++++++++------------------------------------- 1 file changed, 14 insertions(+), 48 deletions(-) diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 5a1f8fd7a..6422181da 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -159,61 +159,27 @@ static int mton(uint32_t mask) } #if ENABLE_FEATURE_UDHCPC_SANITIZEOPT -/* Check if a given label represents a valid DNS label - * Return pointer to the first character after the label - * (NUL or dot) upon success, NULL otherwise. - * See RFC1035, 2.3.1 - */ +/* Check if a given name represents a valid DNS name */ +/* See RFC1035, 2.3.1 */ /* We don't need to be particularly anal. For example, allowing _, hyphen * at the end, or leading and trailing dots would be ok, since it - * can't be used for attacks. (Leading hyphen can be, if someone uses - * cmd "$hostname" + * can't be used for attacks. (Leading hyphen can be, if someone uses cmd "$hostname" * in the script: then hostname may be treated as an option) */ -static const char *valid_domain_label(const char *label) -{ - unsigned char ch; - //unsigned pos = 0; - - if (label[0] == '-') - return NULL; - for (;;) { - ch = *label; - if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { - if (ch < '0' || ch > '9') { - if (ch == '\0' || ch == '.') - return label; - /* DNS allows only '-', but we are more permissive */ - if (ch != '-' && ch != '_') - return NULL; - } - } - label++; - //pos++; - //Do we want this? - //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */ - // return NULL; - } -} - -/* Check if a given name represents a valid DNS name */ -/* See RFC1035, 2.3.1 */ static int good_hostname(const char *name) { - //const char *start = name; - - for (;;) { - name = valid_domain_label(name); - if (!name) - return 0; - if (!name[0]) - return 1; - //Do we want this? - //return ((name - start) < 1025); /* NS_MAXDNAME */ - name++; - if (*name == '\0') - return 1; // We allow trailing dot too + if (*name == '-') /* Can't start with '-' */ + return 0; + + while (*name) { + unsigned char ch = *name++; + if (!isalnum(ch)) + /* DNS allows only '-', but we are more permissive */ + if (ch != '-' && ch != '_' && ch != '.') + return 0; + // TODO: do we want to validate lengths against NS_MAXLABEL and NS_MAXDNAME? } + return 1; } #else # define good_hostname(name) 1 -- cgit v1.2.3-55-g6feb From 9b4a9d96b89f06355ad9551d782d34506699aac8 Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Sun, 8 Mar 2020 13:35:20 -0500 Subject: xstrndup: Use strndup instead of implementing it. Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- libbb/xfuncs_printf.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 93f325c62..f1cf7aeed 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c @@ -93,26 +93,17 @@ char* FAST_FUNC xstrdup(const char *s) // the (possibly truncated to length n) string into it. char* FAST_FUNC xstrndup(const char *s, int n) { - int m; char *t; if (ENABLE_DEBUG && s == NULL) bb_simple_error_msg_and_die("xstrndup bug"); - /* We can just xmalloc(n+1) and strncpy into it, */ - /* but think about xstrndup("abc", 10000) wastage! */ - m = n; - t = (char*) s; - while (m) { - if (!*t) break; - m--; - t++; - } - n -= m; - t = xmalloc(n + 1); - t[n] = '\0'; + t = strndup(s, n); - return memcpy(t, s, n); + if (t == NULL) + bb_die_memory_exhausted(); + + return t; } void* FAST_FUNC xmemdup(const void *s, int n) -- cgit v1.2.3-55-g6feb From b2ab920716f640cbaaf486512ba177f4e0b597c5 Mon Sep 17 00:00:00 2001 From: Mark Edgar Date: Sat, 30 May 2020 19:05:46 +0200 Subject: unexpand: correct behavior for --first-only --tabs=4 Prior to the patch, both -f and --first-only are in all cases either no-op or ignored. Without --tabs, --first-only is the default so specifying it is a no-op. With --tabs, --all is implied, and --first-only is intended to reset this. function old new delta expand_main 690 694 +4 Signed-off-by: Mark Edgar Signed-off-by: Denys Vlasenko --- coreutils/expand.c | 8 ++++---- testsuite/unexpand.tests | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/coreutils/expand.c b/coreutils/expand.c index 4fa974df8..5f5993921 100644 --- a/coreutils/expand.c +++ b/coreutils/expand.c @@ -160,7 +160,7 @@ static void unexpand(FILE *file, unsigned tab_size, unsigned opt) putchar('\t'); } - if ((opt & OPT_INITIAL) && ptr != line) { + if (!(opt & OPT_ALL) && ptr != line) { printf("%*s%s", len, "", ptr); break; } @@ -207,13 +207,13 @@ int expand_main(int argc UNUSED_PARAM, char **argv) "ft:a" "\0" "ta" /* -t NUM sets -a */, - "first-only\0" No_argument "i" + "first-only\0" No_argument "f" "tabs\0" Required_argument "t" "all\0" No_argument "a" , &opt_t ); - /* -f --first-only is the default */ - if (!(opt & OPT_ALL)) opt |= OPT_INITIAL; + /* -t implies -a, but an explicit -f overrides */ + if (opt & OPT_INITIAL) opt &= ~OPT_ALL; } tab_size = xatou_range(opt_t, 1, UINT_MAX); diff --git a/testsuite/unexpand.tests b/testsuite/unexpand.tests index 7b326dc2c..4ab693ec8 100755 --- a/testsuite/unexpand.tests +++ b/testsuite/unexpand.tests @@ -31,6 +31,39 @@ testing "unexpand case 7" "unexpand" \ testing "unexpand case 8" "unexpand" \ "a b\n" "" "a b\n" \ +testcase() +{ + testing "unexpand flags $*" "unexpand $*" \ + "$want" "" ' a b c' +} + +# tabs=8, Convert only leading sequences of blanks +want='\ta b c' +testcase +testcase -f +testcase -f -t8 +testcase -t8 -f +testcase -t8 --first-only + +# tabs=8, Convert all blanks +want='\ta\tb c' +testcase -a +testcase -t8 +testcase -a -t8 + +# tabs=4, Convert all blanks +want='\t\ta\t\tb\t c' +testcase -t4 +testcase -a -t4 +testcase -t4 -a + +# tabs=4, Convert only leading sequences of blanks +want='\t\ta b c' +testcase -t4 -f +testcase -f -t4 +testcase -t4 --first-only +testcase --first-only -t4 + test x"$CONFIG_UNICODE_SUPPORT" = x"y" \ && test x"$CONFIG_UNICODE_USING_LOCALE" != x"y" \ && testing "unexpand with unicode characher 0x394" "unexpand" \ -- cgit v1.2.3-55-g6feb From 002be6e821eedfa190c5b060e7b61acb306c2a92 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 9 Jun 2020 15:58:32 +0200 Subject: sysctl: do report EACCES errors on write function old new delta sysctl_act_recursive 165 179 +14 sysctl_act_on_setting 467 471 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 18/0) Total: 18 bytes Signed-off-by: Denys Vlasenko --- procps/sysctl.c | 9 ++++++--- testsuite/unexpand.tests | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/procps/sysctl.c b/procps/sysctl.c index 6d77185ca..e16b119e9 100644 --- a/procps/sysctl.c +++ b/procps/sysctl.c @@ -169,13 +169,15 @@ static int sysctl_act_on_setting(char *setting) if (fd < 0) { switch (errno) { - case EACCES: - /* Happens for write-only settings, e.g. net.ipv6.route.flush */ - goto end; case ENOENT: if (option_mask32 & FLAG_SHOW_KEY_ERRORS) bb_error_msg("error: '%s' is an unknown key", outname); break; + case EACCES: + /* Happens for write-only settings, e.g. net.ipv6.route.flush */ + if (!writing) + goto end; + /* fall through */ default: bb_perror_msg("error %sing key '%s'", writing ? @@ -236,6 +238,7 @@ static int sysctl_act_recursive(const char *path) int retval = 0; if (!(option_mask32 & FLAG_WRITE) + && !strchr(path, '=') /* do not try to resurse on "var=val" */ && stat(path, &buf) == 0 && S_ISDIR(buf.st_mode) ) { diff --git a/testsuite/unexpand.tests b/testsuite/unexpand.tests index 4ab693ec8..aeaae13f0 100755 --- a/testsuite/unexpand.tests +++ b/testsuite/unexpand.tests @@ -33,8 +33,8 @@ testing "unexpand case 8" "unexpand" \ testcase() { - testing "unexpand flags $*" "unexpand $*" \ - "$want" "" ' a b c' + testing "unexpand flags $*" "unexpand $*" \ + "$want" "" ' a b c' } # tabs=8, Convert only leading sequences of blanks -- cgit v1.2.3-55-g6feb From 0cad5f9b6dd80858c3ebb3893e04d2378eddc872 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 9 Jun 2020 17:22:06 +0200 Subject: udhcp: comment out unused domain compression code function old new delta attach_option 411 406 -5 dname_enc 381 167 -214 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-219) Total: -219 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 2 +- networking/udhcp/common.h | 2 +- networking/udhcp/domain_codec.c | 27 ++++++++++++++++----------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 9ec752dfc..16bf69707 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -431,7 +431,7 @@ static NOINLINE void attach_option( #if ENABLE_FEATURE_UDHCP_RFC3397 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { /* reuse buffer and length for RFC1035-formatted string */ - allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); + allocated = buffer = (char *)dname_enc(/*NULL, 0,*/ buffer, &length); } #endif diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 60255eefa..73f860a77 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -218,7 +218,7 @@ void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t #endif #if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704 char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; -uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; +uint8_t *dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) FAST_FUNC; #endif struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c index b7a3a5353..752c0a863 100644 --- a/networking/udhcp/domain_codec.c +++ b/networking/udhcp/domain_codec.c @@ -109,11 +109,11 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) return ret; } -/* Convert a domain name (src) from human-readable "foo.blah.com" format into +/* Convert a domain name (src) from human-readable "foo.BLAH.com" format into * RFC1035 encoding "\003foo\004blah\003com\000". Return allocated string, or * NULL if an error occurs. */ -static uint8_t *convert_dname(const char *src) +static uint8_t *convert_dname(const char *src, int *retlen) { uint8_t c, *res, *lenptr, *dst; int len; @@ -129,6 +129,7 @@ static uint8_t *convert_dname(const char *src) /* label too long, too short, or two '.'s in a row? abort */ if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { free(res); + *retlen = 0; return NULL; } *lenptr = len; @@ -144,13 +145,16 @@ static uint8_t *convert_dname(const char *src) if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */ free(res); + *retlen = 0; return NULL; } - *dst = 0; + *dst++ = 0; + *retlen = dst - res; return res; } +#if 0 //UNUSED /* Returns the offset within cstr at which dname can be found, or -1 */ static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) { @@ -188,28 +192,27 @@ static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) return -1; } +#endif +uint8_t* FAST_FUNC dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) +{ +#if 0 //UNUSED, was intended for long, repetitive DHCP_DOMAIN_SEARCH options? + uint8_t *d, *dname; /* Computes string to be appended to cstr so that src would be added to * the compression (best case, it's a 2-byte pointer to some offset within * cstr; worst case, it's all of src, converted to <4>host<3>com<0> format). * The computed string is returned directly; its length is returned via retlen; * NULL and 0, respectively, are returned if an error occurs. */ -uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) -{ - uint8_t *d, *dname; - int off; - - dname = convert_dname(src); + dname = convert_dname(src, retlen); if (dname == NULL) { - *retlen = 0; return NULL; } d = dname; while (*d) { if (cstr) { - off = find_offset(cstr, clen, d); + int off = find_offset(cstr, clen, d); if (off >= 0) { /* found a match, add pointer and return */ *d++ = NS_CMPRSFLGS | (off >> 8); *d = off; @@ -221,6 +224,8 @@ uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen = d - dname + 1; return dname; +#endif + return convert_dname(src, retlen); } #ifdef DNS_COMPR_TESTING -- cgit v1.2.3-55-g6feb From 17764603f2a10bd43d174dc05512f38ab16a080a Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 9 Jun 2020 17:38:21 +0200 Subject: httpd: allow '-h' to work when daemonized with NOMMU enabled Commit d1b75e184 (httpd: permit non-default home directory with NOMMU enabled) only works when used with the '-f' (foreground) option. When '-f' isn't specified and NOMMU is enabled bb_daemonize_or_rexec() is called to daemonize the server. Since the server process has been re-execed the previous patch results in the xchdir() not being called. Fix this by resetting the re_execed variable in this case. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- networking/httpd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/httpd.c b/networking/httpd.c index c2d226592..f4e95768f 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -2734,11 +2734,11 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) #if !BB_MMU if (!(opt & OPT_FOREGROUND)) { bb_daemonize_or_rexec(0, argv); /* don't change current directory */ + re_execed = 0; /* for the following chdir to work */ } #endif - - /* Chdir to home (unless we were re-execed for NOMMU case: - * we are already in the home dir then). + /* Chdir to home (unless we were re_exec()ed for NOMMU case + * in mini_httpd_nommu(): we are already in the home dir then). */ if (!re_execed) xchdir(home_httpd); -- cgit v1.2.3-55-g6feb From d30d1ebc117db182a6156df182057291d6fbaae1 Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Tue, 9 Jun 2020 16:59:54 -0500 Subject: dhcpc: refactor xmalloc_optname_optval to shrink binary size function old new delta len_of_option_as_string 14 13 -1 dhcp_option_lengths 14 13 -1 udhcp_str2optset 641 637 -4 static.xmalloc_optname_optval 777 718 -59 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-65) Total: -65 bytes Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- networking/udhcp/common.h | 2 +- networking/udhcp/dhcpc.c | 41 +++++++++++++++-------------------------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 73f860a77..6214db06a 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -78,7 +78,7 @@ struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet { /*** Options ***/ enum { - OPTION_IP = 1, + OPTION_IP = 0, OPTION_IP_PAIR, OPTION_STRING, /* Opts of STRING_HOST type will be sanitized before they are passed diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 6422181da..102178a4f 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -208,9 +208,8 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ case OPTION_IP: case OPTION_IP_PAIR: dest += sprint_nip(dest, "", option); - if (type == OPTION_IP) - break; - dest += sprint_nip(dest, "/", option + 4); + if (type == OPTION_IP_PAIR) + dest += sprint_nip(dest, "/", option + 4); break; // case OPTION_BOOLEAN: // dest += sprintf(dest, *option ? "yes" : "no"); @@ -312,7 +311,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ * IPv4MaskLen <= 32, * 6rdPrefixLen <= 128, * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128 - * (2nd condition need no check - it follows from 1st and 3rd). + * (2nd condition needs no check - it follows from 1st and 3rd). * Else, return envvar with empty value ("optname=") */ if (len >= (1 + 1 + 16 + 4) @@ -326,17 +325,12 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ /* 6rdPrefix */ dest += sprint_nip6(dest, /* "", */ option); option += 16; - len -= 1 + 1 + 16 + 4; - /* "+ 4" above corresponds to the length of IPv4 addr - * we consume in the loop below */ - while (1) { - /* 6rdBRIPv4Address(es) */ - dest += sprint_nip(dest, " ", option); - option += 4; - len -= 4; /* do we have yet another 4+ bytes? */ - if (len < 0) - break; /* no */ - } + len -= 1 + 1 + 16; + *dest++ = ' '; + /* 6rdBRIPv4Address(es), use common IPv4 logic to process them */ + type = OPTION_IP; + optlen = 4; + continue; } return ret; @@ -358,23 +352,18 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ */ option++; len--; + if (option[-1] == 1) { + /* use common IPv4 logic to process IP addrs */ + type = OPTION_IP; + optlen = 4; + continue; + } if (option[-1] == 0) { dest = dname_dec(option, len, ret); if (dest) { free(ret); return dest; } - } else - if (option[-1] == 1) { - const char *pfx = ""; - while (1) { - len -= 4; - if (len < 0) - break; - dest += sprint_nip(dest, pfx, option); - pfx = " "; - option += 4; - } } return ret; #endif -- cgit v1.2.3-55-g6feb From 0356607264b8e1476d98a81667488ba1d6295d23 Mon Sep 17 00:00:00 2001 From: Sören Tempel Date: Tue, 9 Jun 2020 17:51:26 +0200 Subject: deluser: check if specified home is a directory before removing it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Alpine, some users use /dev/null as a home directory. When removing such a user with `deluser --remove-home` this causes the /dev/null device file to be removed which is undesirable. To prevent this pitfall, check if the home directory specified for the user is an actual directory (or a symlink to a directory). Implementations of similar tools for other operating systems also implement such checks. For instance, the OpenBSD rmuser(1) implementation [0]. [0]: https://github.com/openbsd/src/blob/b69faa6c70c5bfcfdddc6138cd8e0ee18cc15b03/usr.sbin/adduser/rmuser.perl#L143-L151 function old new delta deluser_main 337 380 +43 Signed-off-by: Sören Tempel Signed-off-by: Denys Vlasenko --- loginutils/deluser.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 56bc7eaa6..8e7df737c 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -99,8 +99,14 @@ int deluser_main(int argc, char **argv) pfile = bb_path_passwd_file; if (ENABLE_FEATURE_SHADOWPASSWDS) sfile = bb_path_shadow_file; - if (opt_delhome) - remove_file(pw->pw_dir, FILEUTILS_RECUR); + if (opt_delhome) { + struct stat st; + + /* Make sure home is an actual directory before + * removing it (e.g. users with /dev/null as home) */ + if (stat(pw->pw_dir, &st) == 0 && S_ISDIR(st.st_mode)) + remove_file(pw->pw_dir, FILEUTILS_RECUR); + } } else { struct group *gr; do_delgroup: -- cgit v1.2.3-55-g6feb From 505eeae402a84dc5208986c5ad611f5e485cbe34 Mon Sep 17 00:00:00 2001 From: Biswapriyo Nath Date: Tue, 9 Jun 2020 23:05:12 +0530 Subject: Makefile.flags: restrict Wno-constant-logical-operand and Wno-string-plus-int options for clang these options were added in b4ef2e3467d8e980ccf13c9dd342459c013b455f commit gcc shows unrecognized command-line option warnings Signed-off-by: Biswapriyo Nath Signed-off-by: Denys Vlasenko --- Makefile.flags | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile.flags b/Makefile.flags index bed766b8a..cff935ff5 100644 --- a/Makefile.flags +++ b/Makefile.flags @@ -77,7 +77,9 @@ CFLAGS += $(call cc-option,-fno-asynchronous-unwind-tables,) CFLAGS += $(call cc-option,-fno-builtin-printf,) # clang-9 does not like "str" + N and "if (CONFIG_ITEM && cond)" constructs +ifeq ($(CC),clang) CFLAGS += $(call cc-option,-Wno-string-plus-int -Wno-constant-logical-operand) +endif # FIXME: These warnings are at least partially to be concerned about and should # be fixed.. -- cgit v1.2.3-55-g6feb From 4789c7cd8152fee53c176e569b022ec4013597a0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 10 Jun 2020 15:37:39 +0200 Subject: nmeter: add %T (zero-based timestamp) format function old new delta collect_tv - 132 +132 collect_monotonic - 61 +61 nmeter_main 754 778 +24 gmtime - 21 +21 init_monotonic - 18 +18 init_functions 44 48 +4 packed_usage 33432 33420 -12 collect_time 125 19 -106 ------------------------------------------------------------------------------ (add/remove: 5/0 grow/shrink: 2/2 up/down: 260/-118) Total: 142 bytes Signed-off-by: Denys Vlasenko --- procps/nmeter.c | 68 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/procps/nmeter.c b/procps/nmeter.c index ae16d8548..856ce0202 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -37,6 +37,7 @@ //usage: "\n %[pn] # of processes" //usage: "\n %b Block io" //usage: "\n %Nt Time (with N decimal points)" +//usage: "\n %NT Zero-based timestamp (with N decimal points)" //usage: "\n %r Print instead of at EOL" //TODO: @@ -88,6 +89,7 @@ struct globals { int delta; unsigned deltanz; struct timeval tv; + struct timeval start; #define first_proc_file proc_stat proc_file proc_stat; // Must match the order of proc_name's! proc_file proc_loadavg; @@ -101,7 +103,6 @@ struct globals { #define is26 (G.is26 ) #define need_seconds (G.need_seconds ) #define cur_outbuf (G.cur_outbuf ) -#define tv (G.tv ) #define proc_stat (G.proc_stat ) #define proc_loadavg (G.proc_loadavg ) #define proc_net_dev (G.proc_net_dev ) @@ -754,25 +755,53 @@ S_STAT(time_stat) unsigned scale; S_STAT_END(time_stat) -static void FAST_FUNC collect_time(time_stat *s) +static void FAST_FUNC collect_tv(time_stat *s, struct timeval *tv, int local) { char buf[sizeof("12:34:56.123456")]; struct tm* tm; - unsigned us = tv.tv_usec + s->scale/2; - time_t t = tv.tv_sec; + unsigned us = tv->tv_usec + s->scale/2; + time_t t = tv->tv_sec; if (us >= 1000000) { t++; us -= 1000000; } - tm = localtime(&t); + if (local) + tm = localtime(&t); + else + tm = gmtime(&t); - sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); + sprintf(buf, "%02u:%02u:%02u", tm->tm_hour, tm->tm_min, tm->tm_sec); if (s->prec) - sprintf(buf+8, ".%0*d", s->prec, us / s->scale); + sprintf(buf+8, ".%0*u", s->prec, us / s->scale); put(buf); } +static void FAST_FUNC collect_time(time_stat *s) +{ + collect_tv(s, &G.tv, /*local:*/ 1); +} + +static void FAST_FUNC collect_monotonic(time_stat *s) +{ + struct timeval tv_mono; + + tv_mono.tv_sec = G.tv.tv_sec - G.start.tv_sec; +#if 0 /* Do we want this? */ + if (tv_mono.tv_sec < 0) { + /* Time went backwards, reset start time to "now" */ + tv_mono.tv_sec = 0; + G.start = G.tv; + } +#endif + tv_mono.tv_usec = G.tv.tv_usec - G.start.tv_usec; + if ((int32_t)tv_mono.tv_usec < 0) { + tv_mono.tv_usec += 1000000; + tv_mono.tv_sec--; + } + collect_tv(s, &tv_mono, /*local:*/ 0); +} + static s_stat* init_time(const char *param) { int prec; @@ -789,6 +818,13 @@ static s_stat* init_time(const char *param) return (s_stat*)s; } +static s_stat* init_monotonic(const char *param) +{ + time_stat *s = (void*)init_time(param); + s->collect = collect_monotonic; + return (s_stat*)s; +} + static void FAST_FUNC collect_info(s_stat *s) { gen ^= 1; @@ -801,7 +837,7 @@ static void FAST_FUNC collect_info(s_stat *s) typedef s_stat* init_func(const char *param); -static const char options[] ALIGN1 = "ncmsfixptbr"; +static const char options[] ALIGN1 = "ncmsfixptTbr"; static init_func *const init_functions[] = { init_if, init_cpu, @@ -812,6 +848,7 @@ static init_func *const init_functions[] = { init_ctx, init_fork, init_time, + init_monotonic, init_blk, init_cr }; @@ -913,13 +950,15 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) // Generate first samples but do not print them, they're bogus collect_info(first); reset_outbuf(); + if (G.delta >= 0) { - gettimeofday(&tv, NULL); - usleep(G.delta > 1000000 ? 1000000 : G.delta - tv.tv_usec % G.deltanz); + gettimeofday(&G.tv, NULL); + usleep(G.delta > 1000000 ? 1000000 : G.delta - G.tv.tv_usec % G.deltanz); } + gettimeofday(&G.start, NULL); + G.tv = G.start; while (1) { - gettimeofday(&tv, NULL); collect_info(first); put_c(G.final_char); print_outbuf(); @@ -932,11 +971,11 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) if (G.delta >= 0) { int rem; // can be commented out, will sacrifice sleep time precision a bit - gettimeofday(&tv, NULL); + gettimeofday(&G.tv, NULL); if (need_seconds) - rem = G.delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % G.deltanz; + rem = G.delta - ((ullong)G.tv.tv_sec*1000000 + G.tv.tv_usec) % G.deltanz; else - rem = G.delta - (unsigned)tv.tv_usec % G.deltanz; + rem = G.delta - (unsigned)G.tv.tv_usec % G.deltanz; // Sometimes kernel wakes us up just a tiny bit earlier than asked // Do not go to very short sleep in this case if (rem < (unsigned)G.delta / 128) { @@ -944,6 +983,7 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv) } usleep(rem); } + gettimeofday(&G.tv, NULL); } /*return 0;*/ -- cgit v1.2.3-55-g6feb From faab906d2867145c81e9bcb1f2bb1f81fd90e734 Mon Sep 17 00:00:00 2001 From: Uwe Glaeser Date: Sun, 21 Jun 2020 02:56:12 +0200 Subject: udhcpc6: use correct multicast MAC function old new delta static.MAC_DHCP6MCAST_ADDR - 6 +6 Signed-off-by: Uwe Glaeser Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 85c410a7c..fc2d672b7 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -553,11 +553,15 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, }; + /* IPv6 requires different multicast contents in Ethernet Frame (RFC 2464) */ + static const uint8_t MAC_DHCP6MCAST_ADDR[6] ALIGN2 = { + 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, + }; return d6_send_raw_packet( packet, (end - (uint8_t*) packet), /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, - /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR, + /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR, client_data.ifindex ); } -- cgit v1.2.3-55-g6feb From 62744efa472886ea8fdeb262dcb184974e3f88de Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 16 Jun 2020 10:06:27 +0200 Subject: examples/udhcp/simple.script: fix IPv6 support when using udhcpc The udhcpc script calls ip addr flush .. which flushes addresses of any address family, including IPv6. However, busybox udhcpc is IPv4 only and should not influence IPv6 addressing. Hence use ip addr flush with family constraint. The script particularly broke IPv6 SLAAC: Typically when udhcpc calls the script the kernel already assigned the IPv6 link-local address. The flush removes the link-local IPv6 address again and prohibits proper IPv6 operation such as SLAAC since neighbor discovery protocol relies on IPv6 link-local addressing. Signed-off-by: Stefan Agner [Taken from https://git.openembedded.org/openembedded-core/commit/meta/recipes-core/busybox/files/simple.script?id=b77541dbb2f442e51842f9d24c8745a6df2d1478] Signed-off-by: Quentin Schulz Signed-off-by: Denys Vlasenko --- examples/udhcp/simple.script | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/udhcp/simple.script b/examples/udhcp/simple.script index 6658fbeef..f079ec8b8 100755 --- a/examples/udhcp/simple.script +++ b/examples/udhcp/simple.script @@ -18,7 +18,7 @@ case "$1" in deconfig) echo "Clearing IP addresses on $interface, upping it" if command -v ip >/dev/null; then - ip addr flush dev $interface + ip -4 addr flush dev $interface ip link set dev $interface up else ifconfig $interface 0.0.0.0 -- cgit v1.2.3-55-g6feb From 6eb38fded2f459f2828121a2f6b1499da2677553 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 23 Jun 2020 02:46:53 +0200 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 ++ networking/brctl.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/libbb.h b/include/libbb.h index 392c0443d..d9858f5df 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1385,8 +1385,10 @@ static inline void __attribute__ ((deprecated("use bb_simple_info_msg instead")) #define bb_perror_msg_and_die(...) BB_MSG(_perror_msg_and_die, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) #define bb_herror_msg(...) BB_MSG(_herror_msg, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) #define bb_herror_msg_and_die(...) BB_MSG(_herror_msg_and_die, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) +#if ENABLE_FEATURE_SYSLOG_INFO #define bb_info_msg(...) BB_MSG(_info_msg, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) #endif +#endif /* We need to export XXX_main from libbusybox * only if we build "individual" binaries diff --git a/networking/brctl.c b/networking/brctl.c index 25640246d..68725f93c 100644 --- a/networking/brctl.c +++ b/networking/brctl.c @@ -591,6 +591,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) return EXIT_SUCCESS; } +#if ENABLE_FEATURE_BRCTL_FANCY if (key == ARG_showmacs) { show_bridge_macs(br); return EXIT_SUCCESS; @@ -599,6 +600,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) show_bridge_stp(br); return EXIT_SUCCESS; } +#endif if (!*argv) /* All of the below need at least two arguments */ bb_show_usage(); -- cgit v1.2.3-55-g6feb From df1f479fc5167d6fa82b127c91a3851c0035fcac Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 23 Jun 2020 03:13:55 +0200 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- networking/brctl.c | 4 +++- procps/top.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/networking/brctl.c b/networking/brctl.c index 68725f93c..2f4ac4a87 100644 --- a/networking/brctl.c +++ b/networking/brctl.c @@ -107,7 +107,7 @@ static unsigned str_to_jiffies(const char *time_str) #define filedata bb_common_bufsiz1 -#if ENABLE_FEATURE_BRCTL_SHOW +#if ENABLE_FEATURE_BRCTL_SHOW || ENABLE_FEATURE_BRCTL_FANCY static int read_file(const char *name) { int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1); @@ -120,7 +120,9 @@ static int read_file(const char *name) } return n; } +#endif +#if ENABLE_FEATURE_BRCTL_SHOW /* NB: we are in /sys/class/net */ static int show_bridge(const char *name, int need_hdr) diff --git a/procps/top.c b/procps/top.c index 5c41e8e10..8d39526ff 100644 --- a/procps/top.c +++ b/procps/top.c @@ -979,9 +979,11 @@ static unsigned handle_input(unsigned scan_mask, duration_t interval) IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK) ) { scan_mask ^= PSSCAN_TASKS; +# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE free(prev_hist); prev_hist = NULL; prev_hist_count = 0; +# endif continue; } # endif -- cgit v1.2.3-55-g6feb From 03ab212bff0fa7f51c0f75ee4be5db67184e41a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 23 Jun 2020 03:43:39 +0200 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- miscutils/devfsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index f3d935b2e..d47ee4d47 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c @@ -353,6 +353,7 @@ static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found"; #define error_logger_and_die(p, fmt, args...) bb_perror_msg_and_die(fmt, ## args) #else #define info_logger(p, fmt, args...) +#define simple_info_logger(p, msg) #define msg_logger(p, fmt, args...) #define simple_msg_logger(p, msg) #define msg_logger_and_die(p, fmt, args...) exit(EXIT_FAILURE) -- cgit v1.2.3-55-g6feb From d206b1651ac4dc4db1d9bbd172a81da0568b42e8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 23 Jun 2020 09:38:53 +0200 Subject: randomconfig fix Signed-off-by: Denys Vlasenko --- include/platform.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/platform.h b/include/platform.h index 50365a31c..43bb391bd 100644 --- a/include/platform.h +++ b/include/platform.h @@ -30,6 +30,10 @@ # endif #endif +#if !__GNUC_PREREQ(5,0) +# define deprecated(msg) deprecated +#endif + #undef inline #if defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L /* it's a keyword */ -- cgit v1.2.3-55-g6feb From 5fa5c4bde8b9ab75fa0ed37ee2fafca3fd46288a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 23 Jun 2020 21:28:19 +0200 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- editors/patch.c | 3 ++- include/libbb.h | 1 + libbb/duration.c | 1 + scripts/randomtest | 22 ++++++++++++++++++++++ testsuite/cpio.tests | 6 +++--- testsuite/patch.tests | 4 ++-- 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/editors/patch.c b/editors/patch.c index 0ce0210fd..aaa253591 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -264,7 +264,7 @@ static int apply_one_hunk(void) if (!plist && matcheof) break; if (backwarn) - fdprintf(2,"Possibly reversed hunk %d at %ld\n", + fdprintf(2, "Possibly reversed hunk %d at %ld\n", TT.hunknum, TT.linenum); // File ended before we found a place for this hunk. @@ -593,6 +593,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) TT.linenum = 0; TT.hunknum = 0; } + fflush_all(); // make "patching file F" visible } TT.hunknum++; diff --git a/include/libbb.h b/include/libbb.h index d9858f5df..6be934994 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -298,6 +298,7 @@ typedef unsigned long uoff_t; /* scary. better ideas? (but do *test* them first!) */ #define OFF_T_MAX ((off_t)~((off_t)1 << (sizeof(off_t)*8-1))) /* Users report bionic to use 32-bit off_t even if LARGEFILE support is requested. + * On musl, !ENABLE_LFS on 32-bit arches thinks that off_t is 32-bit. * We misdetected that. Don't let it build: */ struct BUG_off_t_size_is_misdetected { diff --git a/libbb/duration.c b/libbb/duration.c index 5acd0dba3..22b209f4d 100644 --- a/libbb/duration.c +++ b/libbb/duration.c @@ -17,6 +17,7 @@ //kbuild:lib-$(CONFIG_TIMEOUT) += duration.o //kbuild:lib-$(CONFIG_PING) += duration.o //kbuild:lib-$(CONFIG_PING6) += duration.o +//kbuild:lib-$(CONFIG_WATCH) += duration.o #include "libbb.h" diff --git a/scripts/randomtest b/scripts/randomtest index 94709a99f..ec2f095b2 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -113,6 +113,28 @@ if test x"$LIBC" = x"uclibc"; then echo 'CONFIG_ASH_INTERNAL_GLOB=y' >>.config fi +# If musl +if test x"$LIBC" = x"musl"; then + cat .config \ + | grep -v CONFIG_STATIC \ + | grep -v CONFIG_LFS \ + | grep -v CONFIG_EXTRA_COMPAT \ + | grep -v CONFIG_FEATURE_2_4_MODULES \ + | grep -v CONFIG_FEATURE_VI_REGEX_SEARCH \ + | grep -v CONFIG_FEATURE_MOUNT_NFS \ + | grep -v CONFIG_FEATURE_INETD_RPC \ + >.config.new + mv .config.new .config + echo 'CONFIG_STATIC=y' >>.config + # with LFS off, uoff_t will have wrong width: + echo 'CONFIG_LFS=y' >>.config + echo '# CONFIG_EXTRA_COMPAT is not set' >>.config + echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config + echo '# CONFIG_FEATURE_VI_REGEX_SEARCH is not set' >>.config + echo '# CONFIG_FEATURE_MOUNT_NFS is not set' >>.config + echo '# CONFIG_FEATURE_INETD_RPC is not set' >>.config +fi + # If STATIC, remove some things. # PAM with static linking is probably pointless # (but I need to try - now I don't have libpam.a on my system, only libpam.so) diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index 88ec086b6..85e746589 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests @@ -129,7 +129,7 @@ SKIP= optional FEATURE_CPIO_O testing "cpio uses by default uid/gid" \ -"echo $0 | cpio -o -H newc | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ +"echo $0 | cpio -o -H newc | cpio -tv 2>&1 | head -n1 | awk ' { print \$2 } '; echo \$?" \ "\ $user/$group 0 @@ -138,7 +138,7 @@ SKIP= optional FEATURE_CPIO_O testing "cpio -R with create" \ -"echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ +"echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | head -n1 | awk ' { print \$2 } '; echo \$?" \ "\ 1234/5678 0 @@ -147,7 +147,7 @@ SKIP= optional FEATURE_CPIO_O testing "cpio -R with extract" \ -"echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ +"echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | head -n1 | awk ' { print \$2 } '; echo \$?" \ "\ 8765/4321 0 diff --git a/testsuite/patch.tests b/testsuite/patch.tests index 39205242c..1d48e90be 100755 --- a/testsuite/patch.tests +++ b/testsuite/patch.tests @@ -75,12 +75,12 @@ zxc testing "patch detects already applied hunk" \ 'patch 2>&1; echo $?; cat input' \ "\ +patching file input Possibly reversed hunk 1 at 4 Hunk 1 FAILED 1/1. abc +def 123 -patching file input 1 abc def @@ -103,12 +103,12 @@ def testing "patch detects already applied hunk at the EOF" \ 'patch 2>&1; echo $?; cat input' \ "\ +patching file input Possibly reversed hunk 1 at 4 Hunk 1 FAILED 1/1. abc 123 +456 -patching file input 1 abc 123 -- cgit v1.2.3-55-g6feb From 7c443d110d4dc51ba48bad8ed1427716b754bf2e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Jun 2020 00:27:37 +0200 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- archival/cpio.c | 1 + scripts/randomtest | 3 +++ testsuite/mdev.tests | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 0f37ffbb9..94b4b8174 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -516,6 +516,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) if (archive_handle->cpio__blocks != (off_t)-1 && !(opt & OPT_QUIET) ) { + fflush_all(); fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); } diff --git a/scripts/randomtest b/scripts/randomtest index ec2f095b2..76550d267 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -117,6 +117,7 @@ fi if test x"$LIBC" = x"musl"; then cat .config \ | grep -v CONFIG_STATIC \ + | grep -v CONFIG_DEBUG_SANITIZE \ | grep -v CONFIG_LFS \ | grep -v CONFIG_EXTRA_COMPAT \ | grep -v CONFIG_FEATURE_2_4_MODULES \ @@ -126,6 +127,8 @@ if test x"$LIBC" = x"musl"; then >.config.new mv .config.new .config echo 'CONFIG_STATIC=y' >>.config + # "error: cannot specify -static with -fsanitize=address": + echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config # with LFS off, uoff_t will have wrong width: echo 'CONFIG_LFS=y' >>.config echo '# CONFIG_EXTRA_COMPAT is not set' >>.config diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 8e53ec564..44a723024 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests @@ -93,7 +93,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 444 >disk/scsiA" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_LS_SORTFILES testing "mdev move/symlink rule '>bar/baz'" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -111,7 +111,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 444 >disk/" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_LS_SORTFILES testing "mdev move/symlink rule '>bar/'" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ -- cgit v1.2.3-55-g6feb From d5314e71294d228cff5d86e00d15661461f68fc9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Jun 2020 09:31:30 +0200 Subject: suppress a few compile warnings Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 2 +- shell/hush.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index de236dea0..e40a72064 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -99,7 +99,7 @@ static bool BB_ispunct(CHAR_T c) # if ENABLE_FEATURE_EDITING_VI static bool BB_isalnum_or_underscore(CHAR_T c) { - return ((unsigned)c < 256 && isalnum(c)) || c == '_'; + return isalnum(c) || c == '_'; } # endif # define BB_ispunct(c) ispunct(c) diff --git a/shell/hush.c b/shell/hush.c index cab7ea5b0..2cf2170ca 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7917,7 +7917,7 @@ static const struct built_in_command *find_builtin(const char *name) return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); } -#if EDITING_HAS_get_exe_name +#if ENABLE_HUSH_JOB && EDITING_HAS_get_exe_name static const char * FAST_FUNC get_builtin_name(int i) { if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { -- cgit v1.2.3-55-g6feb From 67e1529b921416d6c3f33fb43691bc9919e3eacc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Jun 2020 13:39:13 +0200 Subject: nologin: make it possible to build it as single applet Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 38 +++++++++++++++++++++++---- shell/Config.src | 20 ++++++++------ shell/ash.c | 41 +++++++++++++++-------------- shell/hush.c | 73 ++++++++++++++++++++++++++++++---------------------- util-linux/nologin.c | 2 +- 5 files changed, 110 insertions(+), 64 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f842e73cc..a515c3fe3 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -754,7 +754,9 @@ static void install_links(const char *busybox UNUSED_PARAM, } # endif +# if ENABLE_BUSYBOX || NUM_APPLETS > 0 static void run_applet_and_exit(const char *name, char **argv) NORETURN; +#endif # if NUM_SCRIPTS > 0 static int find_script_by_name(const char *name) @@ -775,13 +777,13 @@ int scripted_main(int argc UNUSED_PARAM, char **argv) { int script = find_script_by_name(applet_name); if (script >= 0) -#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH +# if ENABLE_SHELL_ASH exit(ash_main(-script - 1, argv)); -#elif ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH +# elif ENABLE_SHELL_HUSH exit(hush_main(-script - 1, argv)); -#else +# else return 1; -#endif +# endif return 0; } @@ -1024,7 +1026,33 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv) } # endif -#endif /* !defined(SINGLE_APPLET_MAIN) */ +#else /* defined(SINGLE_APPLET_MAIN) */ + +# if NUM_SCRIPTS > 0 +/* if SINGLE_APPLET_MAIN, these two functions are simpler: */ +int scripted_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; +int scripted_main(int argc UNUSED_PARAM, char **argv) +{ +# if ENABLE_SHELL_ASH + int script = 0; + exit(ash_main(-script - 1, argv)); +# elif ENABLE_SHELL_HUSH + int script = 0; + exit(hush_main(-script - 1, argv)); +# else + return 1; +# endif +} +char* FAST_FUNC +get_script_content(unsigned n UNUSED_PARAM) +{ + char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), + UNPACKED_SCRIPTS_LENGTH); + return t; +} +# endif /* NUM_SCRIPTS > 0 */ + +#endif /* defined(SINGLE_APPLET_MAIN) */ #if ENABLE_BUILD_LIBBUSYBOX diff --git a/shell/Config.src b/shell/Config.src index d7623f774..5efbf9995 100644 --- a/shell/Config.src +++ b/shell/Config.src @@ -17,6 +17,7 @@ choice config SH_IS_ASH depends on !NOMMU bool "ash" + select SHELL_ASH help Choose ash to be the shell executed by 'sh' name. The ash code will be built into busybox. If you don't select @@ -25,6 +26,7 @@ config SH_IS_ASH config SH_IS_HUSH bool "hush" + select SHELL_HUSH help Choose hush to be the shell executed by 'sh' name. The hush code will be built into busybox. If you don't select @@ -57,6 +59,7 @@ choice config BASH_IS_ASH depends on !NOMMU bool "ash" + select SHELL_ASH help Choose ash to be the shell executed by 'bash' name. The ash code will be built into busybox. If you don't select @@ -65,6 +68,7 @@ config BASH_IS_ASH config BASH_IS_HUSH bool "hush" + select SHELL_HUSH help Choose hush to be the shell executed by 'bash' name. The hush code will be built into busybox. If you don't select @@ -81,12 +85,12 @@ INSERT comment "Options common to all shells" -if ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH +if SHELL_ASH || SHELL_HUSH config FEATURE_SH_MATH bool "POSIX math support" default y - depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH + depends on SHELL_ASH || SHELL_HUSH help Enable math support in the shell via $((...)) syntax. @@ -107,14 +111,14 @@ config FEATURE_SH_MATH_BASE config FEATURE_SH_EXTRA_QUIET bool "Hide message on interactive shell startup" default y - depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH + depends on SHELL_ASH || SHELL_HUSH help Remove the busybox introduction when starting a shell. config FEATURE_SH_STANDALONE bool "Standalone shell" default n - depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH + depends on SHELL_ASH || SHELL_HUSH help This option causes busybox shells to use busybox applets in preference to executables in the PATH whenever possible. For @@ -135,7 +139,7 @@ config FEATURE_SH_STANDALONE config FEATURE_SH_NOFORK bool "Run 'nofork' applets directly" default n - depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH + depends on SHELL_ASH || SHELL_HUSH help This option causes busybox shells to not execute typical fork/exec/wait sequence, but call _main directly, @@ -153,14 +157,14 @@ config FEATURE_SH_NOFORK config FEATURE_SH_READ_FRAC bool "read -t N.NNN support (+110 bytes)" default y - depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH + depends on SHELL_ASH || SHELL_HUSH help Enable support for fractional second timeout in read builtin. config FEATURE_SH_HISTFILESIZE bool "Use $HISTFILESIZE" default y - depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH + depends on SHELL_ASH || SHELL_HUSH help This option makes busybox shells to use $HISTFILESIZE variable to set shell history size. Note that its max value is capped @@ -169,7 +173,7 @@ config FEATURE_SH_HISTFILESIZE config FEATURE_SH_EMBEDDED_SCRIPTS bool "Embed scripts in the binary" default y - depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH + depends on SHELL_ASH || SHELL_HUSH help Allow scripts to be compressed and embedded in the busybox binary. The scripts should be placed in the 'embed' directory diff --git a/shell/ash.c b/shell/ash.c index 2a4c839a7..ecb9b132b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -15,10 +15,15 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//config:config SHELL_ASH +//config: bool #hidden option +//config: depends on !NOMMU +//config: //config:config ASH //config: bool "ash (78 kb)" //config: default y //config: depends on !NOMMU +//config: select SHELL_ASH //config: help //config: The most complete and most pedantically correct shell included with //config: busybox. This shell is actually a derivative of the Debian 'dash' @@ -28,17 +33,17 @@ //config:# ash options //config:# note: Don't remove !NOMMU part in the next line; it would break //config:# menuconfig's indenting. -//config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH) +//config:if !NOMMU && (SHELL_ASH || ASH || SH_IS_ASH || BASH_IS_ASH) //config: //config:config ASH_OPTIMIZE_FOR_SIZE //config: bool "Optimize for size instead of speed" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_INTERNAL_GLOB //config: bool "Use internal glob() implementation" //config: default y # Y is bigger, but because of uclibc glob() bug, let Y be default for now -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: help //config: Do not use glob() function from libc, use internal implementation. //config: Use this if you are getting "glob.h: No such file or directory" @@ -49,7 +54,7 @@ //config:config ASH_BASH_COMPAT //config: bool "bash-compatible extensions" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_BASH_SOURCE_CURDIR //config: bool "'source' and '.' builtins search current directory after $PATH" @@ -70,17 +75,17 @@ //config:config ASH_JOB_CONTROL //config: bool "Job control" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_ALIAS //config: bool "Alias support" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_RANDOM_SUPPORT //config: bool "Pseudorandom generator and $RANDOM variable" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: help //config: Enable pseudorandom generator and dynamic variable "$RANDOM". //config: Each read of "$RANDOM" will generate a new pseudorandom value. @@ -91,7 +96,7 @@ //config:config ASH_EXPAND_PRMT //config: bool "Expand prompt string" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: help //config: $PS# may contain volatile content, such as backquote commands. //config: This option recreates the prompt string from the environment @@ -100,14 +105,14 @@ //config:config ASH_IDLE_TIMEOUT //config: bool "Idle timeout variable $TMOUT" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: help //config: Enable bash-like auto-logout after $TMOUT seconds of idle time. //config: //config:config ASH_MAIL //config: bool "Check for new mail in interactive shell" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: help //config: Enable "check for new mail" function: //config: if set, $MAIL file and $MAILPATH list of files @@ -117,32 +122,32 @@ //config:config ASH_ECHO //config: bool "echo builtin" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_PRINTF //config: bool "printf builtin" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_TEST //config: bool "test builtin" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_HELP //config: bool "help builtin" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_GETOPTS //config: bool "getopts builtin" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: //config:config ASH_CMDCMD //config: bool "command builtin" //config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: depends on SHELL_ASH //config: help //config: Enable support for the 'command' builtin, which allows //config: you to run the specified command or builtin, @@ -155,9 +160,7 @@ //applet:IF_SH_IS_ASH( APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) -//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o -//kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o -//kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o +//kbuild:lib-$(CONFIG_SHELL_ASH) += ash.o ash_ptr_hack.o shell_common.o //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o /* diff --git a/shell/hush.c b/shell/hush.c index 2cf2170ca..e9cec1cc9 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -95,6 +95,7 @@ //config:config HUSH //config: bool "hush (68 kb)" //config: default y +//config: select SHELL_HUSH //config: help //config: hush is a small shell. It handles the normal flow control //config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops, @@ -106,10 +107,20 @@ //config: It does not handle select, aliases, tilde expansion, //config: &>file and >&file redirection of stdout+stderr. //config: +// This option is visible (has a description) to make it possible to select +// a "scripted" applet (such as NOLOGIN) but avoid selecting any shells: +//config:config SHELL_HUSH +//config: bool "Internal shell for embedded script support" +//config: default n +//config: +//config:# hush options +//config:# It's only needed to get "nice" menuconfig indenting. +//config:if SHELL_HUSH || HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: //config:config HUSH_BASH_COMPAT //config: bool "bash-compatible extensions" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_BRACE_EXPANSION //config: bool "Brace expansion" @@ -133,7 +144,7 @@ //config:config HUSH_INTERACTIVE //config: bool "Interactive mode" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: help //config: Enable interactive mode (prompt and command editing). //config: Without this, hush simply reads and executes commands @@ -159,31 +170,31 @@ //config:config HUSH_TICK //config: bool "Support command substitution" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: help //config: Enable `command` and $(command). //config: //config:config HUSH_IF //config: bool "Support if/then/elif/else/fi" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_LOOPS //config: bool "Support for, while and until loops" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_CASE //config: bool "Support case ... esac statement" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: help //config: Enable case ... esac statement. +400 bytes. //config: //config:config HUSH_FUNCTIONS //config: bool "Support funcname() { commands; } syntax" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: help //config: Enable support for shell functions. +800 bytes. //config: @@ -197,7 +208,7 @@ //config:config HUSH_RANDOM_SUPPORT //config: bool "Pseudorandom generator and $RANDOM variable" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: help //config: Enable pseudorandom generator and dynamic variable "$RANDOM". //config: Each read of "$RANDOM" will generate a new pseudorandom value. @@ -205,7 +216,7 @@ //config:config HUSH_MODE_X //config: bool "Support 'hush -x' option and 'set -x' command" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: help //config: This instructs hush to print commands before execution. //config: Adds ~300 bytes. @@ -213,27 +224,27 @@ //config:config HUSH_ECHO //config: bool "echo builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_PRINTF //config: bool "printf builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_TEST //config: bool "test builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_HELP //config: bool "help builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_EXPORT //config: bool "export builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_EXPORT_N //config: bool "Support 'export -n' option" @@ -245,83 +256,83 @@ //config:config HUSH_READONLY //config: bool "readonly builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: help //config: Enable support for read-only variables. //config: //config:config HUSH_KILL //config: bool "kill builtin (supports kill %jobspec)" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_WAIT //config: bool "wait builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_COMMAND //config: bool "command builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_TRAP //config: bool "trap builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_TYPE //config: bool "type builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_TIMES //config: bool "times builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_READ //config: bool "read builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_SET //config: bool "set builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_UNSET //config: bool "unset builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_ULIMIT //config: bool "ulimit builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_UMASK //config: bool "umask builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_GETOPTS //config: bool "getopts builtin" //config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH //config: //config:config HUSH_MEMLEAK //config: bool "memleak builtin (debugging)" //config: default n -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: depends on SHELL_HUSH +//config: +//config:endif # hush options //applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP)) // APPLET_ODDNAME:name main location suid_type help //applet:IF_SH_IS_HUSH( APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) //applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) -//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o -//kbuild:lib-$(CONFIG_SH_IS_HUSH) += hush.o match.o shell_common.o -//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += hush.o match.o shell_common.o +//kbuild:lib-$(CONFIG_SHELL_HUSH) += hush.o match.o shell_common.o //kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o /* -i (interactive) is also accepted, diff --git a/util-linux/nologin.c b/util-linux/nologin.c index 5e5e42305..5a8b047a5 100644 --- a/util-linux/nologin.c +++ b/util-linux/nologin.c @@ -7,7 +7,7 @@ //config: //config:config NOLOGIN_DEPENDENCIES //config: bool "Enable dependencies for nologin" -//config: default y +//config: default n # Y default makes it harder to select single-applet test //config: depends on NOLOGIN //config: select CAT //config: select ECHO -- cgit v1.2.3-55-g6feb From 5663a17dabfcad885cc80f155ef84f7b843845cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Jun 2020 13:43:11 +0200 Subject: bc: placate a "defined but not used" warning Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/miscutils/bc.c b/miscutils/bc.c index c7246ea1a..4d987325e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2522,7 +2522,9 @@ static void xc_read_line(BcVec *vec, FILE *fp) #if ENABLE_FEATURE_BC_INTERACTIVE if (G_interrupt) { // ^C was pressed +# if ENABLE_FEATURE_EDITING intr: +# endif if (fp != stdin) { // ^C while running a script (bc SCRIPT): die. // We do not return to interactive prompt: -- cgit v1.2.3-55-g6feb From b02f8ca9098bedad00407fdaf3c3150fc81212ce Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Jun 2020 16:36:44 +0200 Subject: make_single_applets.sh: switch off nologin deps option Signed-off-by: Denys Vlasenko --- make_single_applets.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/make_single_applets.sh b/make_single_applets.sh index a37168cdf..7df53397e 100755 --- a/make_single_applets.sh +++ b/make_single_applets.sh @@ -29,6 +29,8 @@ for app in $apps; do done # remove "busybox" as well allno="`echo "$allno" | sed "s/^CONFIG_BUSYBOX=y\$/# CONFIG_BUSYBOX is not set/"`" +# disable any CONFIG_script_DEPENDENCIES as well +allno="`echo "$allno" | sed "s/^\(CONFIG_.*_DEPENDENCIES\)=y\$/# \1 is not set/"`" #echo "$allno" >.config_allno trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT -- cgit v1.2.3-55-g6feb From 24c212b9acba0a3bbd74298d5ba076910cea51b0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 25 Jun 2020 02:01:29 +0200 Subject: gzip -d with zcat enabled but gunzip disabled was misbehaving Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 87a802209..6244bce85 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -386,7 +386,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) * Normally, "zcat" is just "gunzip -c". * But if seamless magic is enabled, then we are much more clever. */ - if (ENABLE_ZCAT && (!ENABLE_GUNZIP || applet_name[1] == 'c')) + if (ENABLE_ZCAT && applet_name[1] == 'c') option_mask32 |= BBUNPK_OPT_STDOUT | BBUNPK_SEAMLESS_MAGIC; return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); -- cgit v1.2.3-55-g6feb From fb957125d8aa83c9df6e54292327983a51ee7ffd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 26 Jun 2020 21:22:50 +0200 Subject: Bump version to 1.32.0 Signed-off-by: Denys Vlasenko --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 15bb660d1..fbbae4b2a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 PATCHLEVEL = 32 SUBLEVEL = 0 -EXTRAVERSION = .git +EXTRAVERSION = NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From c918ea1673e4e930835d387bb989c620bf022e94 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 26 Jun 2020 21:30:50 +0200 Subject: Start 1.33.0 development cycle Signed-off-by: Denys Vlasenko --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fbbae4b2a..045fbad9a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 -PATCHLEVEL = 32 +PATCHLEVEL = 33 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = .git NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From a16c8ef21253d2fbb8f311ee34514cdc0a3f49a2 Mon Sep 17 00:00:00 2001 From: Norbert Lange Date: Fri, 14 Feb 2020 22:13:38 +0100 Subject: nc_bloaty: support udp broadcast ports Add a -b option, identical to debians "traditional" netcat. This allows sending (subnet) UDP Broadcasts. function old new delta packed_usage 33420 33441 +21 nc_main 1041 1057 +16 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 37/0) Total: 37 bytes Signed-off-by: Norbert Lange Signed-off-by: Denys Vlasenko --- networking/nc_bloaty.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 034e03d21..88eda6b28 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c @@ -84,6 +84,7 @@ //usage: ) //usage: "\n -n Don't do DNS resolution" //usage: "\n -u UDP mode" +//usage: "\n -b Allow broadcasts" //usage: "\n -v Verbose" //usage: IF_NC_EXTRA( //usage: "\n -o FILE Hex dump traffic" @@ -171,17 +172,19 @@ enum { OPT_p = (1 << 1), OPT_s = (1 << 2), OPT_u = (1 << 3), - OPT_v = (1 << 4), - OPT_w = (1 << 5), - OPT_l = (1 << 6) * ENABLE_NC_SERVER, - OPT_k = (1 << 7) * ENABLE_NC_SERVER, - OPT_i = (1 << (6+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, - OPT_o = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, - OPT_z = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, + OPT_b = (1 << 4), + OPT_v = (1 << 5), + OPT_w = (1 << 6), + OPT_l = (1 << 7) * ENABLE_NC_SERVER, + OPT_k = (1 << 8) * ENABLE_NC_SERVER, + OPT_i = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, + OPT_o = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, + OPT_z = (1 << (9+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA, }; #define o_nflag (option_mask32 & OPT_n) #define o_udpmode (option_mask32 & OPT_u) +#define o_bcmode (option_mask32 & OPT_b) #if ENABLE_NC_EXTRA #define o_ofile (option_mask32 & OPT_o) #define o_zero (option_mask32 & OPT_z) @@ -788,7 +791,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv) // -g -G -t -r deleted, unimplemented -a deleted too getopt32(argv, "^" - "np:s:uvw:+"/* -w N */ IF_NC_SERVER("lk") + "np:s:ubvw:+"/* -w N */ IF_NC_SERVER("lk") IF_NC_EXTRA("i:o:z") "\0" "?2:vv"IF_NC_SERVER(":ll"), /* max 2 params; -v and -l are counters */ @@ -851,8 +854,11 @@ int nc_main(int argc UNUSED_PARAM, char **argv) } xmove_fd(x, netfd); setsockopt_reuseaddr(netfd); - if (o_udpmode) + if (o_udpmode) { + if (o_bcmode) + setsockopt_broadcast(netfd); socket_want_pktinfo(netfd); + } if (!ENABLE_FEATURE_UNIX_LOCAL || cnt_l != 0 /* listen */ || ouraddr->u.sa.sa_family != AF_UNIX -- cgit v1.2.3-55-g6feb From 86a633ef9aeffc040a7b828034793d056c66a191 Mon Sep 17 00:00:00 2001 From: Norbert Lange Date: Fri, 14 Feb 2020 22:15:07 +0100 Subject: dpkg: prevent important directories from being removed busybox will remove directory symlinks, which is at odds with common layouts that have some of bin/lib/lib32/lib64 symlinked. this adds a exludelist for critcal and often symlinked directories. Fixes: Bug 12551 function old new delta remove_file_array 139 231 +92 Signed-off-by: Norbert Lange Signed-off-by: Denys Vlasenko --- archival/dpkg.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/archival/dpkg.c b/archival/dpkg.c index da77fba05..68a40bf6e 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -1204,6 +1204,27 @@ static char **create_list(const char *filename) return file_list; } +/** This tests if the filename is an "important" directory, which might be symlinked. + * Debians dpkg test if directories are used by other packages, this + * implementation doesn't and would remove for ex. an lib -> usr/lib symlink. + */ +static int is_builtin_exclude(const char *name) +{ + if (*name++ != '/') + return 0; + if (index_in_strings(".\0" "etc\0" "opt\0" "srv\0" "var\0" "var/lib\0", + name) >= 0) + return 1; + if (is_prefixed_with(name, "usr/")) { + name += sizeof("usr/") - 1; + if (is_prefixed_with(name, "local/")) + name += sizeof("local/") - 1; + } + + return index_in_strings("bin\0" "lib\0" "lib32\0" "lib64\0" "sbin\0", + name) >= 0; +} + /* maybe i should try and hook this into remove_file.c somehow */ static int remove_file_array(char **remove_names, char **exclude_names) { @@ -1215,6 +1236,8 @@ static int remove_file_array(char **remove_names, char **exclude_names) return 0; } for (i = 0; remove_names[i] != NULL; i++) { + if (is_builtin_exclude(remove_names[i])) + continue; if (exclude_names != NULL) { for (j = 0; exclude_names[j] != NULL; j++) { if (strcmp(remove_names[i], exclude_names[j]) == 0) { -- cgit v1.2.3-55-g6feb From 05faa6103bf85ecf362ad677ce761e2266311e3b Mon Sep 17 00:00:00 2001 From: Norbert Lange Date: Fri, 14 Feb 2020 22:16:10 +0100 Subject: dhcpd: remove hardcoded pidfile path Signed-off-by: Norbert Lange Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 9d6604943..6075689dc 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -46,6 +46,12 @@ #include "dhcpc.h" #include "dhcpd.h" +#if ENABLE_PID_FILE_PATH == 1 +#define PID_FILE_PATH CONFIG_PID_FILE_PATH +#else +#define PID_FILE_PATH "/var/run" +#endif + /* globals */ #define g_leases ((struct dyn_lease*)ptr_to_globals) /* struct server_data_t server_data is in bb_common_bufsiz1 */ @@ -406,7 +412,7 @@ static const struct config_keyword keywords[] = { {"offer_time" , read_u32 , OFS(offer_time ), "60"}, {"min_lease" , read_u32 , OFS(min_lease_sec), "60"}, {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE}, - {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"}, + {"pidfile" , read_str , OFS(pidfile ), PID_FILE_PATH "/udhcpd.pid"}, {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"}, /* keywords with no defaults must be last! */ {"option" , read_optset , OFS(options ), ""}, -- cgit v1.2.3-55-g6feb From 79bd7c3f7b37b3b7f85b982bdb4fb9058d6d3a8c Mon Sep 17 00:00:00 2001 From: Norbert Lange Date: Fri, 14 Feb 2020 22:16:11 +0100 Subject: acpid: only display -p if supported in usage Signed-off-by: Norbert Lange Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpd.c | 2 +- util-linux/acpid.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 6075689dc..acfdaa8c3 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -46,7 +46,7 @@ #include "dhcpc.h" #include "dhcpd.h" -#if ENABLE_PID_FILE_PATH == 1 +#if ENABLE_PID_FILE_PATH #define PID_FILE_PATH CONFIG_PID_FILE_PATH #else #define PID_FILE_PATH "/var/run" diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 95f8150e2..fc8215cce 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -42,7 +42,9 @@ //usage: "\n -c DIR Config directory [/etc/acpi]" //usage: "\n -e FILE /proc event file [/proc/acpi/event]" //usage: "\n -l FILE Log file [/var/log/acpid.log]" -//usage: "\n -p FILE Pid file [/var/run/acpid.pid]" +//usage: IF_FEATURE_PIDFILE( +//usage: "\n -p FILE Pid file [" CONFIG_PID_FILE_PATH "/acpid.pid]" +//usage: ) //usage: "\n -a FILE Action file [/etc/acpid.conf]" //usage: "\n -M FILE Map file [/etc/acpi.map]" //usage: IF_FEATURE_ACPID_COMPAT( -- cgit v1.2.3-55-g6feb From fc2ce04a38ebfb03f9aeff205979786839cd5a7c Mon Sep 17 00:00:00 2001 From: Scott Court Date: Mon, 29 Jun 2020 14:30:12 +0200 Subject: wget: fix openssl options for cert verification function old new delta is_ip_address - 54 +54 spawn_https_helper_openssl 461 486 +25 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/0 up/down: 79/0) Total: 79 bytes Signed-off-by: Scott Court Signed-off-by: Denys Vlasenko --- networking/wget.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 6a8c08324..ea60c18b2 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -673,7 +673,8 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) pid = xvfork(); if (pid == 0) { /* Child */ - char *argv[9]; + char *argv[13]; + char **argp; close(sp[0]); xmove_fd(sp[1], 0); @@ -696,13 +697,25 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) * TLS server_name (SNI) field are FQDNs (DNS hostnames). * IPv4 and IPv6 addresses, port numbers are not allowed. */ + argp = &argv[5]; if (!is_ip_address(servername)) { - argv[5] = (char*)"-servername"; - argv[6] = (char*)servername; + *argp++ = (char*)"-servername"; //[5] + *argp++ = (char*)servername; //[6] } if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { - argv[7] = (char*)"-verify_return_error"; + /* Abort on bad server certificate */ + *argp++ = (char*)"-verify"; //[7] + *argp++ = (char*)"100"; //[8] + *argp++ = (char*)"-verify_return_error"; //[9] + if (!is_ip_address(servername)) { + *argp++ = (char*)"-verify_hostname"; //[10] + *argp++ = (char*)servername; //[11] + } else { + *argp++ = (char*)"-verify_ip"; //[10] + *argp++ = (char*)host; //[11] + } } + //[12] (or earlier) is NULL terminator BB_EXECVP(argv[0], argv); xmove_fd(3, 2); -- cgit v1.2.3-55-g6feb From acdc8eed89399a9fa5e7478ee40b928c65e3ab4e Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Tue, 23 Jun 2020 15:25:08 -0500 Subject: udhcp: add option scanner Added an option scanner to udhcp to enable iteration over packet options. Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 96 ++++++++++++++++++++++++++--------------------- networking/udhcp/common.h | 8 ++++ 2 files changed, 62 insertions(+), 42 deletions(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 16bf69707..20d843bab 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -15,7 +15,7 @@ const uint8_t MAC_BCAST_ADDR[6] ALIGN2 = { }; #if ENABLE_UDHCPC || ENABLE_UDHCPD -/* Supported options are easily added here. +/* Supported options are easily added here, they need to be sorted. * See RFC2132 for more options. * OPTION_REQ: these options are requested by udhcpc (unless -o). */ @@ -222,79 +222,91 @@ unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings } } -/* Get an option with bounds checking (warning, result is not aligned) */ -uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) +/* Initialize state to be used between subsequent udhcp_scan_options calls */ +void FAST_FUNC init_scan_state(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) +{ + scan_state->overload = 0; + scan_state->rem = sizeof(packet->options); + scan_state->optionptr = packet->options; +} + +/* Iterate over packet's options, each call returning the next option. + * scan_state needs to be initialized with init_scan_state beforehand. + * Warning, result is not aligned. */ +uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) { - uint8_t *optionptr; int len; - int rem; - int overload = 0; enum { FILE_FIELD101 = FILE_FIELD * 0x101, SNAME_FIELD101 = SNAME_FIELD * 0x101, }; /* option bytes: [code][len][data1][data2]..[dataLEN] */ - optionptr = packet->options; - rem = sizeof(packet->options); while (1) { - if (rem <= 0) { + if (scan_state->rem <= 0) { complain: bb_simple_error_msg("bad packet, malformed option field"); return NULL; } /* DHCP_PADDING and DHCP_END have no [len] byte */ - if (optionptr[OPT_CODE] == DHCP_PADDING) { - rem--; - optionptr++; + if (scan_state->optionptr[OPT_CODE] == DHCP_PADDING) { + scan_state->rem--; + scan_state->optionptr++; continue; } - if (optionptr[OPT_CODE] == DHCP_END) { - if ((overload & FILE_FIELD101) == FILE_FIELD) { + if (scan_state->optionptr[OPT_CODE] == DHCP_END) { + if ((scan_state->overload & FILE_FIELD101) == FILE_FIELD) { /* can use packet->file, and didn't look at it yet */ - overload |= FILE_FIELD101; /* "we looked at it" */ - optionptr = packet->file; - rem = sizeof(packet->file); + scan_state->overload |= FILE_FIELD101; /* "we looked at it" */ + scan_state->optionptr = packet->file; + scan_state->rem = sizeof(packet->file); continue; } - if ((overload & SNAME_FIELD101) == SNAME_FIELD) { + if ((scan_state->overload & SNAME_FIELD101) == SNAME_FIELD) { /* can use packet->sname, and didn't look at it yet */ - overload |= SNAME_FIELD101; /* "we looked at it" */ - optionptr = packet->sname; - rem = sizeof(packet->sname); + scan_state->overload |= SNAME_FIELD101; /* "we looked at it" */ + scan_state->optionptr = packet->sname; + scan_state->rem = sizeof(packet->sname); continue; } break; } - if (rem <= OPT_LEN) + if (scan_state->rem <= OPT_LEN) goto complain; /* complain and return NULL */ - len = 2 + optionptr[OPT_LEN]; - rem -= len; - if (rem < 0) + len = 2 + scan_state->optionptr[OPT_LEN]; + scan_state->rem -= len; + /* So far no valid option with length 0 known. */ + if (scan_state->rem < 0 || scan_state->optionptr[OPT_LEN] == 0) goto complain; /* complain and return NULL */ - if (optionptr[OPT_CODE] == code) { - if (optionptr[OPT_LEN] == 0) { - /* So far no valid option with length 0 known. - * Having this check means that searching - * for DHCP_MESSAGE_TYPE need not worry - * that returned pointer might be unsafe - * to dereference. - */ - goto complain; /* complain and return NULL */ - } - log_option("option found", optionptr); - return optionptr + OPT_DATA; + if (scan_state->optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { + if (len >= 3) + scan_state->overload |= scan_state->optionptr[OPT_DATA]; + } else { + uint8_t *return_ptr = scan_state->optionptr; + scan_state->optionptr += len; + return return_ptr; } + scan_state->optionptr += len; + } - if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { - if (len >= 3) - overload |= optionptr[OPT_DATA]; - /* fall through */ + return NULL; +} + +/* Get an option with bounds checking (warning, result is not aligned) */ +uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) +{ + uint8_t *optptr; + struct dhcp_scan_state scan_state; + + init_scan_state(packet, &scan_state); + while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) { + if (optptr[OPT_CODE] == code) { + log_option("option found", optptr); + return optptr + OPT_DATA; } - optionptr += len; } /* log3 because udhcpc uses it a lot - very noisy */ diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 6214db06a..81c1dcbdc 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -107,6 +107,12 @@ enum { OPTION_LIST = 0x20, }; +struct dhcp_scan_state { + int overload; + int rem; + uint8_t *optionptr; +}; + /* DHCP option codes (partial list). See RFC 2132 and * http://www.iana.org/assignments/bootp-dhcp-parameters/ * Commented out options are handled by common option machinery, @@ -206,6 +212,8 @@ extern const uint8_t dhcp_option_lengths[] ALIGN1; unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); +void init_scan_state(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC; +uint8_t *udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC; uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; /* Same as above + ensures that option length is 4 bytes * (returns NULL if size is different) -- cgit v1.2.3-55-g6feb From 1f86ecb72974d0b284d73e7fea5acdab104af5f8 Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Tue, 23 Jun 2020 15:25:09 -0500 Subject: udhcpc: fix a TODO in fill_envp using option scanner fill_envp now iterates over the packet only once instead of a few hundred times using the new option scanner. function old new delta udhcp_scan_options - 189 +189 putenvp - 46 +46 init_scan_state - 22 +22 udhcp_get_option 227 104 -123 udhcp_run_script 835 601 -234 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 0/2 up/down: 257/-357) Total: -100 bytes Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpc.c | 198 ++++++++++++++++++++--------------------------- 1 file changed, 84 insertions(+), 114 deletions(-) diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 102178a4f..50dfead63 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -386,59 +386,78 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ return ret; } -/* put all the parameters into the environment */ -static char **fill_envp(struct dhcp_packet *packet) +static void putenvp(llist_t **envp, char *new_opt) +{ + putenv(new_opt); + log2(" %s", new_opt); + llist_add_to(envp, new_opt); +} + +static const char* get_optname(uint8_t code, const struct dhcp_optflag **dh) { - int envc; - int i; - char **envp, **curr; - const char *opt_name; - uint8_t *temp; - uint8_t overload = 0; - -#define BITMAP unsigned -#define BBITS (sizeof(BITMAP) * 8) -#define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1))) -#define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS]) - BITMAP found_opts[256 / BBITS]; - - memset(found_opts, 0, sizeof(found_opts)); - - /* We need 7 elements for: - * "interface=IFACE" - * "ip=N.N.N.N" from packet->yiaddr - * "giaddr=IP" from packet->gateway_nip (unless 0) - * "siaddr=IP" from packet->siaddr_nip (unless 0) - * "boot_file=FILE" from packet->file (unless overloaded) - * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded) - * terminating NULL + /* Find the option: + * dhcp_optflags is sorted so we stop searching when dh->code >= code, which is faster + * than iterating over the entire array. + * Options which don't have a match in dhcp_option_strings[], e.g DHCP_REQUESTED_IP, + * are located after the sorted array, so these entries will never be reached + * and they'll count as unknown options. */ - envc = 7; - /* +1 element for each option, +2 for subnet option: */ - if (packet) { - /* note: do not search for "pad" (0) and "end" (255) options */ -//TODO: change logic to scan packet _once_ - for (i = 1; i < 255; i++) { - temp = udhcp_get_option(packet, i); - if (temp) { - if (i == DHCP_OPTION_OVERLOAD) - overload |= *temp; - else if (i == DHCP_SUBNET) - envc++; /* for $mask */ - envc++; - /*if (i != DHCP_MESSAGE_TYPE)*/ - FOUND_OPTS(i) |= BMASK(i); - } - } - } - curr = envp = xzalloc(sizeof(envp[0]) * envc); + for (*dh = dhcp_optflags; (*dh)->code && (*dh)->code < code; (*dh)++) + continue; + + if ((*dh)->code == code) + return nth_string(dhcp_option_strings, (*dh - dhcp_optflags)); - *curr = xasprintf("interface=%s", client_data.interface); - putenv(*curr++); + return NULL; +} + +/* put all the parameters into the environment */ +static llist_t *fill_envp(struct dhcp_packet *packet) +{ + uint8_t *optptr; + struct dhcp_scan_state scan_state; + char *new_opt; + llist_t *envp = NULL; + + putenvp(&envp, xasprintf("interface=%s", client_data.interface)); if (!packet) return envp; + init_scan_state(packet, &scan_state); + + /* Iterate over the packet options. + * Handle each option based on whether it's an unknown / known option. + * There may be (although unlikely) duplicate options. For now, only the last + * appearing option will be stored in the environment, and all duplicates + * are freed properly. + * Long options may be implemented in the future (see RFC 3396) if needed. + */ + while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) { + const struct dhcp_optflag *dh; + const char *opt_name; + uint8_t code = optptr[OPT_CODE]; + uint8_t len = optptr[OPT_LEN]; + uint8_t *data = optptr + OPT_DATA; + + opt_name = get_optname(code, &dh); + if (opt_name) { + new_opt = xmalloc_optname_optval(data, dh, opt_name); + if (code == DHCP_SUBNET && len == 4) { + uint32_t subnet; + putenvp(&envp, new_opt); + move_from_unaligned32(subnet, data); + new_opt = xasprintf("mask=%u", mton(subnet)); + } + } else { + unsigned ofs; + new_opt = xmalloc(sizeof("optNNN=") + 1 + len*2); + ofs = sprintf(new_opt, "opt%u=", code); + bin2hex(new_opt + ofs, (char *)data, len)[0] = '\0'; + } + putenvp(&envp, new_opt); + } + /* Export BOOTP fields. Fields we don't (yet?) export: * uint8_t op; // always BOOTREPLY * uint8_t htype; // hardware address type. 1 = 10mb ethernet @@ -452,77 +471,31 @@ static char **fill_envp(struct dhcp_packet *packet) * uint8_t chaddr[16]; // link-layer client hardware address (MAC) */ /* Most important one: yiaddr as $ip */ - *curr = xmalloc(sizeof("ip=255.255.255.255")); - sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); - putenv(*curr++); + new_opt = xmalloc(sizeof("ip=255.255.255.255")); + sprint_nip(new_opt, "ip=", (uint8_t *) &packet->yiaddr); + putenvp(&envp, new_opt); + if (packet->siaddr_nip) { /* IP address of next server to use in bootstrap */ - *curr = xmalloc(sizeof("siaddr=255.255.255.255")); - sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); - putenv(*curr++); + new_opt = xmalloc(sizeof("siaddr=255.255.255.255")); + sprint_nip(new_opt, "siaddr=", (uint8_t *) &packet->siaddr_nip); + putenvp(&envp, new_opt); } if (packet->gateway_nip) { /* IP address of DHCP relay agent */ - *curr = xmalloc(sizeof("giaddr=255.255.255.255")); - sprint_nip(*curr, "giaddr=", (uint8_t *) &packet->gateway_nip); - putenv(*curr++); + new_opt = xmalloc(sizeof("giaddr=255.255.255.255")); + sprint_nip(new_opt, "giaddr=", (uint8_t *) &packet->gateway_nip); + putenvp(&envp, new_opt); } - if (!(overload & FILE_FIELD) && packet->file[0]) { + if (!(scan_state.overload & FILE_FIELD) && packet->file[0]) { /* watch out for invalid packets */ - *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); - putenv(*curr++); + new_opt = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); + putenvp(&envp, new_opt); } - if (!(overload & SNAME_FIELD) && packet->sname[0]) { + if (!(scan_state.overload & SNAME_FIELD) && packet->sname[0]) { /* watch out for invalid packets */ - *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); - putenv(*curr++); - } - - /* Export known DHCP options */ - opt_name = dhcp_option_strings; - i = 0; - while (*opt_name) { - uint8_t code = dhcp_optflags[i].code; - BITMAP *found_ptr = &FOUND_OPTS(code); - BITMAP found_mask = BMASK(code); - if (!(*found_ptr & found_mask)) - goto next; - *found_ptr &= ~found_mask; /* leave only unknown options */ - temp = udhcp_get_option(packet, code); - *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name); - putenv(*curr++); - if (code == DHCP_SUBNET && temp[-OPT_DATA + OPT_LEN] == 4) { - /* Subnet option: make things like "$ip/$mask" possible */ - uint32_t subnet; - move_from_unaligned32(subnet, temp); - *curr = xasprintf("mask=%u", mton(subnet)); - putenv(*curr++); - } - next: - opt_name += strlen(opt_name) + 1; - i++; - } - /* Export unknown options */ - for (i = 0; i < 256;) { - BITMAP bitmap = FOUND_OPTS(i); - if (!bitmap) { - i += BBITS; - continue; - } - if (bitmap & BMASK(i)) { - unsigned len, ofs; - - temp = udhcp_get_option(packet, i); - /* udhcp_get_option returns ptr to data portion, - * need to go back to get len - */ - len = temp[-OPT_DATA + OPT_LEN]; - *curr = xmalloc(sizeof("optNNN=") + 1 + len*2); - ofs = sprintf(*curr, "opt%u=", i); - *bin2hex(*curr + ofs, (void*) temp, len) = '\0'; - putenv(*curr++); - } - i++; + new_opt = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); + putenvp(&envp, new_opt); } return envp; @@ -531,7 +504,7 @@ static char **fill_envp(struct dhcp_packet *packet) /* Call a script with a par file and env vars */ static void udhcp_run_script(struct dhcp_packet *packet, const char *name) { - char **envp, **curr; + llist_t *envp; char *argv[3]; envp = fill_envp(packet); @@ -543,11 +516,8 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name) argv[2] = NULL; spawn_and_wait(argv); - for (curr = envp; *curr; curr++) { - log2(" %s", *curr); - bb_unsetenv_and_free(*curr); - } - free(envp); + /* Free all allocated environment variables */ + llist_free(envp, (void (*)(void *))bb_unsetenv_and_free); } -- cgit v1.2.3-55-g6feb From ac79db6a3b8c9d1815dc4f506d55bc6a2a4e34dd Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Thu, 11 Jun 2020 15:45:57 -0500 Subject: procps: code shrink function old new delta skip_whitespace_if_prefixed_with - 17 +17 procps_read_smaps 911 854 -57 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 17/-57) Total: -40 bytes Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- libbb/procps.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libbb/procps.c b/libbb/procps.c index af3ad86ff..4cc3cb2a1 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -177,6 +177,15 @@ static char *skip_fields(char *str, int count) } #endif +static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) +{ + char *tp = is_prefixed_with(buf, prefix); + if (tp) { + tp = skip_whitespace(tp); + } + return tp; +} + #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, void (*cb)(struct smaprec *, void *), void *data) @@ -207,8 +216,7 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, char *tp, *p; #define SCAN(S, X) \ - if ((tp = is_prefixed_with(buf, S)) != NULL) { \ - tp = skip_whitespace(tp); \ + if ((tp = skip_whitespace_if_prefixed_with(buf, S)) != NULL) { \ total->X += currec.X = fast_strtoul_10(&tp); \ continue; \ } -- cgit v1.2.3-55-g6feb From c9fc15359ef8fe5aa98ab0308c1563d9bcf99bb8 Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Thu, 11 Jun 2020 15:45:58 -0500 Subject: compare_string_array: code shrink Code shrink and prevention of possible out of bounds access. function old new delta nth_string 36 26 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-10) Total: -10 bytes text data bss dec hex filename 981342 16915 1872 1000129 f42c1 busybox_old 981332 16915 1872 1000119 f42b7 busybox_unstripped Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- libbb/compare_string_array.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c index 01a9df0e2..a06e57d3d 100644 --- a/libbb/compare_string_array.c +++ b/libbb/compare_string_array.c @@ -117,8 +117,11 @@ int FAST_FUNC index_in_substrings(const char *strings, const char *key) const char* FAST_FUNC nth_string(const char *strings, int n) { while (n) { - n--; - strings += strlen(strings) + 1; + if (*strings++ == '\0') { + if (*strings == '\0') /* reached end of strings */ + break; + n--; + } } return strings; } -- cgit v1.2.3-55-g6feb From d21a63f9fca8eb16f79de9b72d4a3484dfaec1fc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Jun 2020 08:33:02 +0200 Subject: libbb: code shrink in last_char_is() Signed-off-by: Denys Vlasenko --- libbb/last_char_is.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libbb/last_char_is.c b/libbb/last_char_is.c index 66f2e3635..918526e6c 100644 --- a/libbb/last_char_is.c +++ b/libbb/last_char_is.c @@ -8,16 +8,17 @@ */ #include "libbb.h" -/* Find out if the last character of a string matches the one given. - * Don't underrun the buffer if the string length is 0. - */ +/* Find out if the last character of a string matches the one given */ char* FAST_FUNC last_char_is(const char *s, int c) { - if (s && *s) { - size_t sz = strlen(s) - 1; - s += sz; - if ( (unsigned char)*s == c) - return (char*)s; + if (s) { + size_t sz = strlen(s); + /* Don't underrun the buffer if the string length is 0 */ + if (sz != 0) { + s += sz - 1; + if ((unsigned char)*s == c) + return (char*)s; + } } return NULL; } -- cgit v1.2.3-55-g6feb