From vda.linux at googlemail.com Sun Jul 3 19:44:27 2022 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Sun, 3 Jul 2022 21:44:27 +0200 Subject: [PATCH] lineedit: get PWD from ash In-Reply-To: <62baf6d1.LtQJ7QN7pNHEUtas%rmy@pobox.com> References: <62baf6d1.LtQJ7QN7pNHEUtas%rmy@pobox.com> Message-ID: Applied, thank you. On Tue, Jun 28, 2022 at 2:46 PM Ron Yorston wrote: > > The line editing code and ash disagree when the current directory > is changed to a symbolic link: > > ~ $ mkdir real > ~ $ ln -s real link > ~ $ cd link > ~/real $ pwd > /home/rmyf36/link > > Note the prompt says we're in ~/real. Bash does: > > [rmy at random ~]$ cd link > [rmy at random link]$ pwd > /home/rmyf36/link > > Ash uses the name supplied by the user while the line editing code > calls getcwd(3). The discrepancy can be avoided by fetching the > value of PWD from ash. > > Hush (incorrectly?) calls getcwd(3) when the directory is changed > so there's no disagreement with the line editing code. > > function old new delta > parse_and_put_prompt 921 904 -17 > > Signed-off-by: Ron Yorston > --- > libbb/lineedit.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/libbb/lineedit.c b/libbb/lineedit.c > index b685399f9..27b5ef30e 100644 > --- a/libbb/lineedit.c > +++ b/libbb/lineedit.c > @@ -2035,7 +2035,13 @@ static void parse_and_put_prompt(const char *prmt_ptr) > case 'W': /* basename of cur dir */ > if (!cwd_buf) { > const char *home; > +#if ENABLE_SHELL_ASH > + cwd_buf = state->sh_get_var ? > + xstrdup(state->sh_get_var("PWD")) : > + xrealloc_getcwd_or_warn(NULL); > +#else > cwd_buf = xrealloc_getcwd_or_warn(NULL); > +#endif > if (!cwd_buf) > cwd_buf = (char *)bb_msg_unknown; > else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { > -- > 2.36.1 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From ludwig.nussel at suse.de Mon Jul 11 09:28:07 2022 From: ludwig.nussel at suse.de (Ludwig Nussel) Date: Mon, 11 Jul 2022 11:28:07 +0200 Subject: [PATCH 1/2] rpm: query installed packages Message-ID: <20220711092808.1714-1-ludwig.nussel@suse.de> Dump original package header into /usr/lib/sysimage/rpm-headers when installing packages. Querying installed packages becomes trivial with that. No separate DB needed. PoC of a similar thing in original rpm: https://github.com/rpm-software-management/rpm/pull/1959 Signed-off-by: Ludwig Nussel --- archival/rpm.c | 85 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 13 deletions(-) diff --git a/archival/rpm.c b/archival/rpm.c index af8db99a6..a53a3e7bf 100644 --- a/archival/rpm.c +++ b/archival/rpm.c @@ -44,6 +44,7 @@ #define TAG_PACKAGER 1015 #define TAG_GROUP 1016 #define TAG_URL 1020 +#define TAG_ARCH 1022 #define TAG_PREIN 1023 #define TAG_POSTIN 1024 #define TAG_FILEFLAGS 1037 @@ -62,6 +63,8 @@ #define RPMFILE_CONFIG (1 << 0) #define RPMFILE_DOC (1 << 1) +#define HEADER_DIR "/usr/lib/sysimage/rpm-headers" + enum rpm_functions_e { rpm_query = 1, rpm_install = 2, @@ -69,7 +72,8 @@ enum rpm_functions_e { rpm_query_package = 8, rpm_query_list = 16, rpm_query_list_doc = 32, - rpm_query_list_config = 64 + rpm_query_list_config = 64, + rpm_query_all = 128, }; typedef struct { @@ -321,17 +325,44 @@ static void extract_cpio(int fd, const char *source_rpm) continue; } +static void install_header(int rpm_fd) +{ + int fd; + off_t payloadstart; + char* path = xasprintf("%s/%s-%s-%s.%s.rpm", HEADER_DIR, + rpm_getstr0(TAG_NAME), rpm_getstr0(TAG_VERSION), + rpm_getstr0(TAG_RELEASE), rpm_getstr0(TAG_ARCH)); + /* hack to avoid copy */ + path[strlen(HEADER_DIR)] = 0; + bb_make_directory(path, 0755, FILEUTILS_RECUR); + path[strlen(HEADER_DIR)] = '/'; + + payloadstart = xlseek(rpm_fd, 0, SEEK_CUR); + xlseek(rpm_fd, 0, SEEK_SET); + + fd = xopen(path, O_WRONLY|O_CREAT|O_EXCL); + bb_copyfd_exact_size(rpm_fd, fd, payloadstart); + close(fd); + if (payloadstart != xlseek(rpm_fd, 0, SEEK_CUR)) { + unlink(path); + bb_error_msg_and_die("failed to write header"); + } +} + //usage:#define rpm_trivial_usage //usage: "-i PACKAGE.rpm; rpm -qp[ildc] PACKAGE.rpm" //usage:#define rpm_full_usage "\n\n" //usage: "Manipulate RPM packages\n" //usage: "\nCommands:" //usage: "\n -i Install package" -//usage: "\n -qp Query package" -//usage: "\n -qpi Show information" -//usage: "\n -qpl List contents" -//usage: "\n -qpd List documents" -//usage: "\n -qpc List config files" +//usage: "\n -q Query package" +//usage: "\n\nQuery Options:" +//usage: "\n -p Query package file" +//usage: "\n -a Query all installed packages" +//usage: "\n -i Show information" +//usage: "\n -l List contents" +//usage: "\n -d List documents" +//usage: "\n -c List config files" /* RPM version 4.13.0.1: * Unlike -q, -i seems to imply -p: -i, -ip and -pi work the same. @@ -356,11 +387,13 @@ int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int rpm_main(int argc, char **argv) { int opt, func = 0; + struct dirent *ent; + DIR* rpms = NULL; INIT_G(); INIT_PAGESIZE(G.pagesize); - while ((opt = getopt(argc, argv, "iqpldc")) != -1) { + while ((opt = getopt(argc, argv, "iqpldca")) != -1) { switch (opt) { case 'i': /* First arg: Install mode, with q: Information */ if (!func) func = rpm_install; @@ -384,21 +417,44 @@ int rpm_main(int argc, char **argv) func |= rpm_query_list; func |= rpm_query_list_config; break; + case 'a': /* query all packages */ + func |= rpm_query_all; + break; default: bb_show_usage(); } } argv += optind; //argc -= optind; - if (!argv[0]) { + if (!(func & rpm_query_all) && !argv[0]) { bb_show_usage(); } + if (func & rpm_query && (func | rpm_query_package) != func ) + rpms = xopendir(HEADER_DIR); + for (;;) { int rpm_fd; const char *source_rpm; - rpm_fd = rpm_gettags(*argv); + /* query installed package */ + if (func & rpm_query && (func | rpm_query_package) != func ) { + char* path = NULL; + ent = readdir(rpms); + if (!ent) + break; + if (DOT_OR_DOTDOT(ent->d_name)) + continue; /* . or .. */ + path = concat_path_file(HEADER_DIR, ent->d_name); + rpm_fd = rpm_gettags(path); + free(path); + if (!(func & rpm_query_all) && strcmp(rpm_getstr0(TAG_NAME), *argv)) { + munmap(G.map, G.mapsize); + free(G.mytags); + continue; + } + } else + rpm_fd = rpm_gettags(*argv); print_all_tags(); source_rpm = rpm_getstr0(TAG_SOURCERPM); @@ -406,6 +462,7 @@ int rpm_main(int argc, char **argv) if (func & rpm_install) { /* -i (and not -qi) */ + install_header(rpm_fd); /* Backup any config files */ loop_through_files(TAG_BASENAMES, fileaction_dobackup); /* Extact the archive */ @@ -414,8 +471,8 @@ int rpm_main(int argc, char **argv) loop_through_files(TAG_BASENAMES, fileaction_setowngrp); } else - if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) { - /* -qp */ + if (func & rpm_query) { + /* -q */ if (!(func & (rpm_query_info|rpm_query_list))) { /* If just a straight query, just give package name */ @@ -481,12 +538,14 @@ int rpm_main(int argc, char **argv) /* Unsupported (help text shows what we support) */ bb_show_usage(); } - if (!*++argv) - break; munmap(G.map, G.mapsize); free(G.mytags); close(rpm_fd); + if (!(func & rpm_query_all) && !*++argv) + break; } + if (rpms) + closedir(rpms); return 0; } -- 2.36.1 From ludwig.nussel at suse.de Mon Jul 11 09:28:08 2022 From: ludwig.nussel at suse.de (Ludwig Nussel) Date: Mon, 11 Jul 2022 11:28:08 +0200 Subject: [PATCH 2/2] rpm: print arch for rpm -q too In-Reply-To: <20220711092808.1714-1-ludwig.nussel@suse.de> References: <20220711092808.1714-1-ludwig.nussel@suse.de> Message-ID: <20220711092808.1714-2-ludwig.nussel@suse.de> That's what original rpm also does by default Signed-off-by: Ludwig Nussel --- archival/rpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/archival/rpm.c b/archival/rpm.c index a53a3e7bf..3799e3752 100644 --- a/archival/rpm.c +++ b/archival/rpm.c @@ -476,7 +476,8 @@ int rpm_main(int argc, char **argv) if (!(func & (rpm_query_info|rpm_query_list))) { /* If just a straight query, just give package name */ - printf("%s-%s-%s\n", rpm_getstr0(TAG_NAME), rpm_getstr0(TAG_VERSION), rpm_getstr0(TAG_RELEASE)); + printf("%s-%s-%s.%s\n", rpm_getstr0(TAG_NAME), rpm_getstr0(TAG_VERSION), + rpm_getstr0(TAG_RELEASE), rpm_getstr0(TAG_ARCH)); } if (func & rpm_query_info) { /* Do the nice printout */ -- 2.36.1 From vda.linux at googlemail.com Mon Jul 11 15:44:47 2022 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Mon, 11 Jul 2022 17:44:47 +0200 Subject: [PATCH v2 1/2] awk: fix use after free (CVE-2022-30065) In-Reply-To: <20220629114957.58993faa@ncopa-desktop.lan> References: <20220607195627.1665-1-ncopa@alpinelinux.org> <20220617154535.24188-1-ncopa@alpinelinux.org> <20220629114957.58993faa@ncopa-desktop.lan> Message-ID: On Wed, Jun 29, 2022 at 11:50 AM Natanael Copa wrote: > Denys, > > This fix passes `./runtest awk`. We have used this fix in Alpine Linux > edge (development branch) for a week now and as far I know, there have > been no issues due to this. > > Can you please have another look? And push it to the stable branch if > possible. Sorry for the delay. I'm applying it to current git. Let's not push it to older stable branches, it's not "stable" From vda.linux at googlemail.com Wed Jul 13 11:16:39 2022 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Wed, 13 Jul 2022 13:16:39 +0200 Subject: [PATCH] udhcpc: add support for sending DHCPINFORM requests In-Reply-To: References: Message-ID: Apologies for the delay. On Wed, Apr 20, 2022 at 8:35 PM Sinan Kaya wrote: > From b906997217b363c459fdbd2824bfe6c5ac69607e Mon Sep 17 00:00:00 2001 > From: Sinan Kaya > Date: Tue, 19 Apr 2022 13:47:19 +0000 > Subject: [PATCH] udhcpc: add support for sending DHCPINFORM requests > > It is useful for applications to be able to query DHCP options > without renewing IP address. I would like a more extended information. Imagine someone who never needed to do this before. Explain to them what would happen when udhcpc is run with -I option. How would DHCP handshake change? Give a real-world example (say, one based on your situation which prompted you to make this patch). Give an example where -e IP is useful. Maybe give references to RFCs which document DHCPINFORM usage. > /* Broadcast a DHCP request message */ > /* RFC 2131 3.1 paragraph 3: > - * "The client _broadcasts_ a DHCPREQUEST message..." > + * "The client _broadcasts_ a DHCPREQUEST/INFORM message..." Incorrect. That's not what RFC 2131 3.1 paragraph 3 says. > */ > /* NOINLINE: limit stack usage in caller */ > -static NOINLINE int send_select(uint32_t server, uint32_t requested) > +static NOINLINE int send_select(uint32_t server, uint32_t requested, > int inform) > { > struct dhcp_packet packet; > struct in_addr temp_addr; > char server_str[sizeof("255.255.255.255")]; > + const char *direction; > > /* > * RFC 2131 4.3.2 DHCPREQUEST message > @@ -766,11 +771,12 @@ static NOINLINE int send_select(uint32_t server, > uint32_t requested) > /* Fill in: op, htype, hlen, cookie, chaddr fields, > * xid field, message type option: > */ > - init_packet(&packet, DHCPREQUEST); > + init_packet(&packet, inform ? DHCPINFORM: DHCPREQUEST); > > udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); > > - udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); > + if (server) > + udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); Do you mean, if server is not specified, SERVER_ID may be omitted? Should be omitted? Should this change be made regardless of DHCPINFORM support? > > /* Add options: maxsize, > * "param req" option according to -O, options specified with -x > @@ -780,11 +786,19 @@ static NOINLINE int send_select(uint32_t server, > uint32_t requested) > temp_addr.s_addr = server; > strcpy(server_str, inet_ntoa(temp_addr)); > temp_addr.s_addr = requested; > - bb_info_msg("broadcasting select for %s, server %s", > - inet_ntoa(temp_addr), > - server_str > + if (server) > + direction = "unicasting"; > + else > + direction = "broadcasting"; > + > + bb_info_msg("%s select for %s, server %s", > + direction, > + inet_ntoa(temp_addr), > + server_str > ); RFC 2131 3.1 paragraph 3 says: "The client broadcasts a DHCPREQUEST message". Always. Even if server-id is known. > - return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); > + > + // return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); > + return bcast_or_ucast(&packet, requested, server); > } > > /* Unicast or broadcast a DHCP renew message */ > @@ -1161,9 +1175,9 @@ static void client_background(void) > //usage:# define IF_UDHCP_VERBOSE(...) > //usage:#endif > //usage:#define udhcpc_trivial_usage > -//usage: > "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" > [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" > +//usage: > "[-fbq"IF_UDHCP_VERBOSE("v")"RBI]"IF_FEATURE_UDHCPC_ARPING(" > [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" > //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s > PROG] [-p PIDFILE]\n" > -//usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... > [-O OPT]..." > +//usage: " [-oC] [-r IP] [-e IP] [-V VENDOR] [-F NAME] [-x > OPT:VAL]... [-O OPT]..." > //usage:#define udhcpc_full_usage "\n" > //usage: "\n -i IFACE Interface to use (default > "CONFIG_UDHCPC_DEFAULT_INTERFACE")" > //usage: IF_FEATURE_UDHCP_PORT( > @@ -1172,6 +1186,7 @@ static void client_background(void) > //usage: "\n -s PROG Run PROG at DHCP events (default > "CONFIG_UDHCPC_DEFAULT_SCRIPT")" > //usage: "\n -p FILE Create pidfile" > //usage: "\n -B Request broadcast replies" > +//usage: "\n -I Request using inform" This barely explains anything. > +//usage: "\n -e IP Request this server IP address" This is not correct. We do not "request server IPs". We send requests to servers (sometimes by unicasting to their IPs, but usually via broadcast). > + > + if (opt & OPT_I) > + use_inform = 1; Why do you need to have use_inform variable when (opt & OPT_I) works just as well? From radoslav.kolev at suse.com Thu Jul 14 14:00:17 2022 From: radoslav.kolev at suse.com (Radoslav Kolev) Date: Thu, 14 Jul 2022 17:00:17 +0300 Subject: [PATCH] examples/udhcp/simple.script: use ip to delete routes, fix bashism Message-ID: <20220714140017.13227-1-radoslav.kolev@suse.com> The script depended on the route command being available to set the default route. It also used a Bash extension for incrementing the metric value. Signed-off-by: Radoslav Kolev --- examples/udhcp/simple.script | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/examples/udhcp/simple.script b/examples/udhcp/simple.script index f079ec8b8..0963f7665 100755 --- a/examples/udhcp/simple.script +++ b/examples/udhcp/simple.script @@ -35,7 +35,13 @@ case "$1" in if [ -n "$router" ] ; then echo "Deleting routers" - while route del default gw 0.0.0.0 dev $interface ; do + while + if command -v ip >/dev/null; then + ip route del default dev $interface + else + route del default gw 0.0.0.0 dev $interface + fi + do : done @@ -49,7 +55,12 @@ case "$1" in # Used in datacenters, avoids the need for private ip-addresses between two hops. ip route add $i dev $interface fi - route add default gw $i dev $interface metric $((metric++)) + if command -v ip >/dev/null; then + ip route add default via $i dev $interface metric $metric + else + route add default gw $i dev $interface metric $metric + fi + metric=$((metric + 1)) done fi -- 2.26.2 From radoslav.kolev at suse.com Tue Jul 19 15:53:30 2022 From: radoslav.kolev at suse.com (Radoslav Kolev) Date: Tue, 19 Jul 2022 18:53:30 +0300 Subject: [PATCH 0/2] Fix CVE-2022-28391 Message-ID: <20220719155332.18440-1-radoslav.kolev@suse.com> The following two patches fix CVE-2022-2839 preventing netstat, traceroute and nslookup from sending escape sequences to the terminal. Note that the problem is only reproducible when using musl libc, but not with glibc. More information can be found at: https://gitlab.alpinelinux.org/alpine/aports/-/issues/13661 Ariadne Conill (2): libbb: sockaddr2str: ensure only printable characters are returned for the hostname part nslookup: sanitize all printed strings with printable_string libbb/xconnect.c | 5 +++-- networking/nslookup.c | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) -- 2.26.2 From radoslav.kolev at suse.com Tue Jul 19 15:53:32 2022 From: radoslav.kolev at suse.com (Radoslav Kolev) Date: Tue, 19 Jul 2022 18:53:32 +0300 Subject: [PATCH 2/2] nslookup: sanitize all printed strings with printable_string In-Reply-To: <20220719155332.18440-1-radoslav.kolev@suse.com> References: <20220719155332.18440-1-radoslav.kolev@suse.com> Message-ID: <20220719155332.18440-3-radoslav.kolev@suse.com> From: Ariadne Conill Otherwise, terminal sequences can be injected, which enables various terminal injection attacks from DNS results. CVE: CVE-2022-28391 Signed-off-by: Ariadne Conill Tested-by: Radoslav Kolev --- networking/nslookup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/networking/nslookup.c b/networking/nslookup.c index 6da97baf4..4bdcde1b8 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c @@ -407,7 +407,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) //printf("Unable to uncompress domain: %s\n", strerror(errno)); return -1; } - printf(format, ns_rr_name(rr), dname); + printf(format, ns_rr_name(rr), printable_string(dname)); break; case ns_t_mx: @@ -422,7 +422,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) //printf("Cannot uncompress MX domain: %s\n", strerror(errno)); return -1; } - printf("%s\tmail exchanger = %d %s\n", ns_rr_name(rr), n, dname); + printf("%s\tmail exchanger = %d %s\n", ns_rr_name(rr), n, printable_string(dname)); break; case ns_t_txt: @@ -434,7 +434,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) if (n > 0) { memset(dname, 0, sizeof(dname)); memcpy(dname, ns_rr_rdata(rr) + 1, n); - printf("%s\ttext = \"%s\"\n", ns_rr_name(rr), dname); + printf("%s\ttext = \"%s\"\n", ns_rr_name(rr), printable_string(dname)); } break; @@ -454,7 +454,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) } printf("%s\tservice = %u %u %u %s\n", ns_rr_name(rr), - ns_get16(cp), ns_get16(cp + 2), ns_get16(cp + 4), dname); + ns_get16(cp), ns_get16(cp + 2), ns_get16(cp + 4), printable_string(dname)); break; case ns_t_soa: @@ -483,7 +483,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) return -1; } - printf("\tmail addr = %s\n", dname); + printf("\tmail addr = %s\n", printable_string(dname)); cp += n; printf("\tserial = %lu\n", ns_get32(cp)); -- 2.26.2 From radoslav.kolev at suse.com Tue Jul 19 15:53:31 2022 From: radoslav.kolev at suse.com (Radoslav Kolev) Date: Tue, 19 Jul 2022 18:53:31 +0300 Subject: [PATCH 1/2] libbb: sockaddr2str: ensure only printable characters are returned for the hostname part In-Reply-To: <20220719155332.18440-1-radoslav.kolev@suse.com> References: <20220719155332.18440-1-radoslav.kolev@suse.com> Message-ID: <20220719155332.18440-2-radoslav.kolev@suse.com> From: Ariadne Conill CVE: CVE-2022-28391 Signed-off-by: Ariadne Conill Tested-by: Radoslav Kolev --- libbb/xconnect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 0e0b247b8..02c061e67 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c @@ -497,8 +497,9 @@ static char* FAST_FUNC sockaddr2str(const struct sockaddr *sa, int flags) ); if (rc) return NULL; + /* ensure host contains only printable characters */ if (flags & IGNORE_PORT) - return xstrdup(host); + return xstrdup(printable_string(host)); #if ENABLE_FEATURE_IPV6 if (sa->sa_family == AF_INET6) { if (strchr(host, ':')) /* heh, it's not a resolved hostname */ @@ -509,7 +510,7 @@ static char* FAST_FUNC sockaddr2str(const struct sockaddr *sa, int flags) #endif /* For now we don't support anything else, so it has to be INET */ /*if (sa->sa_family == AF_INET)*/ - return xasprintf("%s:%s", host, serv); + return xasprintf("%s:%s", printable_string(host), serv); /*return xstrdup(host);*/ } -- 2.26.2 From ariel.dalessandro at collabora.com Wed Jul 20 14:14:24 2022 From: ariel.dalessandro at collabora.com (Ariel D'Alessandro) Date: Wed, 20 Jul 2022 11:14:24 -0300 Subject: [RFC] Busybox ash built-in commands fail on unavailable console Message-ID: <848e9126-c611-bf31-348d-ac179a7197a6@collabora.com> Hi all, Busybox's ash built-in commands -e.g. echo, printf, cd- returns an error if the stdout/stderr device is not available. In particular, I reached this behavior while debugging a Debian initramfs, where ash built-in commands are run during boot, before the console is available. For example, Debian initramfs-tools handles this type of error on printf: https://salsa.debian.org/kernel-team/initramfs-tools/-/blob/master/scripts/functions#L8 ``` _log_msg() { if [ "${quiet?}" = "y" ]; then return; fi # shellcheck disable=SC2059 printf "$@" return 0 # Prevents error carry over in case of unavailable console } ``` * As I'm not sure if this is really a bug or not, I'm sending this as an RFC. So, the question of this RFC is: should this be considered a bug and get fixed properly? Note that running other commands from ash won't fail. Although I haven't checked the source code, that's probably due to the forking process handling stdout/stderr differently. The following straces were run from inside and initramfs, when the console device was still unavailable. Failing case,`cd /` runs silently, but `cd -` tries to print to stdout: ``` strace sh -c "cd / ; cd -" [...] chdir("/") = 0 wait4(-1, 0x7fff4d5351bc, WNOHANG, NULL) = -1 ECHILD (No child processes) chdir("/") = 0 newfstatat(1, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x5, 0x1), ...}, AT_EMPTY_PATH) = 0 ioctl(1, TCGETS, 0x7fff4d534880) = -1 EIO (Input/output error) write(1, "/\n", 2) = -1 EIO (Input/output error) getpid() = 223 exit_group(1) = ? +++ exited with 1 +++ ``` Success case, redirecting `cd -` stdout to /dev/null: ``` strace sh -c "cd / ; cd - >> /dev/null" [...] chdir("/") = 0 openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3 fcntl(1, F_DUPFD_CLOEXEC, 10) = 10 dup2(3, 1) = 1 close(3) = 0 wait4(-1, 0x7ffc316043cc, WNOHANG, NULL) = -1 ECHILD (No child processes) chdir("/") = 0 newfstatat(1, "", {st_mode=S_IFCHR|0666, st_rdev=makedev(0x1, 0x3), ...}, AT_EMPTY_PATH) = 0 ioctl(1, TCGETS, 0x7ffc31603a90) = -1 ENOTTY (Inappropriate ioctl for device) write(1, "/\n", 2) = 2 dup2(10, 1) = 1 close(10) = 0 getpid() = 219 exit_group(0) = ? +++ exited with 0 +++ ``` >From Busybox ash source code, it can be seen that the *lone-dash* case `cd -` tries to print to stdout. The other cd cases with the target directory explicitly set don't fail as they don't try to open the output device, which is unavailable at that point. >From https://git.busybox.net/busybox/tree/shell/ash.c#n2980: ``` static int FAST_FUNC cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { [...] else if (LONE_DASH(dest)) { dest = bltinlookup("OLDPWD"); flags |= CD_PRINT; } [...] out: if (flags & CD_PRINT) out1fmt("%s\n", curdir); return 0; } ``` Regards, Ariel D'Alessandro From ska-dietlibc at skarnet.org Wed Jul 20 17:02:56 2022 From: ska-dietlibc at skarnet.org (Laurent Bercot) Date: Wed, 20 Jul 2022 17:02:56 +0000 Subject: [RFC] Busybox ash built-in commands fail on unavailable console In-Reply-To: <848e9126-c611-bf31-348d-ac179a7197a6@collabora.com> References: <848e9126-c611-bf31-348d-ac179a7197a6@collabora.com> Message-ID: >Busybox's ash built-in commands -e.g. echo, printf, cd- returns an error >if the stdout/stderr device is not available. In particular, I reached >this behavior while debugging a Debian initramfs, where ash built-in >commands are run during boot, before the console is available. POSIX mandates that these functions return a nonzero code when an error occurs. This includes not being able to write to stdout. So the commands are conforming, it's definitely not a bug. >_log_msg() >{ > if [ "${quiet?}" = "y" ]; then return; fi > # shellcheck disable=SC2059 > printf "$@" > return 0 # Prevents error carry over in case of unavailable console >} That is valid. Another way of proceeding is enforcing set +e at the beginning of the script, and explicitly exiting on command failures that are deemed fatal. >* As I'm not sure if this is really a bug or not, I'm sending this as an >RFC. So, the question of this RFC is: should this be considered a bug >and get fixed properly? Not a bug. What needs to be fixed is the scripts that assume cd, echo and printf always succeed. Adding "||:" after a command that must always succeed is easy enough - but hindsight is 20/20 :) >From Busybox ash source code, it can be seen that the *lone-dash* case >`cd -` tries to print to stdout. The other cd cases with the target >directory explicitly set don't fail as they don't try to open the output >device, which is unavailable at that point. Working as intended: "cd -" is specified to be equivalent to 'cd "$OLDPWD" && pwd', and it's the only case where cd writes to stdout. I'm afraid cd - >/dev/null is the best workaround you can get. Shell scripting is fraught with peril, and stdout being unavailable is a common pitfall. Good luck, -- Laurent From ariel.dalessandro at collabora.com Thu Jul 21 13:27:59 2022 From: ariel.dalessandro at collabora.com (Ariel D'Alessandro) Date: Thu, 21 Jul 2022 10:27:59 -0300 Subject: [RFC] Busybox ash built-in commands fail on unavailable console In-Reply-To: References: <848e9126-c611-bf31-348d-ac179a7197a6@collabora.com> Message-ID: <2b104cc6-83a8-4822-9888-8d7dc3db7e5b@collabora.com> Hi Laurent, Thanks a lot for your quick feedback. On 7/20/22 14:02, Laurent Bercot wrote: >> Busybox's ash built-in commands -e.g. echo, printf, cd- returns an error >> if the stdout/stderr device is not available. In particular, I reached >> this behavior while debugging a Debian initramfs, where ash built-in >> commands are run during boot, before the console is available. > > ?POSIX mandates that these functions return a nonzero code when an error > occurs. This includes not being able to write to stdout. So the commands > are conforming, it's definitely not a bug. > > >> _log_msg() >> { >> ?? if [ "${quiet?}" = "y" ]; then return; fi >> ?? # shellcheck disable=SC2059 >> ?? printf "$@" >> ?? return 0 # Prevents error carry over in case of unavailable console >> } > > ?That is valid. > ?Another way of proceeding is enforcing set +e at the beginning of > the script, and explicitly exiting on command failures that are deemed > fatal. > > >> * As I'm not sure if this is really a bug or not, I'm sending this as an >> RFC. So, the question of this RFC is: should this be considered a bug >> and get fixed properly? > > ?Not a bug. What needs to be fixed is the scripts that assume cd, echo > and printf always succeed. Adding "||:" after a command that must always > succeed is easy enough - but hindsight is 20/20 :) > > >> From Busybox ash source code, it can be seen that the *lone-dash* case >> `cd -` tries to print to stdout. The other cd cases with the target >> directory explicitly set don't fail as they don't try to open the output >> device, which is unavailable at that point. > > ?Working as intended: "cd -" is specified to be equivalent to > 'cd "$OLDPWD" && pwd', and it's the only case where cd writes to stdout. > > ?I'm afraid cd - >/dev/null is the best workaround you can get. > Shell scripting is fraught with peril, and stdout being unavailable is > a common pitfall. Understood, makes sense. Thanks again for confirming this is not a bug and commands are conforming to the standard. Regards, Ariel From lkml at jv-coder.de Thu Jul 28 06:26:51 2022 From: lkml at jv-coder.de (Joerg Vehlow) Date: Thu, 28 Jul 2022 08:26:51 +0200 Subject: [PATCH] Use seuser for SELinux login In-Reply-To: <1579156302999.61281@itri.org.tw> References: <1579156302999.61281@itri.org.tw> Message-ID: Hi, @maintainers: Is this ignored, because it is not formatted correctly? This seems to be a real bug, that makes login unusable, if selinux is enabled. @Po-Chun: Maybe try re-sending the patch using git send-email and with a clean commit message, that describes the problem and gives a hint to why your solution is correct. Joerg Am 1/16/2020 um 7:31 AM schrieb pchang9 at itri.org.tw: > Hi, > > > The previous mail is missing in the wild, so I resend the same patch again. > > > We are working on enabling SELinux for BusyBox. > > We thought login should use the seuser for the SELinux default > context,?but the Linux username. > > > Reference and example: > > getseuserbyname on https://selinuxproject.org/page/LibselinuxAPISummary > > > ?/https://github.com/SELinuxProject/selinux/blob/master/libselinux/utils/getseuser.c > > / > > Signed-off-by: Po-Chun Chang > --- > ?loginutils/login.c | 11 ++++++++++- > ?1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/loginutils/login.c b/loginutils/login.c > index 4e65b3a19..11a82421b 100644 > --- a/loginutils/login.c > +++ b/loginutils/login.c > @@ -178,12 +178,16 @@ static void die_if_nologin(void) > ?static void initselinux(char *username, char *full_tty, > ??????????????????????????????????????????????? security_context_t > *user_sid) > ?{ > +?????? char *seuser = NULL, *level = NULL; > ??????? security_context_t old_tty_sid, new_tty_sid; > > ??????? if (!is_selinux_enabled()) > ??????????????? return; > > -?????? if (get_default_context(username, NULL, user_sid)) { > +?????? if (getseuserbyname(username, &seuser, &level)) { > +?????????????? bb_error_msg_and_die("can't get seuser for %s", username); > +?????? } > +?????? if (get_default_context(seuser, NULL, user_sid)) { > ??????????????? bb_error_msg_and_die("can't get SID for %s", username); > ??????? } > ??????? if (getfilecon(full_tty, &old_tty_sid) < 0) { > @@ -196,6 +200,11 @@ static void initselinux(char *username, char *full_tty, > ??????? if (setfilecon(full_tty, new_tty_sid) != 0) { > ??????????????? bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, > new_tty_sid); > ??????? } > + > +?????? if (ENABLE_FEATURE_CLEAN_UP) { > +?????????????? free(seuser); > +?????????????? free(level); > +?????? } > ?} > ?#endif > --- > > // > > > > > -- > ???????????????????????????????????? > ???????? This email may contain confidential information. Please > do not use or disclose it in any way and delete it if you are not the > intended recipient. > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From lkml at jv-coder.de Thu Jul 28 06:45:47 2022 From: lkml at jv-coder.de (Joerg Vehlow) Date: Thu, 28 Jul 2022 08:45:47 +0200 Subject: [PATCH] Use seuser for SELinux login In-Reply-To: References: <1579156302999.61281@itri.org.tw> Message-ID: <8a659e92-7da2-686a-9679-5b9ffa73a19b@jv-coder.de> Hi, according to the auto reply from Po-Chun, he left itri. So don't expect a response from him. Joerg Am 7/28/2022 um 8:26 AM schrieb Joerg Vehlow: > Hi, > > @maintainers: Is this ignored, because it is not formatted correctly? > > This seems to be a real bug, that makes login unusable, if selinux is > enabled. > > @Po-Chun: Maybe try re-sending the patch using git send-email and with a > clean commit message, that describes the problem and gives a hint to why > your solution is correct. > > Joerg > > Am 1/16/2020 um 7:31 AM schrieb pchang9 at itri.org.tw: >> Hi, >> >> >> The previous mail is missing in the wild, so I resend the same patch again. >> >> >> We are working on enabling SELinux for BusyBox. >> >> We thought login should use the seuser for the SELinux default >> context,?but the Linux username. >> >> >> Reference and example: >> >> getseuserbyname on https://selinuxproject.org/page/LibselinuxAPISummary >> >> >> ?/https://github.com/SELinuxProject/selinux/blob/master/libselinux/utils/getseuser.c >> >> / >> >> Signed-off-by: Po-Chun Chang >> --- >> ?loginutils/login.c | 11 ++++++++++- >> ?1 file changed, 10 insertions(+), 1 deletion(-) >> >> diff --git a/loginutils/login.c b/loginutils/login.c >> index 4e65b3a19..11a82421b 100644 >> --- a/loginutils/login.c >> +++ b/loginutils/login.c >> @@ -178,12 +178,16 @@ static void die_if_nologin(void) >> ?static void initselinux(char *username, char *full_tty, >> ??????????????????????????????????????????????? security_context_t >> *user_sid) >> ?{ >> +?????? char *seuser = NULL, *level = NULL; >> ??????? security_context_t old_tty_sid, new_tty_sid; >> >> ??????? if (!is_selinux_enabled()) >> ??????????????? return; >> >> -?????? if (get_default_context(username, NULL, user_sid)) { >> +?????? if (getseuserbyname(username, &seuser, &level)) { >> +?????????????? bb_error_msg_and_die("can't get seuser for %s", username); >> +?????? } >> +?????? if (get_default_context(seuser, NULL, user_sid)) { >> ??????????????? bb_error_msg_and_die("can't get SID for %s", username); >> ??????? } >> ??????? if (getfilecon(full_tty, &old_tty_sid) < 0) { >> @@ -196,6 +200,11 @@ static void initselinux(char *username, char *full_tty, >> ??????? if (setfilecon(full_tty, new_tty_sid) != 0) { >> ??????????????? bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, >> new_tty_sid); >> ??????? } >> + >> +?????? if (ENABLE_FEATURE_CLEAN_UP) { >> +?????????????? free(seuser); >> +?????????????? free(level); >> +?????? } >> ?} >> ?#endif >> --- >> >> // >> >> >> >> >> -- >> ???????????????????????????????????? >> ???????? This email may contain confidential information. Please >> do not use or disclose it in any way and delete it if you are not the >> intended recipient. >> >> _______________________________________________ >> busybox mailing list >> busybox at busybox.net >> http://lists.busybox.net/mailman/listinfo/busybox > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Fri Jul 29 14:07:17 2022 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Fri, 29 Jul 2022 16:07:17 +0200 Subject: sort's -k flag is buggy when M is also passed In-Reply-To: References: Message-ID: Fixed in git. Thank you. On Wed, Jun 29, 2022 at 7:11 AM Dennis Chen wrote: > > All commands were run on both Ubuntu busybox v1.30.1 and Alpine busybox > v1.35.0. > > I ran > echo "3 March\n2 April" | busybox sort -k 2,2M > and it returned > 2 April > 3 March > It should return > 3 March > 2 April > and indeed, that is what you get with GNU sort. (It doesn't seem to > matter what the numbers "2" and "3" are - I replaced them both with the > string "filler" and got the same result.) > > This seems to only happen when the field number is >1. For instance > echo "March\nApril" | busybox sort -k 1,1M > correctly outputs > March > April > > It also doesn't happen when M isn't passed into -k. For instance, > echo "a c\nb b" | sort -k 2,2 > correctly returns > b b > a c > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox