From 902d3992922fc8db8495d5fb30a4581711b60c62 Mon Sep 17 00:00:00 2001 From: Alistair Francis <alistair.francis@wdc.com> Date: Wed, 18 Sep 2019 09:28:50 -0700 Subject: time: Use 64 prefix syscall if we have to Some 32-bit architectures no longer have the 32-bit time_t syscalls. Instead they have suffixed syscalls that returns a 64-bit time_t. If the architecture doesn't have the non-suffixed syscall and is using a 64-bit time_t let's use the suffixed syscall instead. This fixes build issues when building for RISC-V 32-bit with 5.1+ kernel headers. If an architecture only supports the suffixed syscalls, but is still using a 32-bit time_t report a compilation error. This avoids us have to deal with converting between 64-bit and 32-bit values. There are currently no architectures where this is the case. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/time.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'libbb') diff --git a/libbb/time.c b/libbb/time.c index cab0ad602..b6fcae28b 100644 --- a/libbb/time.c +++ b/libbb/time.c @@ -257,7 +257,14 @@ char* FAST_FUNC strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) * typically requiring -lrt. We just skip all this mess */ static void get_mono(struct timespec *ts) { +#if defined(__NR_clock_gettime) if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, ts)) +#elif __TIMESIZE == 64 + if (syscall(__NR_clock_gettime64, CLOCK_MONOTONIC, ts)) +#else +# error "We currently don't support architectures without " \ + "the __NR_clock_gettime syscall and 32-bit time_t" +#endif bb_simple_error_msg_and_die("clock_gettime(MONOTONIC) failed"); } unsigned long long FAST_FUNC monotonic_ns(void) -- cgit v1.2.3-55-g6feb From dd4686128290b34d61becaaba88c54d5213f7aa5 Mon Sep 17 00:00:00 2001 From: Martin Lewis <martin.lewis.x84@gmail.com> Date: Sun, 15 Sep 2019 18:13:28 +0200 Subject: libbb: Converted safe_read to safe_write format Changed safe_read to be symmetrical to safe_write, it shall never return EINTR because it calls read multiple times, the error is considered transient. function old new delta safe_read 44 57 +13 Signed-off-by: Martin Lewis <martin.lewis.x84@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/read.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'libbb') diff --git a/libbb/read.c b/libbb/read.c index 5906bc225..a342506a8 100644 --- a/libbb/read.c +++ b/libbb/read.c @@ -12,9 +12,17 @@ ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count) { ssize_t n; - do { + for (;;) { n = read(fd, buf, count); - } while (n < 0 && errno == EINTR); + if (n >= 0 || errno != EINTR) + break; + /* Some callers set errno=0, are upset when they see EINTR. + * Returning EINTR is wrong since we retry read(), + * the "error" was transient. + */ + errno = 0; + /* repeat the read() */ + } return n; } -- cgit v1.2.3-55-g6feb From 7011eca83afc313098f9869eea36742d4506bc02 Mon Sep 17 00:00:00 2001 From: Martin Lewis <martin.lewis.x84@gmail.com> Date: Sun, 15 Sep 2019 18:51:30 +0200 Subject: replace: count_strstr - Handle an edge case where sub is empty If sub is empty, avoids an infinite loop. function old new delta count_strstr 45 63 +18 Signed-off-by: Martin Lewis <martin.lewis.x84@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/replace.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libbb') diff --git a/libbb/replace.c b/libbb/replace.c index a661d96e6..6183d3e6f 100644 --- a/libbb/replace.c +++ b/libbb/replace.c @@ -15,6 +15,10 @@ unsigned FAST_FUNC count_strstr(const char *str, const char *sub) size_t sub_len = strlen(sub); unsigned count = 0; + /* If sub is empty, avoid an infinite loop */ + if (sub_len == 0) + return strlen(str) + 1; + while ((str = strstr(str, sub)) != NULL) { count++; str += sub_len; -- cgit v1.2.3-55-g6feb From 42f454b13b8d972e85acd7f046065ec69af4d206 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Fri, 11 Oct 2019 14:11:44 +0200 Subject: dpkg-deb: work around bogus error message when working with XZ compressed packages function old new delta unpack_xz_stream 2309 2317 +8 bb_full_fd_action 464 472 +8 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- archival/libarchive/decompress_unxz.c | 20 +++++++++++++++++++- archival/libarchive/unxz/xz_stream.h | 2 +- libbb/copyfd.c | 13 ++++++++----- 3 files changed, 28 insertions(+), 7 deletions(-) (limited to 'libbb') diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index f03341384..3dd9bbf49 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c @@ -96,6 +96,24 @@ unpack_xz_stream(transformer_state_t *xstate) */ do { if (membuf[iobuf.in_pos] != 0) { + /* There is more data, but is it XZ data? + * Example: dpkg-deb -f busybox_1.30.1-4_amd64.deb + * reads control.tar.xz "control" file + * inside the ar archive, but tar.xz + * extraction code reaches end of xz data, + * reached this code and reads the beginning + * of data.tar.xz's ar header, which isn't xz data, + * and prints "corrupted data". + * The correct solution is to not read + * past nested archive (to simulate EOF). + * This is a workaround: + */ + if (membuf[iobuf.in_pos] != 0xfd) { + /* It's definitely not a xz signature + * (which is 0xfd,"7zXZ",0x00). + */ + goto end; + } xz_dec_reset(state); goto do_run; } @@ -128,7 +146,7 @@ unpack_xz_stream(transformer_state_t *xstate) break; } } - + end: xz_dec_end(state); free(membuf); diff --git a/archival/libarchive/unxz/xz_stream.h b/archival/libarchive/unxz/xz_stream.h index 66cb5a705..45056e42c 100644 --- a/archival/libarchive/unxz/xz_stream.h +++ b/archival/libarchive/unxz/xz_stream.h @@ -25,7 +25,7 @@ #define STREAM_HEADER_SIZE 12 -#define HEADER_MAGIC "\3757zXZ" +#define HEADER_MAGIC "\375""7zXZ" #define HEADER_MAGIC_SIZE 6 #define FOOTER_MAGIC "YZ" diff --git a/libbb/copyfd.c b/libbb/copyfd.c index ae5c26999..d41fd10f0 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c @@ -18,7 +18,7 @@ * was seen to cause largish delays when user tries to ^C a file copy. * Let's use a saner size. * Note: needs to be >= max(CONFIG_FEATURE_COPYBUF_KB), - * or else "copy to eof" code will use neddlesly short reads. + * or else "copy to eof" code will use needlesly short reads. */ #define SENDFILE_BIGBUF (16*1024*1024) @@ -60,10 +60,13 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) ssize_t rd; if (sendfile_sz) { - rd = sendfile(dst_fd, src_fd, NULL, - size > sendfile_sz ? sendfile_sz : size); - if (rd >= 0) - goto read_ok; + /* dst_fd == -1 is a fake, else... */ + if (dst_fd >= 0) { + rd = sendfile(dst_fd, src_fd, NULL, + size > sendfile_sz ? sendfile_sz : size); + if (rd >= 0) + goto read_ok; + } sendfile_sz = 0; /* do not try sendfile anymore */ } #if CONFIG_FEATURE_COPYBUF_KB > 4 -- cgit v1.2.3-55-g6feb From be5a505d771a77c640acc35ceaa470c80e62f954 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 24 Oct 2019 16:26:55 +0200 Subject: Remove syscall wrappers around clock_gettime, closes 12091 12091 "Direct use of __NR_clock_gettime is not time64-safe". function old new delta runsv_main 1698 1712 +14 startservice 378 383 +5 get_mono 31 25 -6 date_main 932 926 -6 gettimeofday_ns 17 - -17 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 2/2 up/down: 19/-29) Total: -10 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- Makefile.flags | 6 ++++-- coreutils/date.c | 16 +++------------- libbb/time.c | 11 +---------- runit/runsv.c | 11 +---------- 4 files changed, 9 insertions(+), 35 deletions(-) (limited to 'libbb') diff --git a/Makefile.flags b/Makefile.flags index 6f6142cc5..bea464753 100644 --- a/Makefile.flags +++ b/Makefile.flags @@ -129,10 +129,12 @@ endif # fall back to using a temp file: CRYPT_AVAILABLE := $(shell echo 'int main(void){return 0;}' >crypttest.c; $(CC) $(CFLAGS) -lcrypt -o /dev/null crypttest.c >/dev/null 2>&1 && echo "y"; rm crypttest.c) ifeq ($(CRYPT_AVAILABLE),y) -LDLIBS += m crypt +LDLIBS += m rt crypt else -LDLIBS += m +LDLIBS += m rt endif +# libm may be needed for dc, awk, ntpd +# librt may be needed for clock_gettime() # libpam may use libpthread, libdl and/or libaudit. # On some platforms that requires an explicit -lpthread, -ldl, -laudit. diff --git a/coreutils/date.c b/coreutils/date.c index 731241536..f7e9a8d0e 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -33,10 +33,9 @@ //config: Enable option (-I) to output an ISO-8601 compliant //config: date/time string. //config: -//config:# defaults to "no": stat's nanosecond field is a bit non-portable //config:config FEATURE_DATE_NANO //config: bool "Support %[num]N nanosecond format specifier" -//config: default n # syscall(__NR_clock_gettime) or syscall(__NR_clock_gettime64) +//config: default n # stat's nanosecond field is a bit non-portable //config: depends on DATE //config: select PLATFORM_LINUX //config: help @@ -271,17 +270,8 @@ int date_main(int argc UNUSED_PARAM, char **argv) */ #endif } else { -#if ENABLE_FEATURE_DATE_NANO && defined(__NR_clock_gettime) - /* libc has incredibly messy way of doing this, - * typically requiring -lrt. We just skip all this mess */ - syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts); -#elif ENABLE_FEATURE_DATE_NANO && __TIMESIZE == 64 - /* Let's only support the 64 suffix syscalls for 64-bit time_t. - * This simplifies the code for us as we don't need to convert - * between 64-bit and 32-bit. We also don't have a way to - * report overflow errors here. - */ - syscall(__NR_clock_gettime64, CLOCK_REALTIME, &ts); +#if ENABLE_FEATURE_DATE_NANO + clock_gettime(CLOCK_REALTIME, &ts); #else time(&ts.tv_sec); #endif diff --git a/libbb/time.c b/libbb/time.c index b6fcae28b..e66a9cba8 100644 --- a/libbb/time.c +++ b/libbb/time.c @@ -253,18 +253,9 @@ char* FAST_FUNC strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) #define CLOCK_MONOTONIC 1 #endif -/* libc has incredibly messy way of doing this, - * typically requiring -lrt. We just skip all this mess */ static void get_mono(struct timespec *ts) { -#if defined(__NR_clock_gettime) - if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, ts)) -#elif __TIMESIZE == 64 - if (syscall(__NR_clock_gettime64, CLOCK_MONOTONIC, ts)) -#else -# error "We currently don't support architectures without " \ - "the __NR_clock_gettime syscall and 32-bit time_t" -#endif + if (clock_gettime(CLOCK_MONOTONIC, ts)) bb_simple_error_msg_and_die("clock_gettime(MONOTONIC) failed"); } unsigned long long FAST_FUNC monotonic_ns(void) diff --git a/runit/runsv.c b/runit/runsv.c index 737909b0e..36d85101e 100644 --- a/runit/runsv.c +++ b/runit/runsv.c @@ -51,18 +51,9 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #if ENABLE_MONOTONIC_SYSCALL #include <sys/syscall.h> -/* libc has incredibly messy way of doing this, - * typically requiring -lrt. We just skip all this mess */ static void gettimeofday_ns(struct timespec *ts) { -#if defined(__NR_clock_gettime) - syscall(__NR_clock_gettime, CLOCK_REALTIME, ts); -#elif __TIMESIZE == 64 - syscall(__NR_clock_gettime64, CLOCK_REALTIME, ts); -#else -# error "We currently don't support architectures without " \ - "the __NR_clock_gettime syscall and 32-bit time_t" -#endif + clock_gettime(CLOCK_REALTIME, ts); } #else static void gettimeofday_ns(struct timespec *ts) -- cgit v1.2.3-55-g6feb From af7169b4a70eb3f60555ced17a40780f70aaaa5c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Fri, 25 Oct 2019 12:12:22 +0200 Subject: clang/llvm 9 fix - do not eliminate a store to a fake "const" This is *much* better (9 kbytes better) than dropping "*const" optimization trick. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- coreutils/test.c | 2 +- include/libbb.h | 22 +++++++++++++++++++++- libbb/appletlib.c | 2 +- libbb/lineedit.c | 2 +- shell/ash.c | 6 +++--- 5 files changed, 27 insertions(+), 7 deletions(-) (limited to 'libbb') diff --git a/coreutils/test.c b/coreutils/test.c index 868ffbecb..a08986130 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -411,7 +411,7 @@ extern struct test_statics *const test_ptr_to_statics; #define leaving (S.leaving ) #define INIT_S() do { \ - (*(struct test_statics**)&test_ptr_to_statics) = xzalloc(sizeof(S)); \ + (*(struct test_statics**)not_const_pp(&test_ptr_to_statics)) = xzalloc(sizeof(S)); \ barrier(); \ } while (0) #define DEINIT_S() do { \ diff --git a/include/libbb.h b/include/libbb.h index 111d1b790..05a560977 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2153,12 +2153,32 @@ struct globals; * Magic prevents ptr_to_globals from going into rodata. * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */ extern struct globals *const ptr_to_globals; + +#if defined(__clang_major__) && __clang_major__ >= 9 +/* Clang/llvm drops assignment to "constant" storage. Silently. + * Needs serious convincing to not eliminate the store. + */ +static ALWAYS_INLINE void* not_const_pp(const void *p) +{ + void *pp; + __asm__ __volatile__( + "# forget that p points to const" + : /*outputs*/ "=r" (pp) + : /*inputs*/ "0" (p) + ); + return pp; +} +#else +static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; } +#endif + /* At least gcc 3.4.6 on mipsel system needs optimization barrier */ #define barrier() __asm__ __volatile__("":::"memory") #define SET_PTR_TO_GLOBALS(x) do { \ - (*(struct globals**)&ptr_to_globals) = (void*)(x); \ + (*(struct globals**)not_const_pp(&ptr_to_globals)) = (void*)(x); \ barrier(); \ } while (0) + #define FREE_PTR_TO_GLOBALS() do { \ if (ENABLE_FEATURE_CLEAN_UP) { \ free(ptr_to_globals); \ diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 9fa17cfa1..f842e73cc 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -304,7 +304,7 @@ void lbb_prepare(const char *applet IF_FEATURE_INDIVIDUAL(, char **argv)) { #ifdef __GLIBC__ - (*(int **)&bb_errno) = __errno_location(); + (*(int **)not_const_pp(&bb_errno)) = __errno_location(); barrier(); #endif applet_name = applet; diff --git a/libbb/lineedit.c b/libbb/lineedit.c index fbabc6c12..b1ec52b88 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -203,7 +203,7 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics; #define delbuf (S.delbuf ) #define INIT_S() do { \ - (*(struct lineedit_statics**)&lineedit_ptr_to_statics) = xzalloc(sizeof(S)); \ + (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ barrier(); \ cmdedit_termw = 80; \ IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \ diff --git a/shell/ash.c b/shell/ash.c index c5588ea66..4b5eafa7c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -489,7 +489,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; #define random_gen (G_misc.random_gen ) #define backgndpid (G_misc.backgndpid ) #define INIT_G_misc() do { \ - (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \ + (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ barrier(); \ curdir = nullstr; \ physdir = nullstr; \ @@ -1542,7 +1542,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack; #define g_stacknleft (G_memstack.g_stacknleft) #define stackbase (G_memstack.stackbase ) #define INIT_G_memstack() do { \ - (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \ + (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \ barrier(); \ g_stackp = &stackbase; \ g_stacknxt = stackbase.space; \ @@ -2165,7 +2165,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; #endif #define INIT_G_var() do { \ unsigned i; \ - (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \ + (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \ barrier(); \ for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ varinit[i].flags = varinit_data[i].flags; \ -- cgit v1.2.3-55-g6feb From f39a71817ead331b664bc658ac26dec4ec3b75bc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Fri, 25 Oct 2019 17:40:57 +0200 Subject: read_key(): placate "warning: shifting a negative signed value is undefined" Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/read_key.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/read_key.c b/libbb/read_key.c index 951786869..03b7da656 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c @@ -259,7 +259,8 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) buffer[-1] = 0; /* Pack into "1 <row15bits> <col16bits>" 32-bit sequence */ - col |= (((-1 << 15) | row) << 16); + row |= ((unsigned)(-1) << 15); + col |= (row << 16); /* Return it in high-order word */ return ((int64_t) col << 32) | (uint32_t)KEYCODE_CURSOR_POS; } -- cgit v1.2.3-55-g6feb From d3539be8f27b8cbfdfee460fe08299158f08bcd9 Mon Sep 17 00:00:00 2001 From: Alistair Francis <alistair.francis@wdc.com> Date: Tue, 19 Nov 2019 13:06:40 +0100 Subject: Remove stime() function calls stime() has been deprecated in glibc 2.31 and replaced with clock_settime(). Let's replace the stime() function calls with clock_settime() in preperation. function old new delta rdate_main 197 224 +27 clock_settime - 27 +27 date_main 926 941 +15 stime 37 - -37 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 2/0 up/down: 69/-37) Total: 32 bytes Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- coreutils/date.c | 6 +++++- libbb/missing_syscalls.c | 8 -------- util-linux/rdate.c | 8 ++++++-- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'libbb') diff --git a/coreutils/date.c b/coreutils/date.c index f7e9a8d0e..b9b7fd2cb 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -276,6 +276,9 @@ int date_main(int argc UNUSED_PARAM, char **argv) time(&ts.tv_sec); #endif } +#if !ENABLE_FEATURE_DATE_NANO + ts.tv_nsec = 0; +#endif localtime_r(&ts.tv_sec, &tm_time); /* If date string is given, update tm_time, and maybe set date */ @@ -298,9 +301,10 @@ int date_main(int argc UNUSED_PARAM, char **argv) if (date_str[0] != '@') tm_time.tm_isdst = -1; ts.tv_sec = validate_tm_time(date_str, &tm_time); + ts.tv_nsec = 0; /* if setting time, set it */ - if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) { + if ((opt & OPT_SET) && clock_settime(CLOCK_REALTIME, &ts) < 0) { bb_simple_perror_msg("can't set date"); } } diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c index 87cf59b3d..dc40d9155 100644 --- a/libbb/missing_syscalls.c +++ b/libbb/missing_syscalls.c @@ -15,14 +15,6 @@ pid_t getsid(pid_t pid) return syscall(__NR_getsid, pid); } -int stime(const time_t *t) -{ - struct timeval tv; - tv.tv_sec = *t; - tv.tv_usec = 0; - return settimeofday(&tv, NULL); -} - int sethostname(const char *name, size_t len) { return syscall(__NR_sethostname, name, len); diff --git a/util-linux/rdate.c b/util-linux/rdate.c index 41aade5ea..bb1dc519a 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c @@ -95,9 +95,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv) if (!(flags & 2)) { /* no -p (-s may be present) */ if (time(NULL) == remote_time) bb_simple_error_msg("current time matches remote time"); - else - if (stime(&remote_time) < 0) + else { + struct timespec ts; + ts.tv_sec = remote_time; + ts.tv_nsec = 0; + if (clock_settime(CLOCK_REALTIME, &ts) < 0) bb_simple_perror_msg_and_die("can't set time of day"); + } } if (flags != 1) /* not lone -s */ -- cgit v1.2.3-55-g6feb