From 5c105d9f3fd086aff195d3849dcf847d6b0bd927 Mon Sep 17 00:00:00 2001 From: blogic Date: Fri, 5 Oct 2012 10:12:53 +0000 Subject: branch Attitude Adjustment git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@33625 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../patches/001-init_avoid_loop_opening_tty.patch | 15 ++ ...se_md5_hash_by_default_like_it_used_to_be.patch | 20 ++ package/busybox/patches/003-brctl_show_fix.patch | 37 ++++ .../004-upstream-percent_decode_in_place.patch | 237 +++++++++++++++++++++ .../busybox/patches/005-resource_h_include.patch | 10 + .../patches/006-upstream_CVE-2011-2716_fixes.patch | 164 ++++++++++++++ package/busybox/patches/110-wget_getopt_fix.patch | 11 + package/busybox/patches/140-trylink_bash.patch | 8 + .../busybox/patches/141-gen_build_files_bash.patch | 8 + package/busybox/patches/150-no_static_libgcc.patch | 11 + package/busybox/patches/200-etc_crontabs.patch | 22 ++ package/busybox/patches/240-udhcpc_retries.patch | 20 ++ .../patches/241-udhcpc-oversized_packets.patch | 99 +++++++++ package/busybox/patches/242-udhcpc_msgs.patch | 18 ++ .../patches/243-udhcpc_changed_ifindex.patch | 15 ++ .../patches/244-udhcpc_add_6rd_option.patch | 143 +++++++++++++ package/busybox/patches/250-ash_export-n.patch | 34 +++ .../patches/251-ash_fix-redir-substitution.patch | 12 ++ package/busybox/patches/300-netmsg.patch | 103 +++++++++ package/busybox/patches/310-passwd_access.patch | 41 ++++ package/busybox/patches/340-lock_util.patch | 172 +++++++++++++++ package/busybox/patches/350-httpd_redir.patch | 90 ++++++++ .../busybox/patches/410-httpd_cgi_headers.patch | 16 ++ package/busybox/patches/440-httpd_chdir.patch | 10 + package/busybox/patches/470-insmod_search.patch | 137 ++++++++++++ package/busybox/patches/480-mount_union.patch | 29 +++ .../busybox/patches/490-mount_disable_check.patch | 12 ++ package/busybox/patches/510-awk_include.patch | 217 +++++++++++++++++++ package/busybox/patches/524-udhcpc_renew.patch | 10 + .../busybox/patches/610-ntpd_delayed_resolve.patch | 48 +++++ .../busybox/patches/700-hexdump_segfault_fix.patch | 11 + package/busybox/patches/802-brctl_linux24.patch | 74 +++++++ package/busybox/patches/803-id_getgrouplist.patch | 49 +++++ package/busybox/patches/902-telnetd_intr.patch | 10 + package/busybox/patches/910-insmod-q-flag.patch | 33 +++ package/busybox/patches/911-date-k-flag.patch | 83 ++++++++ package/busybox/patches/920-portability.patch | 13 ++ package/busybox/patches/950-partial-checksum.patch | 87 ++++++++ 38 files changed, 2129 insertions(+) create mode 100644 package/busybox/patches/001-init_avoid_loop_opening_tty.patch create mode 100644 package/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch create mode 100644 package/busybox/patches/003-brctl_show_fix.patch create mode 100644 package/busybox/patches/004-upstream-percent_decode_in_place.patch create mode 100644 package/busybox/patches/005-resource_h_include.patch create mode 100644 package/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch create mode 100644 package/busybox/patches/110-wget_getopt_fix.patch create mode 100644 package/busybox/patches/140-trylink_bash.patch create mode 100644 package/busybox/patches/141-gen_build_files_bash.patch create mode 100644 package/busybox/patches/150-no_static_libgcc.patch create mode 100644 package/busybox/patches/200-etc_crontabs.patch create mode 100644 package/busybox/patches/240-udhcpc_retries.patch create mode 100644 package/busybox/patches/241-udhcpc-oversized_packets.patch create mode 100644 package/busybox/patches/242-udhcpc_msgs.patch create mode 100644 package/busybox/patches/243-udhcpc_changed_ifindex.patch create mode 100644 package/busybox/patches/244-udhcpc_add_6rd_option.patch create mode 100644 package/busybox/patches/250-ash_export-n.patch create mode 100644 package/busybox/patches/251-ash_fix-redir-substitution.patch create mode 100644 package/busybox/patches/300-netmsg.patch create mode 100644 package/busybox/patches/310-passwd_access.patch create mode 100644 package/busybox/patches/340-lock_util.patch create mode 100644 package/busybox/patches/350-httpd_redir.patch create mode 100644 package/busybox/patches/410-httpd_cgi_headers.patch create mode 100644 package/busybox/patches/440-httpd_chdir.patch create mode 100644 package/busybox/patches/470-insmod_search.patch create mode 100644 package/busybox/patches/480-mount_union.patch create mode 100644 package/busybox/patches/490-mount_disable_check.patch create mode 100644 package/busybox/patches/510-awk_include.patch create mode 100644 package/busybox/patches/524-udhcpc_renew.patch create mode 100644 package/busybox/patches/610-ntpd_delayed_resolve.patch create mode 100644 package/busybox/patches/700-hexdump_segfault_fix.patch create mode 100644 package/busybox/patches/802-brctl_linux24.patch create mode 100644 package/busybox/patches/803-id_getgrouplist.patch create mode 100644 package/busybox/patches/902-telnetd_intr.patch create mode 100644 package/busybox/patches/910-insmod-q-flag.patch create mode 100644 package/busybox/patches/911-date-k-flag.patch create mode 100644 package/busybox/patches/920-portability.patch create mode 100644 package/busybox/patches/950-partial-checksum.patch (limited to 'package/busybox/patches') diff --git a/package/busybox/patches/001-init_avoid_loop_opening_tty.patch b/package/busybox/patches/001-init_avoid_loop_opening_tty.patch new file mode 100644 index 000000000..4db64c34b --- /dev/null +++ b/package/busybox/patches/001-init_avoid_loop_opening_tty.patch @@ -0,0 +1,15 @@ +--- a/init/init.c ++++ b/init/init.c +@@ -573,8 +573,11 @@ static void run_actions(int action_type) + /* Only run stuff with pid == 0. If pid != 0, + * it is already running + */ +- if (a->pid == 0) ++ if (a->pid == 0) { ++ if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) ++ continue; + a->pid = run(a); ++ } + } + } + } diff --git a/package/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch b/package/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch new file mode 100644 index 000000000..ff79f3ee9 --- /dev/null +++ b/package/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch @@ -0,0 +1,20 @@ +From eb80c2a5315ed08bd329448217695375d89732c9 Mon Sep 17 00:00:00 2001 +From: Nicolas Thill +Date: Wed, 9 Nov 2011 18:17:20 +0100 +Subject: [PATCH] passwd: use MD5 hash by default (like it used to be) + +--- + loginutils/passwd.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +--- a/loginutils/passwd.c ++++ b/loginutils/passwd.c +@@ -94,7 +94,7 @@ int passwd_main(int argc UNUSED_PARAM, c + }; + unsigned opt; + int rc; +- const char *opt_a = "d"; /* des */ ++ const char *opt_a = "m"; /* md5 */ + const char *filename; + char *myname; + char *name; diff --git a/package/busybox/patches/003-brctl_show_fix.patch b/package/busybox/patches/003-brctl_show_fix.patch new file mode 100644 index 000000000..8177fb01c --- /dev/null +++ b/package/busybox/patches/003-brctl_show_fix.patch @@ -0,0 +1,37 @@ +--- a/networking/brctl.c ++++ b/networking/brctl.c +@@ -129,7 +129,7 @@ int brctl_main(int argc UNUSED_PARAM, ch + "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" + "setpathcost\0" "setportprio\0" "setbridgeprio\0" + ) +- IF_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); ++ IF_FEATURE_BRCTL_SHOW("show\0"); + + enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif + IF_FEATURE_BRCTL_FANCY(, +@@ -137,7 +137,7 @@ int brctl_main(int argc UNUSED_PARAM, ch + ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, + ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio + ) +- IF_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) ++ IF_FEATURE_BRCTL_SHOW(, ARG_show) + }; + + int fd; +--- a/networking/Config.src ++++ b/networking/Config.src +@@ -82,12 +82,12 @@ config FEATURE_BRCTL_FANCY + This adds about 600 bytes. + + config FEATURE_BRCTL_SHOW +- bool "Support show, showmac and showstp" ++ bool "Support show" + default y + depends on BRCTL && FEATURE_BRCTL_FANCY + help + Add support for option which prints the current config: +- showmacs, showstp, show ++ show + + config DNSD + bool "dnsd" diff --git a/package/busybox/patches/004-upstream-percent_decode_in_place.patch b/package/busybox/patches/004-upstream-percent_decode_in_place.patch new file mode 100644 index 000000000..d94ee4790 --- /dev/null +++ b/package/busybox/patches/004-upstream-percent_decode_in_place.patch @@ -0,0 +1,237 @@ +http://git.busybox.net/busybox/commit/?id=dd1061b6a79b0161597799e825bfefc27993ace5 + +From dd1061b6a79b0161597799e825bfefc27993ace5 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Sun, 11 Sep 2011 21:04:02 +0200 +Subject: [PATCH] wget: URL-decode user:password before base64-encoding it into auth hdr. Closes 3625. + +function old new delta +percent_decode_in_place - 152 +152 +parse_url 304 317 +13 +handle_incoming_and_exit 2795 2798 +3 +httpd_main 763 760 -3 +decodeString 152 - -152 +------------------------------------------------------------------------------ +(add/remove: 2/1 grow/shrink: 2/1 up/down: 168/-155) Total: 13 bytes + +Signed-off-by: Denys Vlasenko + +--- a/include/libbb.h ++++ b/include/libbb.h +@@ -1570,6 +1570,15 @@ int starts_with_cpu(const char *str) FAS + unsigned get_cpu_count(void) FAST_FUNC; + + ++/* Use strict=1 if you process input from untrusted source: ++ * it will return NULL on invalid %xx (bad hex chars) ++ * and str + 1 if decoded char is / or NUL. ++ * In non-strict mode, it always succeeds (returns str), ++ * and also it additionally decoded '+' to space. ++ */ ++char *percent_decode_in_place(char *str, int strict) FAST_FUNC; ++ ++ + extern const char bb_uuenc_tbl_base64[]; + extern const char bb_uuenc_tbl_std[]; + void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; +--- /dev/null ++++ b/libbb/percent_decode.c +@@ -0,0 +1,69 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Licensed under GPLv2 or later, see file LICENSE in this source tree. ++ */ ++ ++//kbuild:lib-y += percent_decode.o ++ ++#include "libbb.h" ++ ++static unsigned hex_to_bin(unsigned char c) ++{ ++ unsigned v; ++ ++ v = c - '0'; ++ if (v <= 9) ++ return v; ++ /* c | 0x20: letters to lower case, non-letters ++ * to (potentially different) non-letters */ ++ v = (unsigned)(c | 0x20) - 'a'; ++ if (v <= 5) ++ return v + 10; ++ return ~0; ++/* For testing: ++void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); } ++int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f'); ++t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; } ++*/ ++} ++ ++char* FAST_FUNC percent_decode_in_place(char *str, int strict) ++{ ++ /* note that decoded string is always shorter than original */ ++ char *src = str; ++ char *dst = str; ++ char c; ++ ++ while ((c = *src++) != '\0') { ++ unsigned v; ++ ++ if (!strict && c == '+') { ++ *dst++ = ' '; ++ continue; ++ } ++ if (c != '%') { ++ *dst++ = c; ++ continue; ++ } ++ v = hex_to_bin(src[0]); ++ if (v > 15) { ++ bad_hex: ++ if (strict) ++ return NULL; ++ *dst++ = '%'; ++ continue; ++ } ++ v = (v * 16) | hex_to_bin(src[1]); ++ if (v > 255) ++ goto bad_hex; ++ if (strict && (v == '/' || v == '\0')) { ++ /* caller takes it as indication of invalid ++ * (dangerous wrt exploits) chars */ ++ return str + 1; ++ } ++ *dst++ = v; ++ src += 2; ++ } ++ *dst = '\0'; ++ return str; ++} +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -820,78 +820,6 @@ static char *encodeString(const char *st + } + #endif + +-/* +- * Given a URL encoded string, convert it to plain ascii. +- * Since decoding always makes strings smaller, the decode is done in-place. +- * Thus, callers should xstrdup() the argument if they do not want the +- * argument modified. The return is the original pointer, allowing this +- * function to be easily used as arguments to other functions. +- * +- * string The first string to decode. +- * option_d 1 if called for httpd -d +- * +- * Returns a pointer to the decoded string (same as input). +- */ +-static unsigned hex_to_bin(unsigned char c) +-{ +- unsigned v; +- +- v = c - '0'; +- if (v <= 9) +- return v; +- /* c | 0x20: letters to lower case, non-letters +- * to (potentially different) non-letters */ +- v = (unsigned)(c | 0x20) - 'a'; +- if (v <= 5) +- return v + 10; +- return ~0; +-/* For testing: +-void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); } +-int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f'); +-t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; } +-*/ +-} +-static char *decodeString(char *orig, int option_d) +-{ +- /* note that decoded string is always shorter than original */ +- char *string = orig; +- char *ptr = string; +- char c; +- +- while ((c = *ptr++) != '\0') { +- unsigned v; +- +- if (option_d && c == '+') { +- *string++ = ' '; +- continue; +- } +- if (c != '%') { +- *string++ = c; +- continue; +- } +- v = hex_to_bin(ptr[0]); +- if (v > 15) { +- bad_hex: +- if (!option_d) +- return NULL; +- *string++ = '%'; +- continue; +- } +- v = (v * 16) | hex_to_bin(ptr[1]); +- if (v > 255) +- goto bad_hex; +- if (!option_d && (v == '/' || v == '\0')) { +- /* caller takes it as indication of invalid +- * (dangerous wrt exploits) chars */ +- return orig + 1; +- } +- *string++ = v; +- ptr += 2; +- } +- *string = '\0'; +- return orig; +-} +- + #if ENABLE_FEATURE_HTTPD_BASIC_AUTH + /* + * Decode a base64 data stream as per rfc1521. +@@ -1949,7 +1877,7 @@ static void handle_incoming_and_exit(con + } + + /* Decode URL escape sequences */ +- tptr = decodeString(urlcopy, 0); ++ tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1); + if (tptr == NULL) + send_headers_and_exit(HTTP_BAD_REQUEST); + if (tptr == urlcopy + 1) { +@@ -2408,7 +2336,7 @@ int httpd_main(int argc UNUSED_PARAM, ch + , &verbose + ); + if (opt & OPT_DECODE_URL) { +- fputs(decodeString(url_for_decode, 1), stdout); ++ fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout); + return 0; + } + #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR +--- a/networking/wget.c ++++ b/networking/wget.c +@@ -298,8 +298,13 @@ static void parse_url(const char *src_ur + + sp = strrchr(h->host, '@'); + if (sp != NULL) { +- h->user = h->host; ++ // URL-decode "user:password" string before base64-encoding: ++ // wget http://test:my%20pass@example.com should send ++ // Authorization: Basic dGVzdDpteSBwYXNz ++ // which decodes to "test:my pass". ++ // Standard wget and curl do this too. + *sp = '\0'; ++ h->user = percent_decode_in_place(h->host, /*strict:*/ 0); + h->host = sp + 1; + } + +@@ -661,12 +666,6 @@ static void download_one_url(const char + + #if ENABLE_FEATURE_WGET_AUTHENTICATION + if (target.user) { +-//TODO: URL-decode "user:password" string before base64-encoding: +-//wget http://test:my%20pass@example.com should send +-// Authorization: Basic dGVzdDpteSBwYXNz +-//which decodes to "test:my pass", instead of what we send now: +-// Authorization: Basic dGVzdDpteSUyMHBhc3M= +-//Can reuse decodeString() from httpd.c + fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, + base64enc(target.user)); + } diff --git a/package/busybox/patches/005-resource_h_include.patch b/package/busybox/patches/005-resource_h_include.patch new file mode 100644 index 000000000..d66d66d67 --- /dev/null +++ b/package/busybox/patches/005-resource_h_include.patch @@ -0,0 +1,10 @@ +--- a/include/libbb.h ++++ b/include/libbb.h +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/package/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch b/package/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch new file mode 100644 index 000000000..94d5f34a1 --- /dev/null +++ b/package/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch @@ -0,0 +1,164 @@ +--- busybox-1.19.4/networking/udhcp/common.c ++++ busybox-1.19.4-udhcp/networking/udhcp/common.c +@@ -29,16 +29,16 @@ const struct dhcp_optflag dhcp_optflags[ + // { OPTION_IP | OPTION_LIST , 0x07 }, /* DHCP_LOG_SERVER */ + // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */ + { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */ +- { OPTION_STRING | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ ++ { OPTION_STRING_HOST | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ + { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */ +- { OPTION_STRING | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ ++ { OPTION_STRING_HOST | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ + { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */ + { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ + { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ + { OPTION_U16 , 0x1a }, /* DHCP_MTU */ + { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ + { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */ +- { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ ++ { OPTION_STRING_HOST , 0x28 }, /* DHCP_NIS_DOMAIN */ + { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ + { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ + { OPTION_IP | OPTION_LIST , 0x2c }, /* DHCP_WINS_SERVER */ +@@ -46,7 +46,7 @@ const struct dhcp_optflag dhcp_optflags[ + { OPTION_IP , 0x36 }, /* DHCP_SERVER_ID */ + { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */ + //TODO: must be combined with 'sname' and 'file' handling: +- { OPTION_STRING , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ ++ { OPTION_STRING_HOST , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ + { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */ + //TODO: not a string, but a set of LASCII strings: + // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ +@@ -143,6 +143,7 @@ const uint8_t dhcp_option_lengths[] ALIG + [OPTION_IP_PAIR] = 8, + // [OPTION_BOOLEAN] = 1, + [OPTION_STRING] = 1, /* ignored by udhcp_str2optset */ ++ [OPTION_STRING_HOST] = 1, /* ignored by udhcp_str2optset */ + #if ENABLE_FEATURE_UDHCP_RFC3397 + [OPTION_DNS_STRING] = 1, /* ignored by both udhcp_str2optset and xmalloc_optname_optval */ + [OPTION_SIP_SERVERS] = 1, +@@ -411,7 +412,9 @@ static NOINLINE void attach_option( + /* actually 255 is ok too, but adding a space can overlow it */ + + existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); +- if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING) { ++ if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING ++ || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST ++ ) { + /* add space separator between STRING options in a list */ + existing->data[OPT_DATA + old_len] = ' '; + old_len++; +@@ -475,6 +478,7 @@ int FAST_FUNC udhcp_str2optset(const cha + retval = udhcp_str2nip(val, buffer + 4); + break; + case OPTION_STRING: ++ case OPTION_STRING_HOST: + #if ENABLE_FEATURE_UDHCP_RFC3397 + case OPTION_DNS_STRING: + #endif +--- busybox-1.19.4/networking/udhcp/common.h ++++ busybox-1.19.4-udhcp/networking/udhcp/common.h +@@ -80,6 +80,9 @@ enum { + OPTION_IP = 1, + OPTION_IP_PAIR, + OPTION_STRING, ++ /* Opts of STRING_HOST type will be sanitized before they are passed ++ * to udhcpc script's environment: */ ++ OPTION_STRING_HOST, + // OPTION_BOOLEAN, + OPTION_U8, + OPTION_U16, +--- busybox-1.19.4/networking/udhcp/dhcpc.c ++++ busybox-1.19.4-udhcp/networking/udhcp/dhcpc.c +@@ -101,6 +101,7 @@ static const uint8_t len_of_option_as_st + [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, + [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), + [OPTION_STRING ] = 1, ++ [OPTION_STRING_HOST ] = 1, + #if ENABLE_FEATURE_UDHCP_RFC3397 + [OPTION_DNS_STRING ] = 1, /* unused */ + /* Hmmm, this severely overestimates size if SIP_SERVERS option +@@ -135,6 +136,63 @@ static int mton(uint32_t mask) + return i; + } + ++/* Check if a given label represents a valid DNS label ++ * Return pointer to the first character after the label upon success, ++ * NULL otherwise. ++ * 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" ++ * 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; ++ ++ for (;;) { ++ ch = *label; ++ if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { ++ if (pos == 0) { ++ /* label must begin with letter */ ++ return NULL; ++ } ++ 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++; ++ } ++} ++ + /* Create "opt_name=opt_value" string */ + static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name) + { +@@ -185,8 +243,11 @@ static NOINLINE char *xmalloc_optname_op + break; + } + case OPTION_STRING: ++ case OPTION_STRING_HOST: + memcpy(dest, option, len); + dest[len] = '\0'; ++ if (type == OPTION_STRING_HOST && !good_hostname(dest)) ++ safe_strncpy(dest, "bad", len); + return ret; /* Short circuit this case */ + case OPTION_STATIC_ROUTES: { + /* Option binary format: +@@ -314,6 +375,7 @@ static char **fill_envp(struct dhcp_pack + /* +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) { diff --git a/package/busybox/patches/110-wget_getopt_fix.patch b/package/busybox/patches/110-wget_getopt_fix.patch new file mode 100644 index 000000000..100323146 --- /dev/null +++ b/package/busybox/patches/110-wget_getopt_fix.patch @@ -0,0 +1,11 @@ +--- a/networking/wget.c ++++ b/networking/wget.c +@@ -873,7 +873,7 @@ int wget_main(int argc UNUSED_PARAM, cha + /* Ignored: */ + // "tries\0" Required_argument "t" + /* Ignored (we always use PASV): */ +- "passive-ftp\0" No_argument "\xff" ++ "passive-ftp\0" No_argument "\xfd" + "header\0" Required_argument "\xfe" + "post-data\0" Required_argument "\xfd" + /* Ignored (we don't do ssl) */ diff --git a/package/busybox/patches/140-trylink_bash.patch b/package/busybox/patches/140-trylink_bash.patch new file mode 100644 index 000000000..f9571fcbc --- /dev/null +++ b/package/busybox/patches/140-trylink_bash.patch @@ -0,0 +1,8 @@ +--- a/scripts/trylink ++++ b/scripts/trylink +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/usr/bin/env bash + + debug=false + diff --git a/package/busybox/patches/141-gen_build_files_bash.patch b/package/busybox/patches/141-gen_build_files_bash.patch new file mode 100644 index 000000000..d258fb8bc --- /dev/null +++ b/package/busybox/patches/141-gen_build_files_bash.patch @@ -0,0 +1,8 @@ +--- a/scripts/gen_build_files.sh ++++ b/scripts/gen_build_files.sh +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/usr/bin/env bash + + # Note: was using sed OPTS CMD -- FILES + # but users complain that many sed implementations diff --git a/package/busybox/patches/150-no_static_libgcc.patch b/package/busybox/patches/150-no_static_libgcc.patch new file mode 100644 index 000000000..fde6fbb86 --- /dev/null +++ b/package/busybox/patches/150-no_static_libgcc.patch @@ -0,0 +1,11 @@ +--- a/Makefile.flags ++++ b/Makefile.flags +@@ -50,7 +50,7 @@ CFLAGS += $(call cc-option,-fno-builtin- + # -fno-guess-branch-probability: prohibit pseudo-random guessing + # of branch probabilities (hopefully makes bloatcheck more stable): + CFLAGS += $(call cc-option,-fno-guess-branch-probability,) +-CFLAGS += $(call cc-option,-funsigned-char -static-libgcc,) ++CFLAGS += $(call cc-option,-funsigned-char,) + CFLAGS += $(call cc-option,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,) + + # FIXME: These warnings are at least partially to be concerned about and should diff --git a/package/busybox/patches/200-etc_crontabs.patch b/package/busybox/patches/200-etc_crontabs.patch new file mode 100644 index 000000000..ebf299050 --- /dev/null +++ b/package/busybox/patches/200-etc_crontabs.patch @@ -0,0 +1,22 @@ +--- a/miscutils/crond.c ++++ b/miscutils/crond.c +@@ -37,7 +37,7 @@ + + + #define TMPDIR CONFIG_FEATURE_CROND_DIR +-#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" ++#define CRONTABS "/etc/crontabs" + #ifndef SENDMAIL + # define SENDMAIL "sendmail" + #endif +--- a/miscutils/crontab.c ++++ b/miscutils/crontab.c +@@ -22,7 +22,7 @@ + + #include "libbb.h" + +-#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" ++#define CRONTABS "/etc/crontabs" + #ifndef CRONUPDATE + #define CRONUPDATE "cron.update" + #endif diff --git a/package/busybox/patches/240-udhcpc_retries.patch b/package/busybox/patches/240-udhcpc_retries.patch new file mode 100644 index 000000000..a9f4f3d1e --- /dev/null +++ b/package/busybox/patches/240-udhcpc_retries.patch @@ -0,0 +1,20 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1257,7 +1257,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c + + switch (state) { + case INIT_SELECTING: +- if (packet_num < discover_retries) { ++ if (!discover_retries || packet_num < discover_retries) { + if (packet_num == 0) + xid = random_xid(); + /* broadcast */ +@@ -1286,7 +1286,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c + packet_num = 0; + continue; + case REQUESTING: +- if (packet_num < discover_retries) { ++ if (!discover_retries || packet_num < discover_retries) { + /* send broadcast select packet */ + send_select(xid, server_addr, requested_ip); + timeout = discover_timeout; diff --git a/package/busybox/patches/241-udhcpc-oversized_packets.patch b/package/busybox/patches/241-udhcpc-oversized_packets.patch new file mode 100644 index 000000000..471d704a7 --- /dev/null +++ b/package/busybox/patches/241-udhcpc-oversized_packets.patch @@ -0,0 +1,99 @@ +--- a/networking/udhcp/packet.c ++++ b/networking/udhcp/packet.c +@@ -158,6 +158,11 @@ uint16_t FAST_FUNC udhcp_checksum(void * + return ~sum; + } + ++int udhcp_get_payload_len(struct dhcp_packet *dhcp_pkt) ++{ ++ return sizeof(struct dhcp_packet) - DHCP_OPTIONS_BUFSIZE + udhcp_end_option(dhcp_pkt->options) + sizeof(dhcp_pkt->options[0]); ++} ++ + /* Construct a ip/udp header for a packet, send packet */ + int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, + uint32_t source_nip, int source_port, +@@ -166,10 +171,10 @@ int FAST_FUNC udhcp_send_raw_packet(stru + { + struct sockaddr_ll dest_sll; + struct ip_udp_dhcp_packet packet; +- unsigned padding; + int fd; + int result = -1; + const char *msg; ++ int p_len = udhcp_get_payload_len(dhcp_pkt); + + fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); + if (fd < 0) { +@@ -178,8 +183,8 @@ int FAST_FUNC udhcp_send_raw_packet(stru + } + + memset(&dest_sll, 0, sizeof(dest_sll)); +- memset(&packet, 0, offsetof(struct ip_udp_dhcp_packet, data)); +- packet.data = *dhcp_pkt; /* struct copy */ ++ memset(&packet, 0, sizeof(packet)); ++ memcpy(&(packet.data), dhcp_pkt, p_len); + + dest_sll.sll_family = AF_PACKET; + dest_sll.sll_protocol = htons(ETH_P_IP); +@@ -192,36 +197,24 @@ int FAST_FUNC udhcp_send_raw_packet(stru + goto ret_close; + } + +- /* We were sending full-sized DHCP packets (zero padded), +- * but some badly configured servers were seen dropping them. +- * Apparently they drop all DHCP packets >576 *ethernet* octets big, +- * whereas they may only drop packets >576 *IP* octets big +- * (which for typical Ethernet II means 590 octets: 6+6+2 + 576). +- * +- * In order to work with those buggy servers, +- * we truncate packets after end option byte. +- */ +- padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(packet.data.options); +- + packet.ip.protocol = IPPROTO_UDP; + packet.ip.saddr = source_nip; + packet.ip.daddr = dest_nip; + packet.udp.source = htons(source_port); + packet.udp.dest = htons(dest_port); +- /* size, excluding IP header: */ +- packet.udp.len = htons(UDP_DHCP_SIZE - padding); +- /* for UDP checksumming, ip.len is set to UDP packet len */ ++ p_len += sizeof(packet.udp); ++ packet.udp.len = htons(p_len); + packet.ip.tot_len = packet.udp.len; +- packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding); +- /* but for sending, it is set to IP packet len */ +- packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); ++ p_len += sizeof(packet.ip); ++ packet.udp.check = udhcp_checksum(&packet, p_len); ++ packet.ip.tot_len = htons(p_len); + packet.ip.ihl = sizeof(packet.ip) >> 2; + packet.ip.version = IPVERSION; + packet.ip.ttl = IPDEFTTL; + packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip)); + + udhcp_dump_packet(dhcp_pkt); +- result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0, ++ result = sendto(fd, &packet, p_len, /*flags:*/ 0, + (struct sockaddr *) &dest_sll, sizeof(dest_sll)); + msg = "sendto"; + ret_close: +@@ -239,7 +232,6 @@ int FAST_FUNC udhcp_send_kernel_packet(s + uint32_t dest_nip, int dest_port) + { + struct sockaddr_in client; +- unsigned padding; + int fd; + int result = -1; + const char *msg; +@@ -270,9 +262,7 @@ int FAST_FUNC udhcp_send_kernel_packet(s + } + + udhcp_dump_packet(dhcp_pkt); +- +- padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options); +- result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding); ++ result = safe_write(fd, dhcp_pkt, udhcp_get_payload_len(dhcp_pkt)); + msg = "write"; + ret_close: + close(fd); diff --git a/package/busybox/patches/242-udhcpc_msgs.patch b/package/busybox/patches/242-udhcpc_msgs.patch new file mode 100644 index 000000000..998e3b664 --- /dev/null +++ b/package/busybox/patches/242-udhcpc_msgs.patch @@ -0,0 +1,18 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -540,6 +540,7 @@ static int raw_bcast_from_client_config_ + static NOINLINE int send_discover(uint32_t xid, uint32_t requested) + { + struct dhcp_packet packet; ++ static int msgs = 0; + + /* Fill in: op, htype, hlen, cookie, chaddr fields, + * random xid field (we override it below), +@@ -557,6 +558,7 @@ static NOINLINE int send_discover(uint32 + */ + add_client_options(&packet); + ++ if (msgs++ < 3) + bb_info_msg("Sending discover..."); + return raw_bcast_from_client_config_ifindex(&packet); + } diff --git a/package/busybox/patches/243-udhcpc_changed_ifindex.patch b/package/busybox/patches/243-udhcpc_changed_ifindex.patch new file mode 100644 index 000000000..4b28166bc --- /dev/null +++ b/package/busybox/patches/243-udhcpc_changed_ifindex.patch @@ -0,0 +1,15 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1205,6 +1205,12 @@ int udhcpc_main(int argc UNUSED_PARAM, c + /* silence "uninitialized!" warning */ + unsigned timestamp_before_wait = timestamp_before_wait; + ++ /* When running on a bridge, the ifindex may have changed (e.g. if ++ * member interfaces were added/removed or if the status of the ++ * bridge changed). ++ * Workaround: refresh it here before processing the next packet */ ++ udhcp_read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.client_mac); ++ + //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode); + + /* Was opening raw or udp socket here diff --git a/package/busybox/patches/244-udhcpc_add_6rd_option.patch b/package/busybox/patches/244-udhcpc_add_6rd_option.patch new file mode 100644 index 000000000..9e30ef79a --- /dev/null +++ b/package/busybox/patches/244-udhcpc_add_6rd_option.patch @@ -0,0 +1,143 @@ +--- a/networking/udhcp/common.c ++++ b/networking/udhcp/common.c +@@ -60,6 +60,8 @@ const struct dhcp_optflag dhcp_optflags[ + { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ + #endif + { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ ++ { OPTION_6RD , 0xd4 }, /* DHCP_6RD (RFC) */ ++ { OPTION_6RD , 0x96 }, /* DHCP_6RD (Comcast) */ + { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ + + /* Options below have no match in dhcp_option_strings[], +@@ -127,6 +129,8 @@ const char dhcp_option_strings[] ALIGN1 + "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ + #endif + "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ ++ "ip6rd" "\0" /* DHCP_6RD (RFC) */ ++ "ip6rd" "\0" /* DHCP_6RD (Comcast) */ + "wpad" "\0" /* DHCP_WPAD */ + ; + +@@ -154,6 +158,7 @@ const uint8_t dhcp_option_lengths[] ALIG + [OPTION_S32] = 4, + /* Just like OPTION_STRING, we use minimum length here */ + [OPTION_STATIC_ROUTES] = 5, ++ [OPTION_6RD] = 22, + }; + + +--- a/networking/udhcp/common.h ++++ b/networking/udhcp/common.h +@@ -88,6 +88,7 @@ enum { + OPTION_S32, + OPTION_BIN, + OPTION_STATIC_ROUTES, ++ OPTION_6RD, + #if ENABLE_FEATURE_UDHCP_RFC3397 + OPTION_DNS_STRING, /* RFC1035 compressed domain name list */ + OPTION_SIP_SERVERS, +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -100,6 +100,7 @@ static const uint8_t len_of_option_as_st + [OPTION_IP ] = sizeof("255.255.255.255 "), + [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, + [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), ++ [OPTION_6RD ] = sizeof("32 128 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF 255.255.255.255 "), + [OPTION_STRING ] = 1, + #if ENABLE_FEATURE_UDHCP_RFC3397 + [OPTION_DNS_STRING ] = 1, /* unused */ +@@ -123,6 +124,23 @@ static int sprint_nip(char *dest, const + return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); + } + ++static int sprint_nip6(char *dest, const char *pre, const uint8_t *ip) ++{ ++ int len = 0; ++ int off; ++ uint16_t word; ++ ++ len += sprintf(dest, "%s", pre); ++ ++ for (off = 0; off < 16; off += 2) ++ { ++ move_from_unaligned16(word, &ip[off]); ++ len += sprintf(dest+len, "%s%04X", off ? ":" : "", htons(word)); ++ } ++ ++ return len; ++} ++ + /* really simple implementation, just count the bits */ + static int mton(uint32_t mask) + { +@@ -231,6 +249,70 @@ static NOINLINE char *xmalloc_optname_op + } + + return ret; ++ } ++ case OPTION_6RD: { ++ /* Option binary format: ++ * 0 1 2 3 ++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | | ++ * | 6rdPrefix | ++ * | (16 octets) | ++ * | | ++ * | | ++ * | | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | 6rdBRIPv4Address(es) | ++ * . . ++ * . . ++ * . . ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * ++ * We convert it to a string "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address" ++ */ ++ ++ /* Sanity check: ensure that our length is at least 22 bytes, that ++ * IPv4MaskLen is <= 32, 6rdPrefixLen <= 128 and that the sum of ++ * (32 - IPv4MaskLen) + 6rdPrefixLen is less than or equal to 128. ++ * If any of these requirements is not fulfilled, return with empty ++ * value. ++ */ ++ if ((len >= 22) && (*option <= 32) && (*(option+1) <= 128) && ++ (((32 - *option) + *(option+1)) <= 128)) ++ { ++ /* IPv4MaskLen */ ++ dest += sprintf(dest, "%u ", *option++); ++ len--; ++ ++ /* 6rdPrefixLen */ ++ dest += sprintf(dest, "%u ", *option++); ++ len--; ++ ++ /* 6rdPrefix */ ++ dest += sprint_nip6(dest, "", option); ++ option += 16; ++ len -= 16; ++ ++ /* 6rdBRIPv4Addresses */ ++ while (len >= 4) ++ { ++ dest += sprint_nip(dest, " ", option); ++ option += 4; ++ len -= 4; ++ ++ /* the code to determine the option size fails to work with ++ * lengths that are not a multiple of the minimum length, ++ * adding all advertised 6rdBRIPv4Addresses here would ++ * overflow the destination buffer, therefore skip the rest ++ * for now ++ */ ++ break; ++ } ++ } ++ ++ return ret; + } + #if ENABLE_FEATURE_UDHCP_RFC3397 + case OPTION_DNS_STRING: diff --git a/package/busybox/patches/250-ash_export-n.patch b/package/busybox/patches/250-ash_export-n.patch new file mode 100644 index 000000000..048c236b8 --- /dev/null +++ b/package/busybox/patches/250-ash_export-n.patch @@ -0,0 +1,34 @@ +--- a/shell/ash.c ++++ b/shell/ash.c +@@ -12611,8 +12611,17 @@ exportcmd(int argc UNUSED_PARAM, char ** + const char *p; + char **aptr; + int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT; ++ int mask = ~0; ++ int nopt; ++ while ((nopt = nextopt("np"))) { ++ if (nopt == 'n') { ++ mask = ~flag; ++ } else { /* p */ ++ break; ++ } ++ } + +- if (nextopt("p") != 'p') { ++ if (nopt != 'p') { + aptr = argptr; + name = *aptr; + if (name) { +@@ -12624,10 +12633,12 @@ exportcmd(int argc UNUSED_PARAM, char ** + vp = *findvar(hashvar(name), name); + if (vp) { + vp->flags |= flag; ++ vp->flags &= mask; + continue; + } + } + setvar(name, p, flag); ++ setvar(name, p, flag & mask); + } while ((name = *++aptr) != NULL); + return 0; + } diff --git a/package/busybox/patches/251-ash_fix-redir-substitution.patch b/package/busybox/patches/251-ash_fix-redir-substitution.patch new file mode 100644 index 000000000..cb2ae94e0 --- /dev/null +++ b/package/busybox/patches/251-ash_fix-redir-substitution.patch @@ -0,0 +1,12 @@ +--- a/shell/ash.c ++++ b/shell/ash.c +@@ -6846,8 +6846,7 @@ evalvar(char *p, int flags, struct strli + patloc = expdest - (char *)stackblock(); + if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, + startloc, varflags, +-//TODO: | EXP_REDIR too? All other such places do it too +- /* quotes: */ flags & (EXP_FULL | EXP_CASE), ++ /* quotes: */ flags & (EXP_FULL | EXP_CASE | EXP_REDIR), + var_str_list) + ) { + int amount = expdest - ( diff --git a/package/busybox/patches/300-netmsg.patch b/package/busybox/patches/300-netmsg.patch new file mode 100644 index 000000000..e8b2513eb --- /dev/null +++ b/package/busybox/patches/300-netmsg.patch @@ -0,0 +1,103 @@ +--- a/include/applets.src.h ++++ b/include/applets.src.h +@@ -266,6 +266,7 @@ IF_MT(APPLET(mt, BB_DIR_BIN, BB_SUID_DRO + IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP)) + IF_NAMEIF(APPLET(nameif, BB_DIR_SBIN, BB_SUID_DROP)) + IF_NC(APPLET(nc, BB_DIR_USR_BIN, BB_SUID_DROP)) ++IF_NETMSG(APPLET(netmsg, BB_DIR_BIN, BB_SUID_REQUIRE)) + IF_NETSTAT(APPLET(netstat, BB_DIR_BIN, BB_SUID_DROP)) + IF_NICE(APPLET(nice, BB_DIR_BIN, BB_SUID_DROP)) + IF_NOHUP(APPLET(nohup, BB_DIR_USR_BIN, BB_SUID_DROP)) +--- a/networking/Config.src ++++ b/networking/Config.src +@@ -612,6 +612,12 @@ config FEATURE_IPCALC_LONG_OPTIONS + help + Support long options for the ipcalc applet. + ++config NETMSG ++ bool "netmsg" ++ default n ++ help ++ simple program for sending udp broadcast messages ++ + config NETSTAT + bool "netstat" + default y +--- a/networking/Kbuild.src ++++ b/networking/Kbuild.src +@@ -27,6 +27,7 @@ lib-$(CONFIG_IP) += ip.o + lib-$(CONFIG_IPCALC) += ipcalc.o + lib-$(CONFIG_NAMEIF) += nameif.o + lib-$(CONFIG_NC) += nc.o ++lib-$(CONFIG_NETMSG) += netmsg.o + lib-$(CONFIG_NETSTAT) += netstat.o + lib-$(CONFIG_NSLOOKUP) += nslookup.o + lib-$(CONFIG_NTPD) += ntpd.o +--- /dev/null ++++ b/networking/netmsg.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2006 Felix Fietkau ++ * ++ * This is free software, licensed under the GNU General Public License v2. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "busybox.h" ++ ++//usage:#define netmsg_trivial_usage NOUSAGE_STR ++//usage:#define netmsg_full_usage "" ++ ++#ifndef CONFIG_NETMSG ++int main(int argc, char **argv) ++#else ++int netmsg_main(int argc, char **argv) ++#endif ++{ ++ int s; ++ struct sockaddr_in addr; ++ int optval = 1; ++ unsigned char buf[1001]; ++ ++ if (argc != 3) { ++ fprintf(stderr, "usage: %s \"\"\n", argv[0]); ++ exit(1); ++ } ++ ++ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ++ perror("Opening socket"); ++ exit(1); ++ } ++ ++ memset(&addr, 0, sizeof(addr)); ++ addr.sin_family = AF_INET; ++ addr.sin_addr.s_addr = inet_addr(argv[1]); ++ addr.sin_port = htons(0x1337); ++ ++ memset(buf, 0, 1001); ++ buf[0] = 0xde; ++ buf[1] = 0xad; ++ ++ strncpy(buf + 2, argv[2], 998); ++ ++ if (setsockopt (s, SOL_SOCKET, SO_BROADCAST, (caddr_t) &optval, sizeof (optval)) < 0) { ++ perror("setsockopt()"); ++ goto fail; ++ } ++ ++ if (sendto(s, buf, 1001, 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) { ++ perror("sendto()"); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ close(s); ++ exit(1); ++} diff --git a/package/busybox/patches/310-passwd_access.patch b/package/busybox/patches/310-passwd_access.patch new file mode 100644 index 000000000..daa1b9998 --- /dev/null +++ b/package/busybox/patches/310-passwd_access.patch @@ -0,0 +1,41 @@ + + Copyright (C) 2006 OpenWrt.org + +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -1700,21 +1700,32 @@ static int check_user_passwd(const char + + if (ENABLE_FEATURE_HTTPD_AUTH_MD5) { + char *md5_passwd; ++ int user_len_p1; + + md5_passwd = strchr(cur->after_colon, ':'); +- if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1' ++ user_len_p1 = md5_passwd + 1 - cur->after_colon; ++ if (md5_passwd && !strncmp(md5_passwd + 1, "$p$", 3)) { ++ struct passwd *pwd = NULL; ++ ++ pwd = getpwnam(&md5_passwd[4]); ++ if(!pwd->pw_passwd || !pwd->pw_passwd[0] || pwd->pw_passwd[0] == '!') ++ return 1; ++ ++ md5_passwd = pwd->pw_passwd; ++ goto check_md5_pw; ++ } else if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1' + && md5_passwd[3] == '$' && md5_passwd[4] + ) { + char *encrypted; +- int r, user_len_p1; ++ int r; + + md5_passwd++; +- user_len_p1 = md5_passwd - cur->after_colon; + /* comparing "user:" */ + if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) { + continue; + } + ++check_md5_pw: + encrypted = pw_encrypt( + user_and_passwd + user_len_p1 /* cleartext pwd from user */, + md5_passwd /*salt */, 1 /* cleanup */); diff --git a/package/busybox/patches/340-lock_util.patch b/package/busybox/patches/340-lock_util.patch new file mode 100644 index 000000000..eb346421a --- /dev/null +++ b/package/busybox/patches/340-lock_util.patch @@ -0,0 +1,172 @@ +--- a/include/applets.src.h ++++ b/include/applets.src.h +@@ -218,6 +218,7 @@ IF_LN(APPLET_NOEXEC(ln, ln, BB_DIR_BIN, + IF_LOAD_POLICY(APPLET(load_policy, BB_DIR_USR_SBIN, BB_SUID_DROP)) + IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP)) + IF_LOADKMAP(APPLET(loadkmap, BB_DIR_SBIN, BB_SUID_DROP)) ++IF_LOCK(APPLET(lock, BB_DIR_BIN, BB_SUID_DROP)) + IF_LOGGER(APPLET(logger, BB_DIR_USR_BIN, BB_SUID_DROP)) + /* Needs to be run by root or be suid root - needs to change uid and gid: */ + IF_LOGIN(APPLET(login, BB_DIR_BIN, BB_SUID_REQUIRE)) +--- a/miscutils/Config.src ++++ b/miscutils/Config.src +@@ -419,6 +419,11 @@ config FEATURE_HDPARM_HDIO_GETSET_DMA + help + Enables the 'hdparm -d' option to get/set using_dma flag. + ++config LOCK ++ bool "lock" ++ help ++ Small utility for using locks in scripts ++ + config MAKEDEVS + bool "makedevs" + default y +--- a/miscutils/Kbuild.src ++++ b/miscutils/Kbuild.src +@@ -29,6 +29,7 @@ lib-$(CONFIG_INOTIFYD) += inotifyd.o + lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o + lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o + lib-$(CONFIG_LESS) += less.o ++lib-$(CONFIG_LOCK) += lock.o + lib-$(CONFIG_MAKEDEVS) += makedevs.o + lib-$(CONFIG_MAN) += man.o + lib-$(CONFIG_MICROCOM) += microcom.o +--- /dev/null ++++ b/miscutils/lock.c +@@ -0,0 +1,135 @@ ++/* ++ * Copyright (C) 2006 Felix Fietkau ++ * ++ * This is free software, licensed under the GNU General Public License v2. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "busybox.h" ++ ++//usage:#define lock_trivial_usage NOUSAGE_STR ++//usage:#define lock_full_usage "" ++ ++static int unlock = 0; ++static int shared = 0; ++static int waitonly = 0; ++static int fd; ++static char *file; ++ ++static void usage(char *name) ++{ ++ fprintf(stderr, "Usage: %s [-suw] \n" ++ " -s Use shared locking\n" ++ " -u Unlock\n" ++ " -w Wait for the lock to become free, don't acquire lock\n" ++ "\n", name); ++ exit(1); ++} ++ ++static void exit_unlock(int sig) ++{ ++ flock(fd, LOCK_UN); ++ exit(0); ++} ++ ++static int do_unlock(void) ++{ ++ FILE *f; ++ int i; ++ ++ if ((f = fopen(file, "r")) == NULL) ++ return 0; ++ ++ fscanf(f, "%d", &i); ++ if (i > 0) ++ kill(i, SIGTERM); ++ ++ fclose(f); ++ ++ return 0; ++} ++ ++static int do_lock(void) ++{ ++ int pid; ++ char pidstr[8]; ++ ++ if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0700)) < 0) { ++ if ((fd = open(file, O_RDWR)) < 0) { ++ fprintf(stderr, "Can't open %s\n", file); ++ return 1; ++ } ++ } ++ ++ if (flock(fd, (shared ? LOCK_SH : LOCK_EX)) < 0) { ++ fprintf(stderr, "Can't lock %s\n", file); ++ return 1; ++ } ++ ++ pid = fork(); ++ ++ if (pid < 0) ++ return -1; ++ ++ if (pid == 0) { ++ signal(SIGKILL, exit_unlock); ++ signal(SIGTERM, exit_unlock); ++ signal(SIGINT, exit_unlock); ++ if (waitonly) ++ exit_unlock(0); ++ else ++ while (1) ++ sleep(1); ++ } else { ++ if (!waitonly) { ++ lseek(fd, 0, SEEK_SET); ++ ftruncate(fd, 0); ++ sprintf(pidstr, "%d\n", pid); ++ write(fd, pidstr, strlen(pidstr)); ++ close(fd); ++ } ++ ++ return 0; ++ } ++ return 0; ++} ++ ++int lock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; ++int lock_main(int argc, char **argv) ++{ ++ char **args = &argv[1]; ++ int c = argc - 1; ++ ++ while ((*args != NULL) && (*args)[0] == '-') { ++ char *ch = *args; ++ while (*(++ch) > 0) { ++ switch(*ch) { ++ case 'w': ++ waitonly = 1; ++ break; ++ case 's': ++ shared = 1; ++ break; ++ case 'u': ++ unlock = 1; ++ break; ++ } ++ } ++ c--; ++ args++; ++ } ++ ++ if (c != 1) ++ usage(argv[0]); ++ ++ file = *args; ++ if (unlock) ++ return do_unlock(); ++ else ++ return do_lock(); ++} diff --git a/package/busybox/patches/350-httpd_redir.patch b/package/busybox/patches/350-httpd_redir.patch new file mode 100644 index 000000000..11125e71f --- /dev/null +++ b/package/busybox/patches/350-httpd_redir.patch @@ -0,0 +1,90 @@ +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -105,6 +105,7 @@ + //usage: IF_FEATURE_HTTPD_BASIC_AUTH(" [-r REALM]") + //usage: " [-h HOME]\n" + //usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING" ++//usage: " [-R [-H ]]" + //usage:#define httpd_full_usage "\n\n" + //usage: "Listen for incoming HTTP requests\n" + //usage: "\n -i Inetd mode" +@@ -121,6 +122,8 @@ + //usage: "\n -m STRING MD5 crypt STRING") + //usage: "\n -e STRING HTML encode STRING" + //usage: "\n -d STRING URL decode STRING" ++//usage: "\n -R PATH Redirect target path" ++//usage: "\n -H HOST Redirect target host" + + #include "libbb.h" + #if ENABLE_FEATURE_HTTPD_USE_SENDFILE +@@ -272,6 +275,8 @@ struct globals { + + const char *found_mime_type; + const char *found_moved_temporarily; ++ const char *redirect_path; ++ const char *redirect_host; + Htaccess_IP *ip_a_d; /* config allow/deny lines */ + + IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) +@@ -322,6 +327,8 @@ struct globals { + #define index_page (G.index_page ) + #define found_mime_type (G.found_mime_type ) + #define found_moved_temporarily (G.found_moved_temporarily) ++#define redirect_path (G.redirect_path ) ++#define redirect_host (G.redirect_host ) + #define last_mod (G.last_mod ) + #define ip_a_d (G.ip_a_d ) + #define g_realm (G.g_realm ) +@@ -956,8 +963,11 @@ static void send_headers(int responseNum + } + #endif + if (responseNum == HTTP_MOVED_TEMPORARILY) { +- len += sprintf(iobuf + len, "Location: %s/%s%s\r\n", ++ len += sprintf(iobuf + len, "Location: %s%s%s%s%s%s\r\n", ++ (redirect_host ? "http://" : ""), ++ (redirect_host ? redirect_host : ""), + found_moved_temporarily, ++ (redirect_host ? "" : "/"), + (g_query ? "?" : ""), + (g_query ? g_query : "")); + } +@@ -1925,8 +1935,12 @@ static void handle_incoming_and_exit(con + } while (*++tptr); + *++urlp = '\0'; /* terminate after last character */ + ++ /* redirect active */ ++ if (redirect_path && (strncmp(urlcopy, redirect_path, strlen(redirect_path)) != 0)) ++ found_moved_temporarily = redirect_path; ++ + /* If URL is a directory, add '/' */ +- if (urlp[-1] != '/') { ++ if (!redirect_path && (urlp[-1] != '/')) { + if (is_directory(urlcopy + 1, 1, NULL)) { + found_moved_temporarily = urlcopy; + } +@@ -2283,7 +2297,9 @@ static void sighup_handler(int sig UNUSE + } + + enum { +- c_opt_config_file = 0, ++ R_opt_redirect_path = 0, ++ H_opt_redirect_host, ++ c_opt_config_file, + d_opt_decode_url, + h_opt_home_httpd, + IF_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,) +@@ -2332,12 +2348,13 @@ int httpd_main(int argc UNUSED_PARAM, ch + /* We do not "absolutize" path given by -h (home) opt. + * If user gives relative path in -h, + * $SCRIPT_FILENAME will not be set. */ +- opt = getopt32(argv, "c:d:h:" ++ opt = getopt32(argv, "R:H:c:d:h:" + IF_FEATURE_HTTPD_ENCODE_URL_STR("e:") + IF_FEATURE_HTTPD_BASIC_AUTH("r:") + IF_FEATURE_HTTPD_AUTH_MD5("m:") + IF_FEATURE_HTTPD_SETUID("u:") + "p:ifv", ++ &redirect_path, &redirect_host, + &opt_c_configFile, &url_for_decode, &home_httpd + IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) + IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) diff --git a/package/busybox/patches/410-httpd_cgi_headers.patch b/package/busybox/patches/410-httpd_cgi_headers.patch new file mode 100644 index 000000000..b02a5b9d7 --- /dev/null +++ b/package/busybox/patches/410-httpd_cgi_headers.patch @@ -0,0 +1,16 @@ +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -1222,10 +1222,10 @@ static NOINLINE void cgi_io_loop_and_exi + if (full_write(STDOUT_FILENO, HTTP_200, sizeof(HTTP_200)-1) != sizeof(HTTP_200)-1) + break; + } +- /* Commented out: +- if (!strstr(rbuf, "ontent-")) { +- full_write(s, "Content-type: text/plain\r\n\r\n", 28); ++ if (!strstr(rbuf, "ontent-") && !strstr(rbuf, "ocation:")) { ++ full_write(1, "Content-type: text/plain\r\n\r\n", 28); + } ++ /* Previously commented out: + * Counter-example of valid CGI without Content-type: + * echo -en "HTTP/1.0 302 Found\r\n" + * echo -en "Location: http://www.busybox.net\r\n" diff --git a/package/busybox/patches/440-httpd_chdir.patch b/package/busybox/patches/440-httpd_chdir.patch new file mode 100644 index 000000000..401c6eb5d --- /dev/null +++ b/package/busybox/patches/440-httpd_chdir.patch @@ -0,0 +1,10 @@ +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -1814,6 +1814,7 @@ static void handle_incoming_and_exit(con + char *header_ptr = header_ptr; + Htaccess_Proxy *proxy_entry; + #endif ++ xchdir(home_httpd); + + /* Allocation of iobuf is postponed until now + * (IOW, server process doesn't need to waste 8k) */ diff --git a/package/busybox/patches/470-insmod_search.patch b/package/busybox/patches/470-insmod_search.patch new file mode 100644 index 000000000..7f0188fc8 --- /dev/null +++ b/package/busybox/patches/470-insmod_search.patch @@ -0,0 +1,137 @@ +--- a/modutils/Config.src ++++ b/modutils/Config.src +@@ -247,7 +247,7 @@ config FEATURE_MODUTILS_SYMBOLS + config DEFAULT_MODULES_DIR + string "Default directory containing modules" + default "/lib/modules" +- depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO ++ depends on DEPMOD || INSMOD || MODPROBE || MODPROBE_SMALL || MODINFO + help + Directory that contains kernel modules. + Defaults to "/lib/modules" +--- a/modutils/insmod.c ++++ b/modutils/insmod.c +@@ -11,6 +11,106 @@ + + #include "libbb.h" + #include "modutils.h" ++#include ++#ifndef CONFIG_FEATURE_2_4_MODULES ++#include ++#include ++#include ++#endif ++ ++static char *g_filename = NULL; ++ ++static int FAST_FUNC check_module_name_match(const char *filename, struct stat *statbuf, ++ void *userdata, int depth) ++{ ++ char *fullname = (char *) userdata; ++ char *tmp; ++ ++ if (fullname[0] == '\0') ++ return FALSE; ++ ++ tmp = bb_get_last_path_component_nostrip(filename); ++ if (strcmp(tmp, fullname) == 0) { ++ /* Stop searching if we find a match */ ++ g_filename = xstrdup(filename); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static int find_module(char *filename) ++{ ++ char *module_dir, real_module_dir[FILENAME_MAX]; ++ int len, slen, ret = ENOENT, k_version; ++ struct utsname myuname; ++ const char *suffix = ".ko"; ++ struct stat st; ++ ++ /* check the kernel version */ ++ if (uname(&myuname) != 0) ++ return EINVAL; ++ ++ k_version = myuname.release[0] - '0'; ++ ++ if (k_version < 2 || k_version > 9) ++ return EINVAL; ++ ++ if (k_version == 2) { ++ int k_patchlevel = myuname.release[2] - '0'; ++ if (k_patchlevel <= 4) ++#if ENABLE_FEATURE_2_4_MODULES ++ suffix = ".o"; ++#else ++ return EINVAL; ++#endif ++ } ++ ++ len = strlen(filename); ++ slen = strlen(suffix); ++ ++ /* check for suffix and absolute path first */ ++ if ((len < slen + 2) || (strcmp(filename + len - slen, suffix) != 0)) { ++ filename = xasprintf("%s%s", filename, suffix); ++ } else { ++ filename = strdup(filename); ++ if ((stat(filename, &st) == 0) && S_ISREG(st.st_mode)) { ++ g_filename = filename; ++ return 0; ++ } ++ free(filename); ++ return ENOENT; ++ } ++ ++ /* next: scan /lib/modules/ */ ++ /* Jump through hoops in case /lib/modules/`uname -r` ++ * is a symlink. We do not want recursive_action to ++ * follow symlinks, but we do want to follow the ++ * /lib/modules/`uname -r` dir, So resolve it ourselves ++ * if it is a link... */ ++ module_dir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release); ++ if (realpath(module_dir, real_module_dir) != NULL) { ++ free(module_dir); ++ module_dir = real_module_dir; ++ } ++ ++ recursive_action(module_dir, ACTION_RECURSE, ++ check_module_name_match, 0, filename, 0); ++ ++ /* Check if we have a complete path */ ++ if (g_filename == NULL) ++ goto done; ++ ++ if ((stat(g_filename, &st) == 0) && S_ISREG(st.st_mode)) ++ ret = 0; ++ else ++ free(g_filename); ++ ++done: ++ free(filename); ++ ++ return ret; ++} + + /* 2.6 style insmod has no options and required filename + * (not module name - .ko can't be omitted) */ +@@ -58,9 +158,15 @@ int insmod_main(int argc UNUSED_PARAM, c + if (!filename) + bb_show_usage(); + +- rc = bb_init_module(filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0)); ++ rc = find_module(filename); ++ if (rc || (g_filename == NULL)) ++ goto done; ++ ++ rc = bb_init_module(g_filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0)); + if (rc) + bb_error_msg("can't insert '%s': %s", filename, moderror(rc)); ++ free (g_filename); + ++done: + return rc; + } diff --git a/package/busybox/patches/480-mount_union.patch b/package/busybox/patches/480-mount_union.patch new file mode 100644 index 000000000..2f236a152 --- /dev/null +++ b/package/busybox/patches/480-mount_union.patch @@ -0,0 +1,29 @@ +--- a/util-linux/mount.c ++++ b/util-linux/mount.c +@@ -136,6 +136,10 @@ + # include + #endif + ++#ifndef MS_UNION ++#define MS_UNION 0x100 /* 256: Mount on top of a union */ ++#endif ++ + + #if defined(__dietlibc__) + // 16.12.2006, Sampo Kellomaki (sampo@iki.fi) +@@ -254,6 +258,7 @@ static const int32_t mount_options[] = { + /* "rslave" */ MS_SLAVE|MS_RECURSIVE, + /* "rprivate" */ MS_PRIVATE|MS_RECURSIVE, + /* "runbindable" */ MS_UNBINDABLE|MS_RECURSIVE, ++ /* "union" */ MS_UNION, + ) + + // Always understood. +@@ -310,6 +315,7 @@ static const char mount_option_str[] = + "make-rslave\0" + "make-rprivate\0" + "make-runbindable\0" ++ "make-union\0" + ) + + // Always understood. diff --git a/package/busybox/patches/490-mount_disable_check.patch b/package/busybox/patches/490-mount_disable_check.patch new file mode 100644 index 000000000..2fcb7f7fc --- /dev/null +++ b/package/busybox/patches/490-mount_disable_check.patch @@ -0,0 +1,12 @@ +--- a/util-linux/mount.c ++++ b/util-linux/mount.c +@@ -128,9 +128,6 @@ + #if ENABLE_FEATURE_MOUNT_NFS + /* This is just a warning of a common mistake. Possibly this should be a + * uclibc faq entry rather than in busybox... */ +-# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) +-# error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support" +-# endif + # include + # include + # include diff --git a/package/busybox/patches/510-awk_include.patch b/package/busybox/patches/510-awk_include.patch new file mode 100644 index 000000000..9f525acf8 --- /dev/null +++ b/package/busybox/patches/510-awk_include.patch @@ -0,0 +1,217 @@ +--- a/editors/awk.c ++++ b/editors/awk.c +@@ -1,3 +1,4 @@ ++ + /* vi: set sw=4 ts=4: */ + /* + * awk implementation for busybox +@@ -81,9 +82,14 @@ typedef struct chain_s { + } chain; + + /* Function */ ++typedef var *(*awk_cfunc)(var *res, var *args, int nargs); + typedef struct func_s { + unsigned nargs; ++ enum { AWKFUNC, CFUNC } type; ++ union { ++ awk_cfunc cfunc; + struct chain_s body; ++ } x; + } func; + + /* I/O stream */ +@@ -1473,7 +1479,8 @@ static void parse_program(char *p) + next_token(TC_FUNCTION); + g_pos++; + f = newfunc(t_string); +- f->body.first = NULL; ++ f->type = AWKFUNC; ++ f->x.body.first = NULL; + f->nargs = 0; + while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) { + v = findvar(ahash, t_string); +@@ -1482,7 +1489,7 @@ static void parse_program(char *p) + if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM) + break; + } +- seq = &f->body; ++ seq = &f->x.body; + chain_group(); + clear_array(ahash); + +@@ -2580,7 +2587,8 @@ static var *evaluate(node *op, var *res) + var *vbeg, *v; + const char *sv_progname; + +- if (!op->r.f->body.first) ++ if ((op->r.f->type == AWKFUNC) && ++ !op->r.f->x.body.first) + syntax_error(EMSG_UNDEF_FUNC); + + vbeg = v = nvalloc(op->r.f->nargs + 1); +@@ -2597,7 +2605,10 @@ static var *evaluate(node *op, var *res) + fnargs = vbeg; + sv_progname = g_progname; + +- res = evaluate(op->r.f->body.first, res); ++ if (op->r.f->type == AWKFUNC) ++ res = evaluate(op->r.f->x.body.first, res); ++ else if (op->r.f->type == CFUNC) ++ res = op->r.f->x.cfunc(res, fnargs, op->r.f->nargs); + + g_progname = sv_progname; + nvfree(fnargs); +@@ -2991,6 +3002,143 @@ static rstream *next_input_file(void) + #undef files_happen + } + ++/* read the contents of an entire file */ ++static char *get_file(const char *fname) ++{ ++ FILE *F; ++ char *s = NULL; ++ int i, j, flen; ++ ++ F = fopen(fname, "r"); ++ if (!F) { ++ return NULL; ++ } ++ ++ if (fseek(F, 0, SEEK_END) == 0) { ++ flen = ftell(F); ++ s = (char *)xmalloc(flen+4); ++ fseek(F, 0, SEEK_SET); ++ i = 1 + fread(s+1, 1, flen, F); ++ } else { ++ for (i=j=1; j>0; i+=j) { ++ s = (char *)xrealloc(s, i+4096); ++ j = fread(s+i, 1, 4094, F); ++ } ++ } ++ ++ s[i] = '\0'; ++ fclose(F); ++ return s; ++} ++ ++ ++/* parse_include(): ++ * ++ * taken from parse_program from awk.c ++ * END{} is not parsed here, and BEGIN{} is executed immediately ++ */ ++static void parse_include(char *p) ++{ ++ uint32_t tclass; ++ chain *initseq = NULL; ++ chain tmp; ++ func *f; ++ var *v, *tv; ++ ++ tv = nvalloc(1); ++ memset(&tmp, 0, sizeof(tmp)); ++ g_pos = p; ++ t_lineno = 1; ++ while ((tclass = next_token(TC_EOF | TC_OPSEQ | ++ TC_OPTERM | TC_BEGIN | TC_FUNCDECL)) != TC_EOF) { ++ if (tclass & TC_OPTERM) ++ continue; ++ ++ seq = &tmp; ++ if (tclass & TC_BEGIN) { ++ initseq = xzalloc(sizeof(chain)); ++ seq = initseq; ++ chain_group(); ++ } else if (tclass & TC_FUNCDECL) { ++ next_token(TC_FUNCTION); ++ g_pos++; ++ f = newfunc(t_string); ++ f->type = AWKFUNC; ++ f->x.body.first = NULL; ++ f->nargs = 0; ++ while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) { ++ v = findvar(ahash, t_string); ++ v->x.aidx = (f->nargs)++; ++ ++ if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM) ++ break; ++ } ++ seq = &(f->x.body); ++ chain_group(); ++ clear_array(ahash); ++ } ++ } ++ if (initseq && initseq->first) ++ tv = evaluate(initseq->first, tv); ++ nvfree(tv); ++} ++ ++ ++/* include an awk file and run its BEGIN{} section */ ++static xhash *includes = NULL; ++static void include_file(const char *filename) ++{ ++ char *s; ++ var *v; ++ int oldlnr = g_lineno; ++ const char *oldprg = g_progname; ++ ++ if (!includes) ++ includes = hash_init(); ++ ++ /* find out if the file has been included already */ ++ v = findvar(includes, filename); ++ if (istrue(v)) ++ return; ++ setvar_s(v, "1"); ++ ++ /* read include file */ ++ s = get_file(filename); ++ if (!s) { ++ fprintf(stderr, "Could not open file.\n"); ++ return; ++ } ++ g_lineno = 1; ++ g_progname = xstrdup(filename); ++ parse_include(s+1); ++ free(s); ++ g_lineno = oldlnr; ++ g_progname = oldprg; ++} ++ ++static var *include(var *res, var *args, int nargs) ++{ ++ const char *s; ++ ++ nargs = nargs; /* shut up, gcc */ ++ s = getvar_s(args); ++ if (s && (strlen(s) > 0)) ++ include_file(s); ++ ++ return res; ++} ++ ++/* registers a global c function for the awk interpreter */ ++static void register_cfunc(const char *name, awk_cfunc cfunc, int nargs) ++{ ++ func *f; ++ ++ f = newfunc(name); ++ f->type = CFUNC; ++ f->x.cfunc = cfunc; ++ f->nargs = nargs; ++} ++ + int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; + int awk_main(int argc, char **argv) + { +@@ -3056,6 +3204,9 @@ int awk_main(int argc, char **argv) + *s1 = '='; + } + } ++ ++ register_cfunc("include", include, 1); ++ + opt_complementary = "v::f::"; /* -v and -f can occur multiple times */ + opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W); + argv += optind; diff --git a/package/busybox/patches/524-udhcpc_renew.patch b/package/busybox/patches/524-udhcpc_renew.patch new file mode 100644 index 000000000..01edda3a5 --- /dev/null +++ b/package/busybox/patches/524-udhcpc_renew.patch @@ -0,0 +1,10 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -983,7 +983,6 @@ static void perform_renew(void) + state = RENEW_REQUESTED; + break; + case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ +- udhcp_run_script(NULL, "deconfig"); + case REQUESTING: + case RELEASED: + change_listen_mode(LISTEN_RAW); diff --git a/package/busybox/patches/610-ntpd_delayed_resolve.patch b/package/busybox/patches/610-ntpd_delayed_resolve.patch new file mode 100644 index 000000000..5e17ae16c --- /dev/null +++ b/package/busybox/patches/610-ntpd_delayed_resolve.patch @@ -0,0 +1,48 @@ +--- a/networking/ntpd.c ++++ b/networking/ntpd.c +@@ -216,6 +216,7 @@ typedef struct { + typedef struct { + len_and_sockaddr *p_lsa; + char *p_dotted; ++ char *p_hostname; + /* when to send new query (if p_fd == -1) + * or when receive times out (if p_fd >= 0): */ + int p_fd; +@@ -646,8 +647,9 @@ add_peers(char *s) + peer_t *p; + + p = xzalloc(sizeof(*p)); +- p->p_lsa = xhost2sockaddr(s, 123); +- p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); ++ p->p_hostname = s; ++ p->p_lsa = NULL; ++ p->p_dotted = NULL; + p->p_fd = -1; + p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); + p->next_action_time = G.cur_time; /* = set_next(p, 0); */ +@@ -696,6 +698,25 @@ send_query_to_peer(peer_t *p) + * + * Uncomment this and use strace to see it in action: + */ ++ ++ /* See if the peer hostname already resolved yet, if not, retry to resolv and return on failure */ ++ if (!p->p_lsa) ++ { ++ p->p_lsa = host2sockaddr(p->p_hostname, 123); ++ ++ if (p->p_lsa) ++ { ++ p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); ++ VERB1 bb_error_msg("resolved peer %s to %s", p->p_hostname, p->p_dotted); ++ } ++ else ++ { ++ set_next(p, RETRY_INTERVAL); ++ VERB1 bb_error_msg("could not resolve peer %s, skipping", p->p_hostname); ++ return; ++ } ++ } ++ + #define PROBE_LOCAL_ADDR /* { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); } */ + + if (p->p_fd == -1) { diff --git a/package/busybox/patches/700-hexdump_segfault_fix.patch b/package/busybox/patches/700-hexdump_segfault_fix.patch new file mode 100644 index 000000000..ab09fb3e4 --- /dev/null +++ b/package/busybox/patches/700-hexdump_segfault_fix.patch @@ -0,0 +1,11 @@ +--- a/libbb/dump.c ++++ b/libbb/dump.c +@@ -301,7 +301,7 @@ static NOINLINE void rewrite(priv_dumper + ) { + fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt; + } +- if (fu->reps > 1) { ++ if (fu->reps > 1 && fu->nextpr) { + for (pr = fu->nextpr;; pr = pr->nextpr) + if (!pr->nextpr) + break; diff --git a/package/busybox/patches/802-brctl_linux24.patch b/package/busybox/patches/802-brctl_linux24.patch new file mode 100644 index 000000000..8cc19779a --- /dev/null +++ b/package/busybox/patches/802-brctl_linux24.patch @@ -0,0 +1,74 @@ +--- a/networking/brctl.c ++++ b/networking/brctl.c +@@ -56,7 +56,7 @@ + + /* Maximum number of ports supported per bridge interface. */ + #ifndef MAX_PORTS +-# define MAX_PORTS 32 ++# define MAX_PORTS 1024 + #endif + + /* Use internal number parsing and not the "exact" conversion. */ +@@ -193,6 +193,7 @@ int brctl_main(int argc UNUSED_PARAM, ch + printf(bi.stp_enabled ? "\tyes" : "\tno"); + + /* print interface list */ ++ memset(ifidx, 0, sizeof ifidx); + arm_ioctl(args, BRCTL_GET_PORT_LIST, + (unsigned long) ifidx, MAX_PORTS); + xioctl(fd, SIOCDEVPRIVATE, &ifr); +@@ -221,9 +222,19 @@ int brctl_main(int argc UNUSED_PARAM, ch + br = *argv++; + + if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */ +- ioctl_or_perror_and_die(fd, +- key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, +- br, "bridge %s", br); ++ int ret; ++ ret = ioctl(fd, ++ key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, ++ br); ++ if (ret < 0) { ++ arm_ioctl(args, ++ key == ARG_addbr ? BRCTL_ADD_BRIDGE : BRCTL_DEL_BRIDGE, ++ (unsigned long) br, 0); ++ ret = ioctl(fd, SIOCSIFBR, args); ++ } ++ if (ret < 0) { ++ bb_perror_msg_and_die("bridge %s", br); ++ } + goto done; + } + +@@ -232,14 +243,27 @@ int brctl_main(int argc UNUSED_PARAM, ch + + strncpy_IFNAMSIZ(ifr.ifr_name, br); + if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ ++ int ret; ++ int if_index; + brif = *argv; +- ifr.ifr_ifindex = if_nametoindex(brif); +- if (!ifr.ifr_ifindex) { ++ if_index = if_nametoindex(brif); ++ if (!if_index) { + bb_perror_msg_and_die("iface %s", brif); + } +- ioctl_or_perror_and_die(fd, ++ ifr.ifr_ifindex = if_index; ++ ret = ioctl(fd, + key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, +- &ifr, "bridge %s", br); ++ &ifr); ++ if (ret < 0) { ++ arm_ioctl(args, ++ key == ARG_addif ? BRCTL_ADD_IF : BRCTL_DEL_IF, ++ if_index, 0); ++ ifr.ifr_data = (char *) &args; ++ ret = ioctl(fd, SIOCDEVPRIVATE, &ifr); ++ } ++ if (ret < 0) { ++ bb_perror_msg_and_die("bridge %s", br); ++ } + goto done_next_argv; + } + #if ENABLE_FEATURE_BRCTL_FANCY diff --git a/package/busybox/patches/803-id_getgrouplist.patch b/package/busybox/patches/803-id_getgrouplist.patch new file mode 100644 index 000000000..638305ee7 --- /dev/null +++ b/package/busybox/patches/803-id_getgrouplist.patch @@ -0,0 +1,49 @@ +This patch disable supplementary groups handling in id with uClibc versions +prior to v0.9.30, which are lacking the 'getgrouplist' function. + +Signed-off-by: Nicolas Thill + +--- a/coreutils/id.c ++++ b/coreutils/id.c +@@ -63,10 +63,12 @@ + + /* This is a NOEXEC applet. Be very careful! */ + ++#define HAVE_GETGROUPLIST 1 ++ + #if !ENABLE_USE_BB_PWD_GRP + #if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0) + #if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 30) +-#error "Sorry, you need at least uClibc version 0.9.30 for id applet to build" ++#undef HAVE_GETGROUPLIST + #endif + #endif + #endif +@@ -128,7 +130,11 @@ static int get_groups(const char *userna + /* If the user is a member of more than + * *n groups, then -1 is returned. Otherwise >= 0. + * (and no defined way of detecting errors?!) */ ++#if HAVE_GETGROUPLIST + m = getgrouplist(username, rgid, groups, n); ++#else ++ *n = -1; ++#endif + /* I guess *n < 0 might indicate error. Anyway, + * malloc'ing -1 bytes won't be good, so: */ + if (*n < 0) +@@ -210,6 +216,7 @@ int id_main(int argc UNUSED_PARAM, char + if (egid != rgid) + status |= print_group(egid, " "); + } ++#if HAVE_GETGROUPLIST + /* We are supplying largish buffer, trying + * to not run get_groups() twice. That might be slow + * ("user database in remote SQL server" case) */ +@@ -236,6 +243,7 @@ int id_main(int argc UNUSED_PARAM, char + } + if (ENABLE_FEATURE_CLEAN_UP) + free(groups); ++#endif + #if ENABLE_SELINUX + if (is_selinux_enabled()) { + if (getcon(&scontext) == 0) diff --git a/package/busybox/patches/902-telnetd_intr.patch b/package/busybox/patches/902-telnetd_intr.patch new file mode 100644 index 000000000..862ece055 --- /dev/null +++ b/package/busybox/patches/902-telnetd_intr.patch @@ -0,0 +1,10 @@ +--- a/networking/telnetd.c ++++ b/networking/telnetd.c +@@ -330,6 +330,7 @@ make_new_session( + + /* Restore default signal handling ASAP */ + bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); ++ signal(SIGINT, SIG_DFL); + + pid = getpid(); + diff --git a/package/busybox/patches/910-insmod-q-flag.patch b/package/busybox/patches/910-insmod-q-flag.patch new file mode 100644 index 000000000..6002f20f1 --- /dev/null +++ b/package/busybox/patches/910-insmod-q-flag.patch @@ -0,0 +1,33 @@ +--- a/modutils/insmod.c ++++ b/modutils/insmod.c +@@ -139,7 +139,7 @@ int insmod_main(int argc, char **argv) M + int insmod_main(int argc UNUSED_PARAM, char **argv) + { + char *filename; +- int rc; ++ int rc, opt; + + /* Compat note: + * 2.6 style insmod has no options and required filename +@@ -149,10 +149,8 @@ int insmod_main(int argc UNUSED_PARAM, c + * or in $MODPATH. + */ + +- IF_FEATURE_2_4_MODULES( +- getopt32(argv, INSMOD_OPTS INSMOD_ARGS); +- argv += optind - 1; +- ); ++ opt = getopt32(argv, INSMOD_OPTS, NULL, NULL); ++ argv += optind - 1; + + filename = *++argv; + if (!filename) +@@ -163,7 +161,7 @@ int insmod_main(int argc UNUSED_PARAM, c + goto done; + + rc = bb_init_module(g_filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0)); +- if (rc) ++ if (rc && !(opt & INSMOD_OPT_SILENT)) + bb_error_msg("can't insert '%s': %s", filename, moderror(rc)); + free (g_filename); + diff --git a/package/busybox/patches/911-date-k-flag.patch b/package/busybox/patches/911-date-k-flag.patch new file mode 100644 index 000000000..c4f6db4db --- /dev/null +++ b/package/busybox/patches/911-date-k-flag.patch @@ -0,0 +1,83 @@ +--- a/coreutils/date.c ++++ b/coreutils/date.c +@@ -123,6 +123,7 @@ + //usage: IF_FEATURE_DATE_ISOFMT( + //usage: "\n -D FMT Use FMT for -d TIME conversion" + //usage: ) ++//usage: "\n -k Set Kernel timezone from localtime and exit" + //usage: "\n" + //usage: "\nRecognized TIME formats:" + //usage: "\n hh:mm[:ss]" +@@ -135,6 +136,7 @@ + //usage: "Wed Apr 12 18:52:41 MDT 2000\n" + + #include "libbb.h" ++#include + #if ENABLE_FEATURE_DATE_NANO + # include + #endif +@@ -145,8 +147,9 @@ enum { + OPT_UTC = (1 << 2), /* u */ + OPT_DATE = (1 << 3), /* d */ + OPT_REFERENCE = (1 << 4), /* r */ +- OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ +- OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ ++ OPT_KERNELTZ = (1 << 5), /* k */ ++ OPT_TIMESPEC = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ ++ OPT_HINT = (1 << 7) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ + }; + + static void maybe_set_utc(int opt) +@@ -164,12 +167,15 @@ static const char date_longopts[] ALIGN1 + /* "universal\0" No_argument "u" */ + "date\0" Required_argument "d" + "reference\0" Required_argument "r" ++ "set-kernel-tz\0" No_argument "k" + ; + #endif + + int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; + int date_main(int argc UNUSED_PARAM, char **argv) + { ++ time_t tt; ++ struct timezone tz; + struct timespec ts; + struct tm tm_time; + char buf_fmt_dt2str[64]; +@@ -184,7 +190,7 @@ int date_main(int argc UNUSED_PARAM, cha + opt_complementary = "d--s:s--d" + IF_FEATURE_DATE_ISOFMT(":R--I:I--R"); + IF_LONG_OPTS(applet_long_options = date_longopts;) +- opt = getopt32(argv, "Rs:ud:r:" ++ opt = getopt32(argv, "Rs:ud:r:k" + IF_FEATURE_DATE_ISOFMT("I::D:"), + &date_str, &date_str, &filename + IF_FEATURE_DATE_ISOFMT(, &isofmt_arg, &fmt_str2dt)); +@@ -241,6 +247,27 @@ int date_main(int argc UNUSED_PARAM, cha + if (*argv) + bb_show_usage(); + ++ /* Setting of kernel timezone was requested */ ++ if (opt & OPT_KERNELTZ) { ++ tt = time(NULL); ++ localtime_r(&tt, &tm_time); ++ ++ /* workaround warp_clock() on first invocation */ ++ memset(&tz, 0, sizeof(tz)); ++ settimeofday(NULL, &tz); ++ ++ memset(&tz, 0, sizeof(tz)); ++ tz.tz_minuteswest = -(tm_time.tm_gmtoff / 60); ++ ++ if (settimeofday(NULL, &tz)) ++ { ++ bb_perror_msg("can't set kernel time zone"); ++ return EXIT_FAILURE; ++ } ++ ++ return EXIT_SUCCESS; ++ } ++ + /* Now we have parsed all the information except the date format + * which depends on whether the clock is being set or read */ + diff --git a/package/busybox/patches/920-portability.patch b/package/busybox/patches/920-portability.patch new file mode 100644 index 000000000..4e5b9a057 --- /dev/null +++ b/package/busybox/patches/920-portability.patch @@ -0,0 +1,13 @@ +--- a/scripts/kconfig/mconf.c ++++ b/scripts/kconfig/mconf.c +@@ -25,6 +25,10 @@ + #include + #include + ++#ifndef SIGWINCH ++#define SIGWINCH 28 ++#endif ++ + #define LKC_DIRECT_LINK + #include "lkc.h" + diff --git a/package/busybox/patches/950-partial-checksum.patch b/package/busybox/patches/950-partial-checksum.patch new file mode 100644 index 000000000..e595162c6 --- /dev/null +++ b/package/busybox/patches/950-partial-checksum.patch @@ -0,0 +1,87 @@ +diff -ur busybox-1.19.4.orig/networking/udhcp/dhcpc.c busybox-1.19.4/networking/udhcp/dhcpc.c +--- busybox-1.19.4.orig/networking/udhcp/dhcpc.c 2012-09-06 22:33:53.476998721 +0400 ++++ busybox-1.19.4/networking/udhcp/dhcpc.c 2012-09-07 01:09:46.693372304 +0400 +@@ -26,8 +26,8 @@ + #include "dhcpc.h" + + #include +-#include + #include ++#include + + /* struct client_config_t client_config is in bb_common_bufsiz1 */ + +@@ -784,17 +784,41 @@ + static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) + { + int bytes; ++ int nocsum = 0; + struct ip_udp_dhcp_packet packet; + uint16_t check; ++ unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; ++ struct iovec iov = { ++ .iov_base = &packet, ++ .iov_len = sizeof(packet), ++ }; ++ struct msghdr msg = { ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ .msg_control = cmsgbuf, ++ .msg_controllen = sizeof(cmsgbuf), ++ }; ++ struct cmsghdr *cmsg; + + memset(&packet, 0, sizeof(packet)); +- bytes = safe_read(fd, &packet, sizeof(packet)); ++ do { ++ bytes = recvmsg(fd, &msg, 0); ++ } while (bytes < 0 && errno == EINTR); ++ + if (bytes < 0) { + log1("Packet read error, ignoring"); + /* NB: possible down interface, etc. Caller should pause. */ + return bytes; /* returns -1 */ + } + ++ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { ++ if (cmsg->cmsg_level == SOL_PACKET && ++ cmsg->cmsg_type == PACKET_AUXDATA) { ++ struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg); ++ nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY; ++ } ++ } ++ + if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { + log1("Packet is too short, ignoring"); + return -2; +@@ -834,7 +858,7 @@ + packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ + check = packet.udp.check; + packet.udp.check = 0; +- if (check && check != udhcp_checksum(&packet, bytes)) { ++ if (!nocsum && check && check != udhcp_checksum(&packet, bytes)) { + log1("Packet with bad UDP checksum received, ignoring"); + return -2; + } +@@ -880,6 +904,7 @@ + { + int fd; + struct sockaddr_ll sock; ++ int val; + + /* + * Comment: +@@ -946,6 +971,13 @@ + log1("Attached filter to raw socket fd %d", fd); // log? + } + ++ val = 1; ++ if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, &val, ++ sizeof(val)) < 0) { ++ if (errno != ENOPROTOOPT) ++ log1("Failed to set auxiliary packet data for socket fd %d", fd); ++ } ++ + log1("Created raw socket"); + + return fd; -- cgit v1.2.3