From d4e4fdb5ce5ccc067b3d35d877f7a7d978869517 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Jul 2017 21:31:16 +0200 Subject: fixes for bugs found by make_single_applets.sh Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/libbb.h b/include/libbb.h index 9b72c97be..557978e66 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -778,6 +778,8 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags, uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; +/* 0 if argv[0] is NULL: */ +unsigned string_array_len(char **argv) FAST_FUNC; void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; -- cgit v1.2.3-55-g6feb From a8cf9c5a3ffd1601872d1ab14c5be00fde29209c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Jul 2017 18:49:24 +0200 Subject: libbb: new function bb_getgroups() - allocating wrapper around getgroups() function old new delta bb_getgroups - 111 +111 nexpr 843 757 -86 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/1 up/down: 111/-86) Total: 25 bytes Signed-off-by: Denys Vlasenko --- coreutils/test.c | 33 +++++++-------------------------- include/libbb.h | 9 +++++++++ libbb/bb_getgroups.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 26 deletions(-) create mode 100644 libbb/bb_getgroups.c (limited to 'include') diff --git a/coreutils/test.c b/coreutils/test.c index edc625f57..edcf2a2d8 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -563,26 +563,11 @@ static int binop(void) /*return 1; - NOTREACHED */ } - static void initialize_group_array(void) { - int n; - - /* getgroups may be expensive, try to use it only once */ - ngroups = 32; - do { - /* FIXME: ash tries so hard to not die on OOM, - * and we spoil it with just one xrealloc here */ - /* We realloc, because test_main can be entered repeatedly by shell. - * Testcase (ash): 'while true; do test -x some_file; done' - * and watch top. (some_file must have owner != you) */ - n = ngroups; - group_array = xrealloc(group_array, n * sizeof(gid_t)); - ngroups = getgroups(n, group_array); - } while (ngroups > n); + group_array = bb_getgroups(&ngroups, NULL); } - /* Return non-zero if GID is one that we have in our groups list. */ //XXX: FIXME: duplicate of existing libbb function? // see toplevel TODO file: @@ -610,14 +595,10 @@ static int is_a_group_member(gid_t gid) /* Do the same thing access(2) does, but use the effective uid and gid, and don't make the mistake of telling root that any file is executable. */ -static int test_eaccess(char *path, int mode) +static int test_eaccess(struct stat *st, int mode) { - struct stat st; unsigned int euid = geteuid(); - if (stat(path, &st) < 0) - return -1; - if (euid == 0) { /* Root can read or write any file. */ if (mode != X_OK) @@ -625,16 +606,16 @@ static int test_eaccess(char *path, int mode) /* Root can execute any file that has any one of the execute * bits set. */ - if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) + if (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) return 0; } - if (st.st_uid == euid) /* owner */ + if (st->st_uid == euid) /* owner */ mode <<= 6; - else if (is_a_group_member(st.st_gid)) + else if (is_a_group_member(st->st_gid)) mode <<= 3; - if (st.st_mode & mode) + if (st->st_mode & mode) return 0; return -1; @@ -667,7 +648,7 @@ static int filstat(char *nm, enum token mode) i = W_OK; if (mode == FILEX) i = X_OK; - return test_eaccess(nm, i) == 0; + return test_eaccess(&s, i) == 0; } if (is_file_type(mode)) { if (mode == FILREG) diff --git a/include/libbb.h b/include/libbb.h index 557978e66..1c9de3af0 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1033,6 +1033,15 @@ void die_if_bad_username(const char* name) FAST_FUNC; #else #define die_if_bad_username(name) ((void)(name)) #endif +/* + * Returns (-1) terminated malloced result of getgroups(). + * Reallocs group_array (useful for repeated calls). + * ngroups is an initial size of array. It is rounded up to 32 for realloc. + * ngroups is updated on return. + * ngroups can be NULL: bb_getgroups(NULL, NULL) is valid usage. + * Dies on errors (on Linux, only xrealloc can cause this, not internal getgroups call). + */ +gid_t *bb_getgroups(int *ngroups, gid_t *group_array) FAST_FUNC; #if ENABLE_FEATURE_UTMP void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname); diff --git a/libbb/bb_getgroups.c b/libbb/bb_getgroups.c new file mode 100644 index 000000000..59ae53738 --- /dev/null +++ b/libbb/bb_getgroups.c @@ -0,0 +1,47 @@ +/* + * Utility routines. + * + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ + +//kbuild:lib-y += bb_getgroups.o + +#include "libbb.h" + +gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array) +{ + int n = ngroups ? *ngroups : 0; + + /* getgroups may be a bit expensive, try to use it only once */ + if (n < 32) + n = 32; + + for (;;) { +// FIXME: ash tries so hard to not die on OOM (when we are called from test), +// and we spoil it with just one xrealloc here + group_array = xrealloc(group_array, (n+1) * sizeof(group_array[0])); + n = getgroups(n, group_array); + /* + * If buffer is too small, kernel does not return new_n > n. + * It returns -1 and EINVAL: + */ + if (n >= 0) { + /* Terminator for bb_getgroups(NULL, NULL) usage */ + group_array[n] = (gid_t) -1; + break; + } + if (errno == EINVAL) { /* too small? */ + /* This is the way to ask kernel how big the array is */ + n = getgroups(0, group_array); + continue; + } + /* Some other error (should never happen on Linux) */ + bb_perror_msg_and_die("getgroups"); + } + + if (ngroups) + *ngroups = n; + return group_array; +} -- cgit v1.2.3-55-g6feb From 69a5ec9dccfd183cdf6bee7b994336670755cd47 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 7 Jul 2017 19:08:56 +0200 Subject: main: fix the case where user has "halt" as login shell. Closes 9986 halt::0:0::/:/sbin/halt function old new delta run_applet_and_exit 748 751 +3 run_applet_no_and_exit 467 459 -8 Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/appletlib.c | 10 +++++++--- libbb/vfork_daemon_rexec.c | 2 +- shell/ash.c | 2 +- shell/hush.c | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/libbb.h b/include/libbb.h index 1c9de3af0..0317c7d6a 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1117,7 +1117,7 @@ int spawn_and_wait(char **argv) FAST_FUNC; int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; #ifndef BUILD_INDIVIDUAL extern int find_applet_by_name(const char *name) FAST_FUNC; -extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC; +extern void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_FUNC; #endif /* Helpers for daemonization. diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 2dea2b43a..df6584978 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -877,13 +877,17 @@ static int busybox_main(char **argv) # endif # if NUM_APPLETS > 0 -void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) +void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) { int argc = string_array_len(argv); /* Reinit some shared global data */ xfunc_error_retval = EXIT_FAILURE; - applet_name = bb_get_last_path_component_nostrip(argv[0]); + /* + * We do not use argv[0]: do not want to repeat massaging of + * "-/sbin/halt" -> "halt", for example. + */ + applet_name = name; /* Special case. POSIX says "test --help" * should be no different from e.g. "test --foo". @@ -927,7 +931,7 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv) { int applet = find_applet_by_name(name); if (applet >= 0) - run_applet_no_and_exit(applet, argv); + run_applet_no_and_exit(applet, name, argv); } # endif diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 2695f99ee..576534ee5 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -180,7 +180,7 @@ int FAST_FUNC spawn_and_wait(char **argv) * as of yet (and that should probably always stay true). */ /* xfunc_error_retval and applet_name are init by: */ - run_applet_no_and_exit(a, argv); + run_applet_no_and_exit(a, argv[0], argv); } # endif } diff --git a/shell/ash.c b/shell/ash.c index b7635a823..8c2098dd9 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7717,7 +7717,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** clearenv(); while (*envp) putenv(*envp++); - run_applet_no_and_exit(applet_no, argv); + run_applet_no_and_exit(applet_no, cmd, argv); } /* re-exec ourselves with the new arguments */ execve(bb_busybox_exec_path, argv, envp); diff --git a/shell/hush.c b/shell/hush.c index 4ba6b3fdd..cf6d8cd9f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7063,7 +7063,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, /* Do not leak open fds from opened script files etc */ close_all_FILE_list(); debug_printf_exec("running applet '%s'\n", argv[0]); - run_applet_no_and_exit(a, argv); + run_applet_no_and_exit(a, argv[0], argv); } # endif /* Re-exec ourselves */ -- cgit v1.2.3-55-g6feb From 2c1258c620c5847649367394439cc10d0331d211 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 15 Jul 2017 20:22:25 +0200 Subject: Move get_unaligned_le32() macros to platform.h Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_unxz.c | 16 +++++++++++----- include/platform.h | 6 ++++++ networking/tls_aes.c | 4 ---- 3 files changed, 17 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index cd32cc745..350e5358a 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c @@ -27,11 +27,17 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) return ~crc32_block_endian0(~crc, buf, size, global_crc32_table); } -/* We use arch-optimized unaligned accessors */ -#define get_unaligned_le32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_LE32(v); }) -#define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); }) -#define put_unaligned_le32(val, buf) move_to_unaligned32(buf, SWAP_LE32(val)) -#define put_unaligned_be32(val, buf) move_to_unaligned32(buf, SWAP_BE32(val)) +/* We use arch-optimized unaligned fixed-endian accessors. + * They have been moved to libbb (proved to be useful elsewhere as well), + * just check that we have them defined: + */ +#if !defined(get_unaligned_le32) \ + || !defined(get_unaligned_be32) \ + || !defined(put_unaligned_le32) \ + || !defined(put_unaligned_be32) +# error get_unaligned_le32 accessors are not defined +#endif +#define get_le32(p) (*(uint32_t*)(p)) #include "unxz/xz_dec_bcj.c" #include "unxz/xz_dec_lzma2.c" diff --git a/include/platform.h b/include/platform.h index 6c7d03dc7..8210e5c49 100644 --- a/include/platform.h +++ b/include/platform.h @@ -247,6 +247,12 @@ typedef uint64_t bb__aliased_uint64_t FIX_ALIASING; } while (0) #endif +/* Unaligned, fixed-endian accessors */ +#define get_unaligned_le32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_LE32(v); }) +#define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); }) +#define put_unaligned_le32(val, buf) move_to_unaligned32(buf, SWAP_LE32(val)) +#define put_unaligned_be32(val, buf) move_to_unaligned32(buf, SWAP_BE32(val)) + /* ---- Size-saving "small" ints (arch-dependent) ----------- */ diff --git a/networking/tls_aes.c b/networking/tls_aes.c index 6992f1c90..c137442e9 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c @@ -40,10 +40,6 @@ */ #include "tls.h" -/* TODO: grep for this and move to libbb */ -#define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); }) - - // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM // The numbers below can be computed dynamically trading ROM for RAM - // This can be useful in (embedded) bootloader applications, where ROM is often limited. -- cgit v1.2.3-55-g6feb