From ghanson at arista.com Tue Feb 1 17:12:05 2022 From: ghanson at arista.com (Geoff Hanson) Date: Tue, 1 Feb 2022 09:12:05 -0800 Subject: udhcpc6 expects string for bootfile-param opt(60) In-Reply-To: References: Message-ID: Hi Xabier. Thanks for reviewing it. In most cases, there's no printf directive so this just means it's copying the string. But this would cause problems in the case where the string did contain %'s. I've attached a new patch with an alternate way of copying the parameters. Thanks, Geoff On Mon, Jan 31, 2022 at 11:09 AM Xabier Oneca -- xOneca wrote: > Hi Geoff, > > > [...] > > + if (envptr > envval) > > + *envptr++ = ' '; > > + snprintf(envptr, parm_len + 1, optptr); > > You forgot the format string (i.e. "%s"). > > > + envptr += parm_len; > > + optptr += parm_len; > > [...] > > Cheers, > > Xabier Oneca_,,_ > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- Index: busybox-1.33.1/networking/udhcp/d6_dhcpc.c =================================================================== --- busybox-1.33.1.orig/networking/udhcp/d6_dhcpc.c +++ busybox-1.33.1/networking/udhcp/d6_dhcpc.c @@ -79,7 +79,7 @@ static const struct dhcp_optflag d6_optf #endif #if ENABLE_FEATURE_UDHCPC6_RFC5970 { OPTION_STRING, D6_OPT_BOOT_URL }, - { OPTION_STRING, D6_OPT_BOOT_PARAM }, + { OPTION_STRING | OPTION_LIST, D6_OPT_BOOT_PARAM }, #endif { OPTION_STRING, 0xd1 }, /* DHCP_PXE_CONF_FILE */ { OPTION_STRING, 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ @@ -214,19 +214,16 @@ static char** new_env(void) return &client6_data.env_ptr[client6_data.env_idx++]; } -static char *string_option_to_env(const uint8_t *option, - const uint8_t *option_end) +static const char *get_option_name(const uint8_t *option) { - const char *ptr, *name = NULL; - unsigned val_len; + const char *ptr = NULL; int i; ptr = d6_option_strings; i = 0; while (*ptr) { if (d6_optflags[i].code == option[1]) { - name = ptr; - goto found; + return ptr; } ptr += strlen(ptr) + 1; i++; @@ -234,7 +231,19 @@ static char *string_option_to_env(const bb_error_msg("can't find option name for 0x%x, skipping", option[1]); return NULL; - found: +} + +static char *string_option_to_env(const uint8_t *option, + const uint8_t *option_end) +{ + const char *name = NULL; + unsigned val_len; + + name = get_option_name(option); + if (!name) { + return NULL; + } + val_len = (option[2] << 8) | option[3]; if (val_len + &option[D6_OPT_DATA] > option_end) { bb_simple_error_msg("option data exceeds option length"); @@ -243,6 +252,52 @@ static char *string_option_to_env(const return xasprintf("%s=%.*s", name, val_len, (char*)option + 4); } +/* parse list of variable length strings. The length of each string + is the first two bytes */ +static char *string_list_option_to_env(const uint8_t *option, + const uint8_t *option_end) +{ + const char *name = NULL; + unsigned val_len, name_len, parm_len; + int i; + char *envstr, *envptr, *envval; + const uint8_t *optptr; + + name = get_option_name(option); + if (!name) + return NULL; + name_len = strlen(name); + + val_len = (option[2] << 8) | option[3]; + if (val_len + &option[D6_OPT_DATA] > option_end) { + bb_simple_error_msg("option data exceeds option length"); + return NULL; + } + + envptr = envstr = xmalloc(name_len + 1 + val_len); + envptr = stpcpy(envptr, name); + envval = envptr = stpcpy(envptr, "="); + + optptr = option + D6_OPT_DATA; + while (optptr + 1 < option_end) { + parm_len = (*optptr++ << 8) | *optptr++; + if (optptr + parm_len > option_end) { + bb_simple_error_msg("option parm length overflows option length"); + return NULL; + } + if (parm_len > 0) { + if (envptr > envval) + *envptr++ = ' '; + memcpy(envptr, optptr, parm_len); + envptr += parm_len; + optptr += parm_len; + *envptr = '\0'; + } + } + + return envstr; +} + /* put all the parameters into the environment */ static void option_to_env(const uint8_t *option, const uint8_t *option_end) { @@ -407,7 +462,6 @@ static void option_to_env(const uint8_t break; #endif case D6_OPT_BOOT_URL: - case D6_OPT_BOOT_PARAM: case 0xd1: /* DHCP_PXE_CONF_FILE */ case 0xd2: /* DHCP_PXE_PATH_PREFIX */ { @@ -415,6 +469,38 @@ static void option_to_env(const uint8_t if (tmp) *new_env() = tmp; break; + } + case D6_OPT_BOOT_PARAM: +/* 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | OPT_BOOTFILE_PARAM | option-len | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | param-len 1 | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ parameter 1 . + * . (variable length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * . . + * . . + * . . + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | param-len n | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ parameter n . + * . (variable length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + { + char *tmp; + if (option[4]) + /* If the high byte of param-len 1 is non-zero, most + likely this was caused by a non-compliant server + sending the param as a single string. */ + tmp = string_option_to_env(option, option_end); + else + tmp = string_list_option_to_env(option, option_end); + if (tmp) + *new_env() = tmp; + break; } } len_m4 -= 4 + option[3]; From ghanson at arista.com Tue Feb 1 20:53:32 2022 From: ghanson at arista.com (Geoff Hanson) Date: Tue, 1 Feb 2022 12:53:32 -0800 Subject: udhcpc6 expects string for bootfile-param opt(60) In-Reply-To: <45cca76e-f2ec-078c-b60a-d1af9a8f91e7@petrovitsch.priv.at> References: <45cca76e-f2ec-078c-b60a-d1af9a8f91e7@petrovitsch.priv.at> Message-ID: Hi Bernd. Can you look at my second attachment? As part of addressing the issue Xabier reported, I switched to using memcpy. Thanks, Geoff On Tue, Feb 1, 2022 at 12:36 PM Bernd Petrovitsch wrote: > -Hi all! > > On 01.02.2022 18:12, Geoff Hanson wrote: > [...]> In most cases, there's no printf directive so this just means it's > > copying the string. > > Using some user-provided string as a format-string opens the possibility > ofexploits - since decades .... > > But this would cause problems in the case where the string did contain > %'s. > > So why just not only use strncpy(), strlcpy(), memcpy() or similar? > > Kind regards, > Bernd > -------------- next part -------------- An HTML attachment was scrubbed... URL: From bernd at petrovitsch.priv.at Tue Feb 1 20:36:51 2022 From: bernd at petrovitsch.priv.at (Bernd Petrovitsch) Date: Tue, 1 Feb 2022 21:36:51 +0100 Subject: udhcpc6 expects string for bootfile-param opt(60) In-Reply-To: References: Message-ID: <45cca76e-f2ec-078c-b60a-d1af9a8f91e7@petrovitsch.priv.at> -Hi all! On 01.02.2022 18:12, Geoff Hanson wrote: [...]> In most cases, there's no printf directive so this just means it's > copying the string. Using some user-provided string as a format-string opens the possibility ofexploits - since decades .... > But this would cause problems in the case where the string did contain %'s. So why just not only use strncpy(), strlcpy(), memcpy() or similar? Kind regards, Bernd From soeren at soeren-tempel.net Tue Feb 8 19:29:30 2022 From: soeren at soeren-tempel.net (soeren at soeren-tempel.net) Date: Tue, 8 Feb 2022 20:29:30 +0100 Subject: [PATCH] ed: don't use memcpy with overlapping memory regions Message-ID: <20220208192930.15089-1-soeren@soeren-tempel.net> From: S?ren Tempel The memcpy invocations in the subCommand function, modified by this commit, previously used memcpy with overlapping memory regions. This is undefined behavior. On Alpine Linux, it causes BusyBox ed to crash since we compile BusyBox with -D_FORTIFY_SOURCE=2 and our fortify-headers implementation catches this source of undefined behavior [0]. The issue can only be triggered if the replacement string is the same size or shorter than the old string. Looking at the code, it seems to me that a memmove(3) is what was actually intended here, this commit modifies the code accordingly. [0]: https://gitlab.alpinelinux.org/alpine/aports/-/issues/13504 --- editors/ed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/ed.c b/editors/ed.c index 209ce9942..4a84f7433 100644 --- a/editors/ed.c +++ b/editors/ed.c @@ -720,7 +720,7 @@ static void subCommand(const char *cmd, int num1, int num2) if (deltaLen <= 0) { memcpy(&lp->data[offset], newStr, newLen); if (deltaLen) { - memcpy(&lp->data[offset + newLen], + memmove(&lp->data[offset + newLen], &lp->data[offset + oldLen], lp->len - offset - oldLen); From ghanson at arista.com Tue Feb 8 19:58:24 2022 From: ghanson at arista.com (Geoff Hanson) Date: Tue, 8 Feb 2022 11:58:24 -0800 Subject: udhcpc6 expects string for bootfile-param opt(60) In-Reply-To: References: <45cca76e-f2ec-078c-b60a-d1af9a8f91e7@petrovitsch.priv.at> Message-ID: Any further feedback on this? Anything more I need to do or is what I've provided sufficient for the bug report? Thanks, Geoff On Tue, Feb 1, 2022 at 12:53 PM Geoff Hanson wrote: > Hi Bernd. Can you look at my second attachment? As part of addressing the > issue Xabier reported, > I switched to using memcpy. > > Thanks, > Geoff > > On Tue, Feb 1, 2022 at 12:36 PM Bernd Petrovitsch < > bernd at petrovitsch.priv.at> wrote: > >> -Hi all! >> >> On 01.02.2022 18:12, Geoff Hanson wrote: >> [...]> In most cases, there's no printf directive so this just means it's >> > copying the string. >> >> Using some user-provided string as a format-string opens the possibility >> ofexploits - since decades .... >> > But this would cause problems in the case where the string did contain >> %'s. >> >> So why just not only use strncpy(), strlcpy(), memcpy() or similar? >> >> Kind regards, >> Bernd >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jody at jodybruchon.com Wed Feb 9 04:25:58 2022 From: jody at jodybruchon.com (Jody Bruchon) Date: Tue, 8 Feb 2022 23:25:58 -0500 Subject: [PATCH] Style guide: add "Required_argument" example to applet_longopts Message-ID: -------------- next part -------------- From 48532ee17f752a9bbf4dbf6cb1d7662004c41756 Mon Sep 17 00:00:00 2001 From: Jody Bruchon Date: Wed, 31 Mar 2021 11:30:31 -0400 Subject: [PATCH] Style guide: add "Required_argument" example to applet_longopts Signed-off-by: Jody Bruchon --- docs/style-guide.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/style-guide.txt b/docs/style-guide.txt index 9eed7f125..768bca92d 100644 --- a/docs/style-guide.txt +++ b/docs/style-guide.txt @@ -680,8 +680,9 @@ line in the midst of your #includes, if you need to parse long options: Then have long options defined: static const char _longopts[] ALIGN1 = - "list\0" No_argument "t" - "extract\0" No_argument "x" + "list\0" No_argument "t" + "extract\0" No_argument "x" + "directory\0" Required_argument "C" ; And a code block similar to the following near the top of your applet_main() -- 2.15.0 From sun681 at gmail.com Wed Feb 9 16:26:13 2022 From: sun681 at gmail.com (=?UTF-8?B?16HXkNefINei157XqA==?=) Date: Wed, 9 Feb 2022 18:26:13 +0200 Subject: suspected bug in timeout command Message-ID: Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly to a process of mine. I debugged it until I found it from the timeout process which was assigned before to another process with the same pid. (i'm using a lot of timeouts for a lot of jobs) so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check the timeout status. I suspect at this time the process timeout monitoring is terminated, but another one with the same pid is already created. which creates unwanted timeout. There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I can't see why it won't occur also in the current case. there is no change of this behaviour in the latest master. i would appreciate any help, sun. -------------- next part -------------- An HTML attachment was scrubbed... URL: From baruch at tkos.co.il Wed Feb 9 17:12:43 2022 From: baruch at tkos.co.il (Baruch Siach) Date: Wed, 09 Feb 2022 19:12:43 +0200 Subject: suspected bug in timeout command In-Reply-To: References: Message-ID: <871r0cc5vn.fsf@tarshish> Hi Sun, On Wed, Feb 09 2022, ??? ??? wrote: > Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly to a process of mine. I debugged it until I found > it from the timeout process which was assigned before to another process with the same pid. (i'm using a lot of timeouts for a lot of jobs) > so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check the timeout status. I suspect at this time the > process timeout monitoring is terminated, but another one with the same pid is already created. which creates unwanted timeout. > > There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I can't see why it won't occur also in the current > case. > > there is no change of this behaviour in the latest master. > i would appreciate any help, sun. Any reference to PID number is inherently racy. There is no solution for your problem in the traditional POSIX API. Recent Linux kernels provide the "pidfd" API which is meant to be race free. See for example the pidfd_open(2) man page, and related system calls. https://man7.org/linux/man-pages/man2/pidfd_open.2.html For some background see LWN coverage of the feature development. https://lwn.net/Kernel/Index/#pidfd baruch -- ~. .~ Tk Open Systems =}------------------------------------------------ooO--U--Ooo------------{= - baruch at tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il - From mconrad at intellitree.com Wed Feb 9 18:18:21 2022 From: mconrad at intellitree.com (Michael Conrad) Date: Wed, 09 Feb 2022 18:18:21 +0000 (UTC) Subject: suspected bug in timeout command In-Reply-To: <871r0cc5vn.fsf@tarshish> References: <871r0cc5vn.fsf@tarshish> Message-ID: <6712f901-abcc-fff3-01ef-b45b30789013@intellitree.com> On 2/9/22 12:12, Baruch Siach wrote: > Hi Sun, > > On Wed, Feb 09 2022, ??? ??? wrote: >> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly to a process of mine. I debugged it until I found >> it from the timeout process which was assigned before to another process with the same pid. (i'm using a lot of timeouts for a lot of jobs) >> so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check the timeout status. I suspect at this time the >> process timeout monitoring is terminated, but another one with the same pid is already created. which creates unwanted timeout. >> >> There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I can't see why it won't occur also in the current >> case. >> >> there is no change of this behaviour in the latest master. >> i would appreciate any help, sun. > Any reference to PID number is inherently racy. There is no solution for > your problem in the traditional POSIX API. PIDs are not racy if they are sent by the parent process.? Since the timeout command starts the other command, and waits to kill it, it should be the parent process, and will always reliably know that either the child is not reaped and can be sent a signal, or that it is reaped and there's no reason to.? Perhaps the implementation of this command needs corrected? -Mike C From rmy at pobox.com Thu Feb 10 12:57:43 2022 From: rmy at pobox.com (Ron Yorston) Date: Thu, 10 Feb 2022 12:57:43 +0000 Subject: [PATCH] cpio: code shrink Message-ID: <62050bc7.8NfDUxqWvOb54tXW%rmy@pobox.com> Use a generic llist_t to store the names of hardlinked files. function old new delta cpio_o 1140 1122 -18 Signed-off-by: Ron Yorston --- archival/cpio.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 7149782d7..836609fc3 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -223,13 +223,9 @@ static off_t cpio_pad4(off_t size) * It's ok to exit instead of return. */ static NOINLINE int cpio_o(void) { - struct name_s { - struct name_s *next; - char name[1]; - }; struct inodes_s { struct inodes_s *next; - struct name_s *names; + llist_t *names; struct stat st; #if ENABLE_FEATURE_CPIO_RENUMBER_INODES ino_t mapped_inode; @@ -277,7 +273,6 @@ static NOINLINE int cpio_o(void) /* Store hardlinks for later processing, dont output them */ if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) { - struct name_s *n; struct inodes_s *l; /* Do we have this hardlink remembered? */ @@ -302,11 +297,7 @@ static NOINLINE int cpio_o(void) l = l->next; } /* Add new name to "l->names" list */ - n = xmalloc(sizeof(*n) + strlen(name)); - strcpy(n->name, name); - n->next = l->names; - l->names = n; - + llist_add_to(&l->names, xstrdup(name)); free(line); continue; } @@ -320,8 +311,7 @@ static NOINLINE int cpio_o(void) if (links) { /* Output hardlink's data */ st = links->st; - name = links->names->name; - links->names = links->names->next; + name = llist_pop(&links->names); #if ENABLE_FEATURE_CPIO_RENUMBER_INODES if (links->mapped_inode) st.st_ino = links->mapped_inode; @@ -332,7 +322,7 @@ static NOINLINE int cpio_o(void) links = links->next; else st.st_size = 0; - /* NB: we leak links->names and/or links, + /* NB: we leak links->names->name and/or links, * this is intended (we exit soon anyway) */ } else { /* If no (more) hardlinks to output, -- 2.34.1 From danomimanchego123 at gmail.com Thu Feb 10 17:44:12 2022 From: danomimanchego123 at gmail.com (Danomi Manchego) Date: Thu, 10 Feb 2022 12:44:12 -0500 Subject: mount -w flag Message-ID: Hi. It looks like -w flag works with the mount applet. However, -2 does not show in mount --help, presumably due to an extra //: //usage: "\n -r Read-only mount" ////usage: "\n -w Read-write mount (default)" //usage: "\n -t FSTYPE[,...] Filesystem type(s)" Mistake? Thanks in advance, Danomi - From danomimanchego123 at gmail.com Thu Feb 10 17:45:57 2022 From: danomimanchego123 at gmail.com (Danomi Manchego) Date: Thu, 10 Feb 2022 12:45:57 -0500 Subject: mount -w flag In-Reply-To: References: Message-ID: Sorry, typo - "However -w does not show in mount --help, ..." On Thu, Feb 10, 2022 at 12:44 PM Danomi Manchego wrote: > > Hi. It looks like -w flag works with the mount applet. However, -2 > does not show in mount --help, presumably due to an extra //: > > //usage: "\n -r Read-only mount" > ////usage: "\n -w Read-write mount (default)" > //usage: "\n -t FSTYPE[,...] Filesystem type(s)" > > Mistake? > > Thanks in advance, > Danomi - From rob at landley.net Fri Feb 11 21:22:03 2022 From: rob at landley.net (Rob Landley) Date: Fri, 11 Feb 2022 15:22:03 -0600 Subject: suspected bug in timeout command In-Reply-To: <871r0cc5vn.fsf@tarshish> References: <871r0cc5vn.fsf@tarshish> Message-ID: <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> On 2/9/22 11:12 AM, Baruch Siach wrote: > Hi Sun, > > On Wed, Feb 09 2022, ??? ??? wrote: >> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly to a process of mine. I debugged it until I found >> it from the timeout process which was assigned before to another process with the same pid. (i'm using a lot of timeouts for a lot of jobs) >> so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check the timeout status. I suspect at this time the >> process timeout monitoring is terminated, but another one with the same pid is already created. which creates unwanted timeout. >> >> There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I can't see why it won't occur also in the current >> case. >> >> there is no change of this behaviour in the latest master. >> i would appreciate any help, sun. > > Any reference to PID number is inherently racy. Not between parent and child. That's why zombies need reaping: a child process will not exit until the parent accepts its exit code and timing data via wait() (or itself exits). You can leave a zombie process lying around for literally years and the PID won't be reused while the zombie still exists. You can set SIGCHLD to SIG_IGN to allow your child processes to asynchronously self-reap, which can make it disappear out from under you. And that signal mask can be inherited by child processes, just like you can leak filehandles and environment variables and tty state and cpu mask and nice level and a dozen other things into your child process state: the parent process defines the child state back to PID 1. If a parent process ignores SIGCHLD and spawns child processes that run timeout, in that case the child process of the timeout could cycle out from under timeout. I'd look for that in this instance. One workaround would would be timeout.c explicitly doing signal(SIGCHLD, SIG_DFL) to correct its inherited signal mask, but the parent process doing that is pilot error, and that "fix" is about like a program using fcntl(SETFL) to strip O_NONBLOCK off stdout just in case it was called with broken standard filehandles: that kind of defensive programming isn't generally part of busybox. > There is no solution for > your problem in the traditional POSIX API. The preponderance of the evidence is that the posix API people have used for ~50 years and sent into space and such can indeed work reliably for people who know how to use it. Next time you want to say "Linux/posix is fundamentally broken, there is no solution in existing deployed kernels, this command busybox has had for 14 years can't ever have worked reliably and nobody noticed before", why not try phrasing it as a question instead of a statement of fact? Rob From rafdev at dinapo.li Sat Feb 12 01:32:49 2022 From: rafdev at dinapo.li (Raffaello D. Di Napoli) Date: Fri, 11 Feb 2022 20:32:49 -0500 Subject: suspected bug in timeout command In-Reply-To: <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> Message-ID: <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> On 2/11/22 16:22, Rob Landley wrote: > On 2/9/22 11:12 AM, Baruch Siach wrote: >> Hi Sun, >> >> On Wed, Feb 09 2022, ??? ??? wrote: >>> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly to a process of mine. I debugged it until I found >>> it from the timeout process which was assigned before to another process with the same pid. (i'm using a lot of timeouts for a lot of jobs) >>> so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check the timeout status. I suspect at this time the >>> process timeout monitoring is terminated, but another one with the same pid is already created. which creates unwanted timeout. >>> >>> There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I can't see why it won't occur also in the current >>> case. >>> >>> there is no change of this behaviour in the latest master. >>> i would appreciate any help, sun. >> Any reference to PID number is inherently racy. > Not between parent and child. Except in BB?s timeout, the relationship is not parent/child :) Much to my surprise, I?ll say that. When I read the bug report the other day, I thought to myself well, this one ought to be easy to fix. But no, there?s no SIGCHLD to be handled, no relationship between processes to be leveraged. I don?t think this bug can be fixed without a near-complete rewrite, or without doing a lot of procfs digging to really validate the waited-on process, since kill(pid, 0) only validates a pid, not a process. -- Raf From David.Laight at ACULAB.COM Sat Feb 12 11:08:14 2022 From: David.Laight at ACULAB.COM (David Laight) Date: Sat, 12 Feb 2022 11:08:14 +0000 Subject: suspected bug in timeout command In-Reply-To: <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> Message-ID: From: Raffaello D. Di Napoli > Sent: 12 February 2022 01:33 > > > On 2/11/22 16:22, Rob Landley wrote: > > On 2/9/22 11:12 AM, Baruch Siach wrote: > >> Hi Sun, > >> > >> On Wed, Feb 09 2022, ??? ??? wrote: > >>> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly > to a process of mine. I debugged it until I found > >>> it from the timeout process which was assigned before to another process with the same pid. (i'm > using a lot of timeouts for a lot of jobs) > >>> so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check > the timeout status. I suspect at this time the > >>> process timeout monitoring is terminated, but another one with the same pid is already created. > which creates unwanted timeout. > >>> > >>> There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I > can't see why it won't occur also in the current > >>> case. > >>> > >>> there is no change of this behaviour in the latest master. > >>> i would appreciate any help, sun. > >> Any reference to PID number is inherently racy. > > Not between parent and child. > > Except in BB?s timeout, the relationship is not parent/child :) > > Much to my surprise, I?ll say that. When I read the bug report the other > day, I thought to myself well, this one ought to be easy to fix. But no, > there?s no SIGCHLD to be handled, no relationship between processes to > be leveraged. > > I don?t think this bug can be fixed without a near-complete rewrite, or > without doing a lot of procfs digging to really validate the waited-on > process, since kill(pid, 0) only validates a pid, not a process. And Linux uses a strict 'next free pid' algorithm for new processes so the is no guard time between a process exiting and its pid being reused. This problem was 'fixed' inside the kernel by using a small structure instead of the pid itself - but that didn't help userspace (or even some drivers). By comparison NetBSD uses the high bits of the pid as a 'generation number' and so guarantees that a pid won't be reused for some time (a few thousand forks). You can use the process start time (I think it is in /proc/pid/stat) to validate the process just before the kill(). That leaves a very small timing window that it is hard to avoid without using pidfd. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) From mconrad at intellitree.com Sat Feb 12 12:38:06 2022 From: mconrad at intellitree.com (Michael Conrad) Date: Sat, 12 Feb 2022 12:38:06 +0000 (UTC) Subject: suspected bug in timeout command In-Reply-To: References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> Message-ID: <689f8b62-8299-361c-c83f-618bd9ea4abf@intellitree.com> On 2/12/22 06:08, David Laight wrote: > From: Raffaello D. Di Napoli >> Sent: 12 February 2022 01:33 >> >> >> On 2/11/22 16:22, Rob Landley wrote: >>> On 2/9/22 11:12 AM, Baruch Siach wrote: >>>> Hi Sun, >>>> >>>> On Wed, Feb 09 2022, ??? ??? wrote: >>>>> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly >> to a process of mine. I debugged it until I found >>>>> it from the timeout process which was assigned before to another process with the same pid. (i'm >> using a lot of timeouts for a lot of jobs) >>>>> so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check >> the timeout status. I suspect at this time the >>>>> process timeout monitoring is terminated, but another one with the same pid is already created. >> which creates unwanted timeout. >>>>> There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I >> can't see why it won't occur also in the current >>>>> case. >>>>> >>>>> there is no change of this behaviour in the latest master. >>>>> i would appreciate any help, sun. >>>> Any reference to PID number is inherently racy. >>> Not between parent and child. >> Except in BB?s timeout, the relationship is not parent/child :) >> >> Much to my surprise, I?ll say that. When I read the bug report the other >> day, I thought to myself well, this one ought to be easy to fix. But no, >> there?s no SIGCHLD to be handled, no relationship between processes to >> be leveraged. >> >> I don?t think this bug can be fixed without a near-complete rewrite, or >> without doing a lot of procfs digging to really validate the waited-on >> process, since kill(pid, 0) only validates a pid, not a process. > And Linux uses a strict 'next free pid' algorithm for new processes > so the is no guard time between a process exiting and its pid being reused. > This problem was 'fixed' inside the kernel by using a small structure > instead of the pid itself - but that didn't help userspace (or even some drivers). > By comparison NetBSD uses the high bits of the pid as a 'generation number' > and so guarantees that a pid won't be reused for some time (a few thousand forks). > > You can use the process start time (I think it is in /proc/pid/stat) > to validate the process just before the kill(). > That leaves a very small timing window that it is hard to avoid > without using pidfd. > > David > Correctly using pidfd *still* requires that you be the parent process, else the child could get reaped and replaced before the pidfd is created.? As far as I can tell, the only purpose of pidfd is for waking on poll() instead of using signals, which is orthagonal to this problem. I haven't looked at the source in busybox yet, but it boggles my mind that it wouldn't just be a simple fork+alarm+waitpid because that is literally the least code implementation, and race-free. -Mike C From mconrad at intellitree.com Sat Feb 12 12:58:44 2022 From: mconrad at intellitree.com (Michael Conrad) Date: Sat, 12 Feb 2022 12:58:44 +0000 (UTC) Subject: suspected bug in timeout command In-Reply-To: <689f8b62-8299-361c-c83f-618bd9ea4abf@intellitree.com> References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> <689f8b62-8299-361c-c83f-618bd9ea4abf@intellitree.com> Message-ID: <1679c9d6-d668-2801-9b37-e7337ad3023b@intellitree.com> On 2/12/22 07:38, Michael Conrad wrote: > Correctly using pidfd *still* requires that you be the parent process, > else the child could get reaped and replaced before the pidfd is > created.? As far as I can tell, the only purpose of pidfd is for > waking on poll() instead of using signals, which is orthagonal to this > problem. > > I haven't looked at the source in busybox yet, but it boggles my mind > that it wouldn't just be a simple fork+alarm+waitpid because that is > literally the least code implementation, and race-free. > > -Mike C > Sorry for being lazy.? I looked at the source and this is the reason: /* We want to create a grandchild which will watch ?* and kill the grandparent. Other methods: ?* making parent watch child disrupts parent<->child link ?* (example: "tcpsvd 0.0.0.0 1234 timeout service_prog" - ?* it's better if service_prog is a child of tcpsvd!), ?* making child watch parent results in programs having ?* unexpected children.?? ?*/ I don't follow this reasoning.? Does "disrupts the parent<->child link" just about sending signals?? If the timeout app relays all signals from itself to the child, what remaining problems would exist? -Mike C From David.Laight at ACULAB.COM Sat Feb 12 13:13:05 2022 From: David.Laight at ACULAB.COM (David Laight) Date: Sat, 12 Feb 2022 13:13:05 +0000 Subject: suspected bug in timeout command In-Reply-To: <1679c9d6-d668-2801-9b37-e7337ad3023b@intellitree.com> References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> <689f8b62-8299-361c-c83f-618bd9ea4abf@intellitree.com> <1679c9d6-d668-2801-9b37-e7337ad3023b@intellitree.com> Message-ID: <5f1e935250bd46ef82a269b860fae073@AcuMS.aculab.com> From: Michael Conrad > Sent: 12 February 2022 12:59 > > On 2/12/22 07:38, Michael Conrad wrote: > > Correctly using pidfd *still* requires that you be the parent process, > > else the child could get reaped and replaced before the pidfd is > > created.? As far as I can tell, the only purpose of pidfd is for > > waking on poll() instead of using signals, which is orthagonal to this > > problem. Even if the pidfd can't be passed down, it lets you verify the process information and then send the signal. > > I haven't looked at the source in busybox yet, but it boggles my mind > > that it wouldn't just be a simple fork+alarm+waitpid because that is > > literally the least code implementation, and race-free. > > > > -Mike C > > > Sorry for being lazy.? I looked at the source and this is the reason: > > /* We want to create a grandchild which will watch > ?* and kill the grandparent. Other methods: > ?* making parent watch child disrupts parent<->child link > ?* (example: "tcpsvd 0.0.0.0 1234 timeout service_prog" - > ?* it's better if service_prog is a child of tcpsvd!), > ?* making child watch parent results in programs having > ?* unexpected children.?? ?*/ > > I don't follow this reasoning.? Does "disrupts the parent<->child link" > just about sending signals?? If the timeout app relays all signals from > itself to the child, what remaining problems would exist? In that case you can pass 'verification information' through to the grandchild. It could be an open fd of "/proc/self" - which allows the non-racy kill on recent kernels. But other information would allow the timing window be minimalised on older kernels. ISTR that on older kernels an open fd to "proc/nn" always refers to the current process with pid nn. But the actual behaviour is worth checking. I think newer kernels will fail any reads after the process has exited. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) From sun681 at gmail.com Sun Feb 13 07:31:50 2022 From: sun681 at gmail.com (=?UTF-8?B?16HXkNefINei157XqA==?=) Date: Sun, 13 Feb 2022 09:31:50 +0200 Subject: suspected bug in timeout command In-Reply-To: <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> Message-ID: Hey, first of all thanks for your answers and sorry for how I phrase my question. Rob, I still need a clarification if you don't mind. anything that you mention is making sense to me if the timeout implementation here was that the actual command is a child process of a process that doing the timeout logic. which is the case for other implementations I saw (for example here ) but for the case of busybox implementation, the timeout is a child process of the command it runs on (actually a grandchild), so the case of process that represents the command finish and its parent releasing its PID (via wait) can occur, while the process that represents the timeout missing it. and all this can happen while there is no case of ignoring the SIGCHLD. am I wrong? ??????? ??? ??, 11 ????? 2022 ?-23:19 ??? ?Rob Landley?? :? > On 2/9/22 11:12 AM, Baruch Siach wrote: > > Hi Sun, > > > > On Wed, Feb 09 2022, ??? ??? wrote: > >> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue > with a sigterm send randomly to a process of mine. I debugged it until I > found > >> it from the timeout process which was assigned before to another > process with the same pid. (i'm using a lot of timeouts for a lot of jobs) > >> so i looked at the code, "timeout.c" file where it sleep for 1 second > in each iteration then check the timeout status. I suspect at this time the > >> process timeout monitoring is terminated, but another one with the same > pid is already created. which creates unwanted timeout. > >> > >> There is a comment in there about sleep for "HUGE NUM" will probably > result in this issue, but I can't see why it won't occur also in the current > >> case. > >> > >> there is no change of this behaviour in the latest master. > >> i would appreciate any help, sun. > > > > Any reference to PID number is inherently racy. > > Not between parent and child. That's why zombies need reaping: a child > process > will not exit until the parent accepts its exit code and timing data via > wait() > (or itself exits). You can leave a zombie process lying around for > literally > years and the PID won't be reused while the zombie still exists. > > You can set SIGCHLD to SIG_IGN to allow your child processes to > asynchronously > self-reap, which can make it disappear out from under you. And that signal > mask > can be inherited by child processes, just like you can leak filehandles and > environment variables and tty state and cpu mask and nice level and a dozen > other things into your child process state: the parent process defines the > child > state back to PID 1. > > If a parent process ignores SIGCHLD and spawns child processes that run > timeout, > in that case the child process of the timeout could cycle out from under > timeout. I'd look for that in this instance. > > One workaround would would be timeout.c explicitly doing signal(SIGCHLD, > SIG_DFL) to correct its inherited signal mask, but the parent process > doing that > is pilot error, and that "fix" is about like a program using fcntl(SETFL) > to > strip O_NONBLOCK off stdout just in case it was called with broken standard > filehandles: that kind of defensive programming isn't generally part of > busybox. > > > There is no solution for > > your problem in the traditional POSIX API. > > The preponderance of the evidence is that the posix API people have used > for ~50 > years and sent into space and such can indeed work reliably for people who > know > how to use it. > > Next time you want to say "Linux/posix is fundamentally broken, there is no > solution in existing deployed kernels, this command busybox has had for 14 > years > can't ever have worked reliably and nobody noticed before", why not try > phrasing > it as a question instead of a statement of fact? > > Rob > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rob at landley.net Mon Feb 14 03:18:36 2022 From: rob at landley.net (Rob Landley) Date: Sun, 13 Feb 2022 21:18:36 -0600 Subject: suspected bug in timeout command In-Reply-To: References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> Message-ID: <6f887a30-a6ea-5a36-0c0f-7586544f037b@landley.net> On 2/13/22 1:31 AM, ??? ??? wrote: > Hey, first of all thanks for your answers and sorry for how I phrase my question. Sorry, looks like I may be the one who needs to apologize. (See below.) > Rob, I still need a clarification?if you don't mind. anything that you mention > is making sense to me if the timeout implementation here was that the actual > command is a child process of a process that doing the timeout logic. One way that wait() can become unreliable is if the child process inherited a signal mask from its parent (or grandparent) process with SIGCHLD ignored. Let's see what happens in that case, via this dumb little test program: $ cat blah.c #include #include #include #include #include #include int main(int argc, char *argv[]) { int pid, status = 0; signal(SIGCHLD, SIG_IGN); if (!(pid = fork())) {sleep(1); exit(1);} else { pid = wait(&status); printf("exited %d %d\n", pid, status); } exit(1); } So wait() blocks until the child exits, then returns -1 with status left at 0. Let's see what busybox */timeout.c is doing: int status; ... wait(&status); /* wait for child to die */ /* Did intermediate [v]fork or exec fail? */ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) return EXIT_FAILURE; Which means it's not checking wait's return value, and with a 0 status _WIFEXITED() returns... um, some grep -r under /usr/include says: #define __WEXITSTATUS(status) (((status) & 0xff00) >> 8) #define __WTERMSIG(status) ((status) & 0x7f) #define __WIFEXITED(status) (__WTERMSIG(status) == 0) So 0 reads as "it exited" and "exit status 0". So busybox timeout gets a false positive for success. (Except that "status" was uninitalized so it's only PROBABLY zero, not necessarily required to be. These days signal handlers have their own stack so it's probably clean if the call to this function is the first/deepest call made on the stack so far, which wouldn't necessarily be the case for busybox calling shell builtins... Anyway, if it doesn't EXIT_FAILURE it falls through to: /* Ok, exec a program as requested */ argv += optind; #if !BB_MMU argv[0] = sv1; argv[1] = sv2; #endif BB_EXECVP_or_die(argv); Wait, the PARENT process is execing the command line, but is doing so AFTER waiting for the child? What? The child is sending a kill signal to the parent process? Ok, that is EXACTLY the "cannot reliably work" that the other guy was replying to you, that's BONKERS. static NOINLINE int timeout_wait(int timeout, pid_t pid) { /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ ... if (kill(pid, 0)) { ... } And the caller is: /* Here we are grandchild. Sleep, then kill grandparent */ grandchild: if (timeout_wait(timeout, parent) == EXIT_SUCCESS) I just... no? It literally HAS A COMMENT saying that what it's doing won't work reliably? At this point, I think _I_ need some explanation about what's going on here. > which is the case for other implementations I saw (for example here > ) > but for the case of busybox implementation, the timeout is a child process of > the command it runs on (actually a grandchild), Yeah, sorry. That IS bonkers. The "this API cannot be used sanely" complaint was wrong, but "busybox is not using this API sanely" is ALSO wrong. To reliably monitor a process you either need to be its parent, or set up a similar relationship like containers, or ptrace it, or you can pull some tricks with a filehandle to its /proc/$PID contents... But not this. > so the case of process that > represents the command finish and its parent releasing its PID (via wait) can > occur, while the process that represents the timeout missing it. > and all this can happen while there is no case of ignoring the SIGCHLD. > am I wrong? My bad. I thought the busybox code here was sane. It does not appear to be. You're right: reversing the parent/child relationship like this CANNOT be reliable. I assumed busybox's implementation worked like the one I wrote at https://github.com/landley/toybox/blob/master/toys/other/timeout.c where the if (!pid) does the exec() and the else case handles waiting, and it just uses an alarm timer to interrupt itself. But apparently not? (Sorry I didn't check earlier, but I don't usually look at busybox code anymore because I work on a project under a non-GPL license and don't want to get sued.) Rob From ska-dietlibc at skarnet.org Sat Feb 12 23:12:09 2022 From: ska-dietlibc at skarnet.org (Laurent Bercot) Date: Sat, 12 Feb 2022 23:12:09 +0000 Subject: suspected bug in timeout command In-Reply-To: <1679c9d6-d668-2801-9b37-e7337ad3023b@intellitree.com> References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> <689f8b62-8299-361c-c83f-618bd9ea4abf@intellitree.com> <1679c9d6-d668-2801-9b37-e7337ad3023b@intellitree.com> Message-ID: >/* We want to create a grandchild which will watch > * and kill the grandparent. Other methods: > * making parent watch child disrupts parent<->child link > * (example: "tcpsvd 0.0.0.0 1234 timeout service_prog" - > * it's better if service_prog is a child of tcpsvd!), > * making child watch parent results in programs having > * unexpected children. */ > >I don't follow this reasoning. Does "disrupts the parent<->child link" just about sending signals? If the timeout app relays all signals from itself to the child, what remaining problems would exist? Yeah, that's clearly a misdesign. Keeping the same pid for the end of a Bernstein chain whenever possible is a good idea, so the intention is good - but it's only possible when the child is *entirely transparent* wrt control flow. It's a good model, for instance, for ssh-agent, or for a data processor such as a TLS tunnel (that's how s6-tlsd operates); but here, since the child actually impacts control (it sends a signal to the parent on timeout) it's just not applicable - and this thread illustrates exactly why. To really fix the bug, timeout should be rewritten, and run as the parent, and possibly forward signals to the child. -- Laurent From spareproject776 at gmail.com Mon Feb 14 13:20:21 2022 From: spareproject776 at gmail.com (Spare Project) Date: Mon, 14 Feb 2022 13:20:21 +0000 Subject: CONFIG_FEATURE_UNIX_LOCAL Message-ID: Using busybox and dropbear trying to blag unix socket forwarding without installing more software. nc -l local:/tmp/socket doesn?t create any socket ? httpd -p local:/tmp/testing on the other hand does create a socket Is this just a bug in busybox ? Or am I doing something wrong. Will try and have a look at the code itself but I?m not even close to competent enough to think I?ll get anywhere. -------------- next part -------------- An HTML attachment was scrubbed... URL: From roberto.foglietta at gmail.com Mon Feb 14 16:00:22 2022 From: roberto.foglietta at gmail.com (Roberto A. Foglietta) Date: Mon, 14 Feb 2022 17:00:22 +0100 Subject: suspected bug in timeout command In-Reply-To: <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> Message-ID: Il giorno sab 12 feb 2022 alle ore 02:41 Raffaello D. Di Napoli ha scritto: > > > On 2/11/22 16:22, Rob Landley wrote: > > On 2/9/22 11:12 AM, Baruch Siach wrote: > >> Hi Sun, > >> > >> On Wed, Feb 09 2022, ??? ??? wrote: > >>> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly to a process of mine. I debugged it until I found > >>> it from the timeout process which was assigned before to another process with the same pid. (i'm using a lot of timeouts for a lot of jobs) > >>> so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check the timeout status. I suspect at this time the > >>> process timeout monitoring is terminated, but another one with the same pid is already created. which creates unwanted timeout. > >>> > >>> There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I can't see why it won't occur also in the current > >>> case. > >>> > >>> there is no change of this behaviour in the latest master. > >>> i would appreciate any help, sun. > >> Any reference to PID number is inherently racy. > > Not between parent and child. > > Except in BB?s timeout, the relationship is not parent/child :) > > Much to my surprise, I?ll say that. When I read the bug report the other > day, I thought to myself well, this one ought to be easy to fix. But no, > there?s no SIGCHLD to be handled, no relationship between processes to > be leveraged. > > I don?t think this bug can be fixed without a near-complete rewrite, or > without doing a lot of procfs digging to really validate the waited-on > process, since kill(pid, 0) only validates a pid, not a process. https://github.com/brgl/busybox/blob/master/miscutils/timeout.c This is the code under inspection: grandchild: /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ while (1) { sleep(1); if (--timeout <= 0) break; if (kill(parent, 0)) { /* process is gone */ return EXIT_SUCCESS; } } kill(parent, signo); return EXIT_SUCCESS; After all, it might conduct to a PID-race only if the same pid is reused within a second. Which means that 32768-N processes are created in less than a second. Where N is the running processes in the system. Best regards, -- Roberto A. Foglietta +39.349.33.30.697 From roberto.foglietta at gmail.com Mon Feb 14 16:09:41 2022 From: roberto.foglietta at gmail.com (Roberto A. Foglietta) Date: Mon, 14 Feb 2022 17:09:41 +0100 Subject: suspected bug in timeout command In-Reply-To: References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> Message-ID: Il giorno lun 14 feb 2022 alle ore 17:00 Roberto A. Foglietta ha scritto: > > Il giorno sab 12 feb 2022 alle ore 02:41 Raffaello D. Di Napoli > ha scritto: > > > > > > On 2/11/22 16:22, Rob Landley wrote: > > > On 2/9/22 11:12 AM, Baruch Siach wrote: > > >> Hi Sun, > > >> > > >> On Wed, Feb 09 2022, ??? ??? wrote: > > >>> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue with a sigterm send randomly to a process of mine. I debugged it until I found > > >>> it from the timeout process which was assigned before to another process with the same pid. (i'm using a lot of timeouts for a lot of jobs) > > >>> so i looked at the code, "timeout.c" file where it sleep for 1 second in each iteration then check the timeout status. I suspect at this time the > > >>> process timeout monitoring is terminated, but another one with the same pid is already created. which creates unwanted timeout. > > >>> > > >>> There is a comment in there about sleep for "HUGE NUM" will probably result in this issue, but I can't see why it won't occur also in the current > > >>> case. > > >>> > > >>> there is no change of this behaviour in the latest master. > > >>> i would appreciate any help, sun. > > >> Any reference to PID number is inherently racy. > > > Not between parent and child. > > > > Except in BB?s timeout, the relationship is not parent/child :) > > > > Much to my surprise, I?ll say that. When I read the bug report the other > > day, I thought to myself well, this one ought to be easy to fix. But no, > > there?s no SIGCHLD to be handled, no relationship between processes to > > be leveraged. > > > > I don?t think this bug can be fixed without a near-complete rewrite, or > > without doing a lot of procfs digging to really validate the waited-on > > process, since kill(pid, 0) only validates a pid, not a process. > > https://github.com/brgl/busybox/blob/master/miscutils/timeout.c > > This is the code under inspection: > > grandchild: > /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ > while (1) { > sleep(1); > if (--timeout <= 0) > break; > if (kill(parent, 0)) { > /* process is gone */ > return EXIT_SUCCESS; > } > } > kill(parent, signo); > return EXIT_SUCCESS; > > After all, it might conduct to a PID-race only if the same pid is > reused within a second. Which means that 32768-N processes are created > in less than a second. Where N is the running processes in the system. The number of pids could be hugely increased up to 2^22 = 4,194,304 on a 64 bits platform. This does not resolve the issue but it makes it hugely less probable. However, if this bug shows-up, probably it means that the system has a lot of processes running and a lot of processes created and destroyed compared to the max PID available. Thus, the system might be incorrectly configured compared with its typical usage which probably is the main reason because nobody complained before. https://stackoverflow.com/questions/6294133/maximum-pid-in-linux Best regards, -- Roberto A. Foglietta +39.349.33.30.697 From sun681 at gmail.com Mon Feb 14 16:20:59 2022 From: sun681 at gmail.com (=?UTF-8?B?16HXkNefINei157XqA==?=) Date: Mon, 14 Feb 2022 18:20:59 +0200 Subject: suspected bug in timeout command In-Reply-To: References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> Message-ID: Im in not wrong linux use a simple allocation method for pid?d were it just set the next pid to last pid allocated + 1. Then check if its free and if not keep adding until found free one. A process can be created few minutes before it exits and meanwhile the pid?s are continuing and wrap around to the point that at the moment it release is the exact same moment when the next_pid is the same one as the process that just exits. ?????? ??? ??, 14 ????? 2022 ?-18:01 ??? Roberto A. Foglietta < roberto.foglietta at gmail.com>: > Il giorno sab 12 feb 2022 alle ore 02:41 Raffaello D. Di Napoli > ha scritto: > > > > > > On 2/11/22 16:22, Rob Landley wrote: > > > On 2/9/22 11:12 AM, Baruch Siach wrote: > > >> Hi Sun, > > >> > > >> On Wed, Feb 09 2022, ??? ??? wrote: > > >>> Hi, I'm using busybox for a while now (v1.29.2). and I had an issue > with a sigterm send randomly to a process of mine. I debugged it until I > found > > >>> it from the timeout process which was assigned before to another > process with the same pid. (i'm using a lot of timeouts for a lot of jobs) > > >>> so i looked at the code, "timeout.c" file where it sleep for 1 > second in each iteration then check the timeout status. I suspect at this > time the > > >>> process timeout monitoring is terminated, but another one with the > same pid is already created. which creates unwanted timeout. > > >>> > > >>> There is a comment in there about sleep for "HUGE NUM" will probably > result in this issue, but I can't see why it won't occur also in the current > > >>> case. > > >>> > > >>> there is no change of this behaviour in the latest master. > > >>> i would appreciate any help, sun. > > >> Any reference to PID number is inherently racy. > > > Not between parent and child. > > > > Except in BB?s timeout, the relationship is not parent/child :) > > > > Much to my surprise, I?ll say that. When I read the bug report the other > > day, I thought to myself well, this one ought to be easy to fix. But no, > > there?s no SIGCHLD to be handled, no relationship between processes to > > be leveraged. > > > > I don?t think this bug can be fixed without a near-complete rewrite, or > > without doing a lot of procfs digging to really validate the waited-on > > process, since kill(pid, 0) only validates a pid, not a process. > > https://github.com/brgl/busybox/blob/master/miscutils/timeout.c > > This is the code under inspection: > > grandchild: > /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ > while (1) { > sleep(1); > if (--timeout <= 0) > break; > if (kill(parent, 0)) { > /* process is gone */ > return EXIT_SUCCESS; > } > } > kill(parent, signo); > return EXIT_SUCCESS; > > After all, it might conduct to a PID-race only if the same pid is > reused within a second. Which means that 32768-N processes are created > in less than a second. Where N is the running processes in the system. > > Best regards, > -- > Roberto A. Foglietta > +39.349.33.30.697 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From roberto.foglietta at gmail.com Mon Feb 14 16:54:24 2022 From: roberto.foglietta at gmail.com (Roberto A. Foglietta) Date: Mon, 14 Feb 2022 17:54:24 +0100 Subject: suspected bug in timeout command In-Reply-To: References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> Message-ID: ?Il giorno lun 14 feb 2022 alle ore 17:21 ???? ????? ha scritto:? > > Im in not wrong linux use a simple allocation method for pid?d were it just set the next pid to last pid allocated + 1. Then check if its free and if not keep adding until found free one. A process can be created few minutes before it exits and meanwhile the pid?s are continuing and wrap around to the point that at the moment it release is the exact same moment when the next_pid is the same one as the process that just exits. While the timeout is sleeping for 1 second, the supervised PID process dies and another one process starts with the same PID, then the timeout wakes-up and checks for the PID then the race condition happens if the PID process will last longer than the expiring timeout. How much is probable the PID race condition? It related to these factors: - long timeout is used - a lot of processes is created - a lot of processes is running - small maximum PID is used It could happen despite any oddity, by design. That's true. However, it is not avoidable unless timeout does not establish a child-parent relationship with the surveilled process as shown by Rob. Best regards, -- Roberto A. Foglietta +39.349.33.30.697 From David.Laight at ACULAB.COM Mon Feb 14 16:57:22 2022 From: David.Laight at ACULAB.COM (David Laight) Date: Mon, 14 Feb 2022 16:57:22 +0000 Subject: suspected bug in timeout command In-Reply-To: References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> Message-ID: <1fc7c751b6cf49aeb1414a202336d5ca@AcuMS.aculab.com> Yes it does. But it is unlikely to happen in the short time between some kind of test that the process is the right one, and sending the signal. But hoping to see the process ?gone? on a 1 second poll is pretty useless. So if the process?s ?start time? is found (before any of the forks) that can be passed through to the grandchild and checked every second. Then you are very unlikely to kill the wrong process. If you also pass through the open directory fd to ?/proc/self? and use openat() to open whichever /proc/xx/yy file is needed then I think with a later kernel you?ll get an error is the process has died (and the pid reused) and you can also use it to send the signal ? avoiding the pid reuse race. Just a smop. David Im in not wrong linux use a simple allocation method for pid?d were it just set the next pid to last pid allocated + 1. Then check if its free and if not keep adding until found free one. A process can be created few minutes before it exits and meanwhile the pid?s are continuing and wrap around to the point that at the moment it release is the exact same moment when the next_pid is the same one as the process that just exits. - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) -------------- next part -------------- An HTML attachment was scrubbed... URL: From myh at live.com Tue Feb 15 05:05:02 2022 From: myh at live.com (Meng-Yuan Huang) Date: Tue, 15 Feb 2022 05:05:02 +0000 Subject: busybox-armv8l doesn't work on Apple M1 Message-ID: Hello. Some people said Apple M1 doesn't support arm32: https://news.ycombinator.com/item?id=27277351 In contrast, Raspberry Pi 4 SoC supports both arm32 and arm64. This difference results in Apple M1 can't run this busybox armv8l binary https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-armv8l but Raspberry Pi 4 can. This is the error log of executing busybox-armv8l on Ubuntu 21 arm64 on Apple M1. " myh at ubuntu:~$ wget https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-armv8l && chmod 755 busybox-armv8l && ./busybox-armv8l --2022-02-15 12:46:15-- https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-armv8l Resolving busybox.net (busybox.net)... 140.211.167.122 Connecting to busybox.net (busybox.net)|140.211.167.122|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 1148524 (1.1M) Saving to: ?busybox-armv8l? busybox-armv8l 100%[==================================================================>] 1.09M 1.05MB/s in 1.0s 2022-02-15 12:46:17 (1.05 MB/s) - ?busybox-armv8l? saved [1148524/1148524] bash: ./busybox-armv8l: cannot execute binary file: Exec format error myh at ubuntu:~$ file busybox-armv8l busybox-armv8l: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, stripped " Unfortunately, some downstream apps use the busybox-armv8l in their arm64 apps. For example, distroless container image: https://github.com/GoogleContainerTools/distroless/blob/6028308845393e394c650ce5c1332f8182451f17/busybox_archives.bzl#L19-L24 Thus, their apps work only on CPUs supporting both arm32 and arm64, not arm64 only CPUs as Apple M1. Could provide an arm64 busybox binary on busybox.net to help fixing this problem? Regards, Meng-Yuan Huang -------------- next part -------------- An HTML attachment was scrubbed... URL: From roberto.foglietta at gmail.com Tue Feb 15 05:41:09 2022 From: roberto.foglietta at gmail.com (Roberto A. Foglietta) Date: Tue, 15 Feb 2022 06:41:09 +0100 Subject: suspected bug in timeout command In-Reply-To: <5f1e935250bd46ef82a269b860fae073@AcuMS.aculab.com> References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> <689f8b62-8299-361c-c83f-618bd9ea4abf@intellitree.com> <1679c9d6-d668-2801-9b37-e7337ad3023b@intellitree.com> <5f1e935250bd46ef82a269b860fae073@AcuMS.aculab.com> Message-ID: Il Sab 12 Feb 2022, 14:13 David Laight ha scritto: > From: Michael Conrad > > Sent: 12 February 2022 12:59 > > > > On 2/12/22 07:38, Michael Conrad wrote: > > > Correctly using pidfd *still* requires that you be the parent process, > > > else the child could get reaped and replaced before the pidfd is > > > created. As far as I can tell, the only purpose of pidfd is for > > > waking on poll() instead of using signals, which is orthagonal to this > > > problem. > > Even if the pidfd can't be passed down, it lets you verify the process > information and then send the signal. > > > > I haven't looked at the source in busybox yet, but it boggles my mind > > > that it wouldn't just be a simple fork+alarm+waitpid because that is > > > literally the least code implementation, and race-free. > > > > > > -Mike C > > > > > Sorry for being lazy. I looked at the source and this is the reason: > > > > /* We want to create a grandchild which will watch > > * and kill the grandparent. Other methods: > > * making parent watch child disrupts parent<->child link > > * (example: "tcpsvd 0.0.0.0 1234 timeout service_prog" - > > * it's better if service_prog is a child of tcpsvd!), > > * making child watch parent results in programs having > > * unexpected children. */ > > > > I don't follow this reasoning. Does "disrupts the parent<->child link" > > just about sending signals? If the timeout app relays all signals from > > itself to the child, what remaining problems would exist? > > In that case you can pass 'verification information' through to > the grandchild. > > It could be an open fd of "/proc/self" - which allows the non-racy > kill on recent kernels. > But other information would allow the timing window be minimalised on > older kernels. > > ISTR that on older kernels an open fd to "proc/nn" always refers to the > current process with pid nn. But the actual behaviour is worth checking. > I think newer kernels will fail any reads after the process has exited. > Checking the procfs man page there is some mount options that do not allows reading other PID files in that filesystem. I am not 100% sure that a invitered file descriptor could not be read but negate access. Mount options The proc filesystem supports the following mount options: hidepid=n (since Linux 3.3) This option controls who can access the information in /proc/[pid] directories. The argument, n, is one of the following values: -------------- next part -------------- An HTML attachment was scrubbed... URL: From rob at landley.net Tue Feb 15 11:33:31 2022 From: rob at landley.net (Rob Landley) Date: Tue, 15 Feb 2022 05:33:31 -0600 Subject: suspected bug in timeout command In-Reply-To: References: <871r0cc5vn.fsf@tarshish> <1ca50691-71fd-f810-28be-cda8c3d73da5@landley.net> <2a4c26b8-8235-a2d4-db84-644d6130ba81@dinapo.li> Message-ID: On 2/14/22 10:09 AM, Roberto A. Foglietta wrote: > However, if this bug shows-up, probably it means that the system has > a lot of processes running and a lot of processes created and > destroyed compared to the max PID available. Thus, the system might be > incorrectly configured compared with its typical usage which probably > is the main reason because nobody complained before. Nah, a shell script can spin through an awful lot of PIDs pretty fast, and if you're doing a -j 8 build that has a lot of script snippets (let alone parallel autoconf etc) vs something with say a 10 second timeout? Entirely plausible, and not a sign of a system being misconfigured. PIDs get reused, fact of life, unix was already designed to cope back in the 1970s. Rob From neustradamus at hotmail.com Tue Feb 15 13:57:03 2022 From: neustradamus at hotmail.com (* Neustradamus *) Date: Tue, 15 Feb 2022 13:57:03 +0000 Subject: Busybox GitHub Message-ID: Hello all, I think it is needed to contact GitHub to recover https://github.com/busybox. What do you think? A team member can do it? Thanks in advance. Regards, Neustradamus From rob at landley.net Wed Feb 16 02:34:55 2022 From: rob at landley.net (Rob Landley) Date: Tue, 15 Feb 2022 20:34:55 -0600 Subject: Busybox GitHub In-Reply-To: References: Message-ID: On 2/15/22 7:57 AM, * Neustradamus * wrote: > Hello all, > > I think it is needed to contact GitHub to recover https://github.com/busybox. Busybox has never had an account on microsoft github that I am aware of? It hasn't got a facebook page either... Rob From ulrich.eckhardt at base-42.de Wed Feb 16 23:23:53 2022 From: ulrich.eckhardt at base-42.de (Ulrich Eckhardt) Date: Thu, 17 Feb 2022 00:23:53 +0100 Subject: grep: add option for better usability in pipelines Message-ID: <20220217002353.7f20d735@serenity> Greetings! I've implemented a `-p` flag for grep, which disables a behaviour that the exit status is used (abused?) to signal whether any match occurred. In many cases, you won't notice this. Also, in many cases, shell scripts don't check for errors. Now, for an example where it makes a difference. Consider a Bash script like this: # enable automatic error handling set -eo pipefail # check for string "issues" in a logfile cat logfile | grep issue | sort --unique If there are no issues in the logs, grep return exit code 1 and the shell interprets this as an error and exits itself. I've implemented that feature here, though it lacks tests yet: https://github.com/UlrichEckhardt/busybox/tree/grep-pipe-option Also, I'm currently trying to get the same feature into GNU grep as well, the long form `--pipe` is used there. I've also considered `--filter` (because it only filters) as alternative. I'm not fully happy with either one, maybe someone here comes up with a better suggestion. If you want, grab the first commit in there, it just fixes a small typo. I'd be happy to hear any suggestions! Cheers! Uli From explorer09 at gmail.com Thu Feb 17 00:32:06 2022 From: explorer09 at gmail.com (Kang-Che Sung) Date: Thu, 17 Feb 2022 08:32:06 +0800 Subject: grep: add option for better usability in pipelines In-Reply-To: <20220217002353.7f20d735@serenity> References: <20220217002353.7f20d735@serenity> Message-ID: On Thu, Feb 17, 2022 at 8:01 AM Ulrich Eckhardt wrote: > > I've implemented a `-p` flag for grep, which disables a behaviour that > the exit status is used (abused?) to signal whether any match > occurred. The behaviour is POSIX. > Now, for an example where it makes a difference. Consider a Bash script > like this: > > # enable automatic error handling > set -eo pipefail > # check for string "issues" in a logfile > cat logfile | grep issue | sort --unique > > If there are no issues in the logs, grep return exit code 1 and the > shell interprets this as an error and exits itself. > Why do we need to implement a workaround in grep while you can do this in shell to ignore the exit code of grep? { grep issue I've implemented that feature here, though it lacks tests yet: > https://github.com/UlrichEckhardt/busybox/tree/grep-pipe-option > Also, I'm currently trying to get the same feature into GNU grep as > well, the long form `--pipe` is used there. I've also considered > `--filter` (because it only filters) as alternative. I'm not fully > happy with either one, maybe someone here comes up with a better > suggestion. I don't see the '--pipe' option in GNU grep manual and I don't think it would be needed considering that you can tell the shell to ignore an exit code already. From mconrad at intellitree.com Thu Feb 17 04:50:09 2022 From: mconrad at intellitree.com (Michael Conrad) Date: Thu, 17 Feb 2022 04:50:09 +0000 (UTC) Subject: grep: add option for better usability in pipelines In-Reply-To: References: <20220217002353.7f20d735@serenity> Message-ID: <02788237-44a9-1e48-1fcd-15f92e9f9efb@intellitree.com> On 2/16/22 19:32, Kang-Che Sung wrote: > >> Now, for an example where it makes a difference. Consider a Bash script >> like this: >> >> # enable automatic error handling >> set -eo pipefail >> # check for string "issues" in a logfile >> cat logfile | grep issue | sort --unique >> >> If there are no issues in the logs, grep return exit code 1 and the >> shell interprets this as an error and exits itself. >> > Why do we need to implement a workaround in grep while you can > do this in shell to ignore the exit code of grep? > > { grep issue References: <20220217002353.7f20d735@serenity> Message-ID: <20220217082725.05bb0eb9@serenity> On Thu, 17 Feb 2022 08:32:06 +0800 Kang-Che Sung wrote: > On Thu, Feb 17, 2022 at 8:01 AM Ulrich Eckhardt > wrote: > > Now, for an example where it makes a difference. Consider a Bash > > script like this: > > > > # enable automatic error handling > > set -eo pipefail > > # check for string "issues" in a logfile > > cat logfile | grep issue | sort --unique > > > > If there are no issues in the logs, grep return exit code 1 and the > > shell interprets this as an error and exits itself. > > > > Why do we need to implement a workaround in grep while you can > do this in shell to ignore the exit code of grep? > > { grep issue > I've implemented that feature here, though it lacks tests yet: > > https://github.com/UlrichEckhardt/busybox/tree/grep-pipe-option > > Also, I'm currently trying to get the same feature into GNU grep as > > well, the long form `--pipe` is used there. I've also considered > > `--filter` (because it only filters) as alternative. I'm not fully > > happy with either one, maybe someone here comes up with a better > > suggestion. > > I don't see the '--pipe' option in GNU grep manual > Misunderstanding: It's not in there! I have it implemented already and I'm trying to get it incorporated there, which takes time due to FSF paperwork. Cheers! Uli From explorer09 at gmail.com Thu Feb 17 07:32:46 2022 From: explorer09 at gmail.com (Kang-Che Sung) Date: Thu, 17 Feb 2022 15:32:46 +0800 Subject: grep: add option for better usability in pipelines In-Reply-To: <02788237-44a9-1e48-1fcd-15f92e9f9efb@intellitree.com> References: <20220217002353.7f20d735@serenity> <02788237-44a9-1e48-1fcd-15f92e9f9efb@intellitree.com> Message-ID: On Thu, Feb 17, 2022 at 12:50 PM Michael Conrad wrote: > > On 2/16/22 19:32, Kang-Che Sung wrote: > > > >> Now, for an example where it makes a difference. Consider a Bash script > >> like this: > >> > >> # enable automatic error handling > >> set -eo pipefail > >> # check for string "issues" in a logfile > >> cat logfile | grep issue | sort --unique > >> > >> If there are no issues in the logs, grep return exit code 1 and the > >> shell interprets this as an error and exits itself. > >> > > Why do we need to implement a workaround in grep while you can > > do this in shell to ignore the exit code of grep? > > > > { grep issue > In order to implement his suggestion, you need to only ignore exit code > 1, while still allowing other exit codes to abort the script. (like a > system error while reading the file) { grep issue But also, I've never seen ":" used as a command... where is that > documented? Is it equivalent to 'true'? https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.71/html_node/Limitations-of-Builtins.html Look for the "true" section. From explorer09 at gmail.com Thu Feb 17 07:48:42 2022 From: explorer09 at gmail.com (Kang-Che Sung) Date: Thu, 17 Feb 2022 15:48:42 +0800 Subject: grep: add option for better usability in pipelines In-Reply-To: <20220217082725.05bb0eb9@serenity> References: <20220217002353.7f20d735@serenity> <20220217082725.05bb0eb9@serenity> Message-ID: On Thu, Feb 17, 2022 at 3:27 PM Ulrich Eckhardt wrote: > > > > Why do we need to implement a workaround in grep while you can > > do this in shell to ignore the exit code of grep? > > > > { grep issue > `grep -p ...` rather replaces `grep ... || test $? = 1`. The advantage > is that it is explicit about what it does. Understanding the intent of > `-p` or `--pipe` is easier than understanding the alternative. > Unless you can propose the '-p' option to POSIX will busybox implement it as you say. The problem here is portability. FreeBSD grep (https://www.freebsd.org/cgi/man.cgi?query=grep) has a different meaning with '-p' so it won't be portable to use '-p' in shell scripts. And the long option '--pipe' isn't quite helpful either as it would end up being a GNU-only extension and so is discouraged to use in shell scripts (which defeats the purpose of your '--pipe' option in the first place). From bernd at petrovitsch.priv.at Thu Feb 17 08:40:03 2022 From: bernd at petrovitsch.priv.at (Bernd Petrovitsch) Date: Thu, 17 Feb 2022 09:40:03 +0100 Subject: grep: add option for better usability in pipelines In-Reply-To: <20220217082725.05bb0eb9@serenity> References: <20220217002353.7f20d735@serenity> <20220217082725.05bb0eb9@serenity> Message-ID: <10df817f-82e5-fc0d-7b17-10135d9c381a@petrovitsch.priv.at> Hi all! On 17.02.2022 08:27, Ulrich Eckhardt wrote: > On Thu, 17 Feb 2022 08:32:06 +0800 > Kang-Che Sung wrote: >> On Thu, Feb 17, 2022 at 8:01 AM Ulrich Eckhardt >> wrote: >>> Now, for an example where it makes a difference. Consider a Bash >>> script like this: >>> >>> # enable automatic error handling >>> set -eo pipefail >>> # check for string "issues" in a logfile >>> cat logfile | grep issue | sort --unique And useless use of cat .... [...] >> Why do we need to implement a workaround in grep while you can >> do this in shell to ignore the exit code of grep? >> >> { grep issue > `grep -p ...` rather replaces `grep ... || test $? = 1`. The advantage > is that it is explicit about what it does. Understanding the intent of > `-p` or `--pipe` is easier than understanding the alternative. 1st: It's quite the opposite: The alternative is, not POSIX and not even existent in GNU-grep. The : exists in /bin/sh as a built-in since 2 generations and no need to look up some new option. 2nd: busybox is about size - not featuritis (aka bloat). Kind regards, Bernd From walter.lozano at collabora.com Fri Feb 18 15:33:46 2022 From: walter.lozano at collabora.com (Walter Lozano) Date: Fri, 18 Feb 2022 12:33:46 -0300 Subject: [PATCH v2] Improve support for long options to grep In-Reply-To: <86bc00ba-ae3e-5f45-0b33-28c7bdac8f56@collabora.com> References: <20220126141415.1029575-1-walter.lozano@collabora.com> <59592e2f08fc45f8a972359dba04ef5f@AcuMS.aculab.com> <06f9d2c1-897f-10e3-9ede-3d6513b04c89@collabora.com> <86bc00ba-ae3e-5f45-0b33-28c7bdac8f56@collabora.com> Message-ID: On 1/26/22 16:12, Walter Lozano wrote: > > > On 1/26/22 15:38, Xabier Oneca -- xOneca wrote: >> Hi Walter, >> >> ???? > There is also unnecessary duplication of source code. >> ???? > >> ???? > Just use a #define and C string concatenation to add the extra >> ???? > long option strings. >> >> ??? Yes, I totally agree you. However I used this approach since a >> previous >> ??? patch I submitted was rewritten in this way [1] when applying to >> master. >> >> >> Maybe a better approach is to always use getopt32long, as it is >> converted to getopt32 if LONG_OPTS is not enabled. Maybe Denys forgot >> about this. >> See libbb.h: >> https://git.busybox.net/busybox/tree/include/libbb.h#n1351 >> > > Thank you for the pointer. Yes, it looks much cleaner to always use > getopt32long, not sure if there was some reason I'm not aware to try to > avoid it. > Denys any preference in how to handle this to move things forwards? Regards, -- Walter Lozano Collabora Ltd. From d+busybox at adaptive-enterprises.com Sun Feb 20 15:00:32 2022 From: d+busybox at adaptive-enterprises.com (David Leonard) Date: Mon, 21 Feb 2022 01:00:32 +1000 (AEST) Subject: [PATCH] tsort: new applet Message-ID: <82qrn0s-8q67-6r98-rqs-r4376r59r88n@nqncgvir-ragrecevfrf.pbz> Hi, I was recently after tsort to do some init ordering on a small system. Hope this patch is acceptable. Thanks, David function old new delta packed_usage 34414 34433 +19 applet_main 3192 3200 +8 applet_names 2747 2753 +6 tsort_main 737 +737 --- coreutils/tsort.c | 196 +++++++++++++++++++++++++++++++++++++ docs/posix_conformance.txt | 2 +- testsuite/tsort.tests | 110 +++++++++++++++++++++ 3 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 coreutils/tsort.c create mode 100755 testsuite/tsort.tests -------------- next part -------------- A non-text attachment was scrubbed... Name: busybox-tsort.patch Type: text/x-diff Size: 9286 bytes Desc: URL: From farmatito at tiscali.it Sun Feb 20 16:11:41 2022 From: farmatito at tiscali.it (tito) Date: Sun, 20 Feb 2022 17:11:41 +0100 Subject: [PATCH] tsort: new applet In-Reply-To: <82qrn0s-8q67-6r98-rqs-r4376r59r88n@nqncgvir-ragrecevfrf.pbz> References: <82qrn0s-8q67-6r98-rqs-r4376r59r88n@nqncgvir-ragrecevfrf.pbz> Message-ID: <20220220171141.714e853a@devuan> On Mon, 21 Feb 2022 01:00:32 +1000 (AEST) David Leonard wrote: > > > Hi, > I was recently after tsort to do some init ordering on a small system. > Hope this patch is acceptable. > Thanks, > David > > > function old new delta > packed_usage 34414 34433 +19 > applet_main 3192 3200 +8 > applet_names 2747 2753 +6 > tsort_main 737 +737 > --- > coreutils/tsort.c | 196 +++++++++++++++++++++++++++++++++++++ > docs/posix_conformance.txt | 2 +- > testsuite/tsort.tests | 110 +++++++++++++++++++++ > 3 files changed, 307 insertions(+), 1 deletion(-) > create mode 100644 coreutils/tsort.c > create mode 100755 testsuite/tsort.tests Hi, some minor fixes inline. Ciao, Tito From d398d3dbfd8d1356137d574fd168a61cf58898c2 Mon Sep 17 00:00:00 2001 From: David Leonard Date: Sun, 20 Feb 2022 14:29:45 +1000 Subject: [PATCH] tsort: new applet function old new delta packed_usage 34414 34433 +19 applet_main 3192 3200 +8 applet_names 2747 2753 +6 tsort_main 737 +737 --- coreutils/tsort.c | 196 +++++++++++++++++++++++++++++++++++++ docs/posix_conformance.txt | 2 +- testsuite/tsort.tests | 110 +++++++++++++++++++++ 3 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 coreutils/tsort.c create mode 100755 testsuite/tsort.tests diff --git a/coreutils/tsort.c b/coreutils/tsort.c new file mode 100644 index 000000000..242273156 --- /dev/null +++ b/coreutils/tsort.c @@ -0,0 +1,196 @@ +/* vi: set sw=4 ts=4: */ +/* + * tsort implementation for busybox + * + * public domain -- David Leonard, 2022 + */ +//config:config TSORT +//config: bool "tsort (0.7 kb)" +//config: default n +//config: help +//config: tsort performs a topological sort. + +//applet:IF_TSORT(APPLET(tsort, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_TSORT) += tsort.o + +/* BB_AUDIT SUSv3 compliant */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/tsort.html */ + +//usage:#define tsort_trivial_usage +//usage: "[FILE]" +//usage:#define tsort_full_usage "\n\n" +//usage: "Topological sort\n" +//usage:#define tsort_example_usage +//usage: "$ echo -e \"a b\\nb c\" | tsort\n" +//usage: "a\n" +//usage: "b\n" +//usage: "c\n" + +#include "libbb.h" +#include "common_bufsiz.h" + +struct node { + unsigned int in_count; + unsigned int out_count; + struct node **out; + char name[]; +}; + +struct globals { + struct node **nodes; + unsigned int nodes_len; +}; +#define G (*(struct globals*)bb_common_bufsiz1) +#define INIT_G() do { \ + setup_common_bufsiz(); \ + BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \ + G.nodes = NULL; \ + G.nodes_len = 0; \ +} while (0) + +static struct node * +get_node(const char *name) +{ + struct node *n; + unsigned int a = 0; + unsigned int b = G.nodes_len; + + /* binry search for name */ Typo binry -> binary + while (a != b) { + unsigned int m = (a + b) / 2; + int cmp = strcmp(name, G.nodes[m]->name); + if (cmp == 0) { + return G.nodes[m]; + } else if (cmp < 0) { + b = m; + } else { + a = m + 1; + } + } + + /* allocate new node */ + n = xmalloc(sizeof *n + strlen(name) + 1); + n->in_count = 0; + n->out_count = 0; + n->out = NULL; + strcpy(n->name, name); + + /* insert to maintain sort */ + G.nodes = xrealloc(G.nodes, (G.nodes_len + 1) * sizeof *G.nodes); + memmove(&G.nodes[a + 1], &G.nodes[a], + (G.nodes_len - a) * sizeof *G.nodes); + G.nodes[a] = n; + G.nodes_len++; + return n; +} + +static void +add_edge(struct node *a, struct node *b) +{ + a->out = xrealloc(a->out, (a->out_count + 1) * sizeof *a->out); + a->out[a->out_count++] = b; + b->in_count++; +} + +int tsort_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int tsort_main(int argc UNUSED_PARAM, char **argv) +{ + const char *input_filename = "stdin"; + FILE *in = stdin; + char *line; + size_t linesz; + ssize_t len; + struct node *a; + int cycles; + + INIT_G(); + + if (argv[1]) { + if (argv[2]) { + bb_show_usage(); + } + input_filename = argv[1]; + if (input_filename[0] != '-' || input_filename[1]) { + close(STDIN_FILENO); /* == 0 */ + xopen(input_filename, O_RDONLY); /* fd will be 0 */ + } + } + + /* Read in words separated by s */ + a = NULL; + line = NULL; + linesz = 0; + while ((len = getline(&line, &linesz, in)) != -1) { + char *s = line; + while (*(s = skip_whitespace(s))) { + struct node *b; + char *word; + + word = s; + s = skip_non_whitespace(s); + if (*s) { + *s++ = '\0'; + } + + /* Create nodes and edges for each word pair */ + b = get_node(word); + if (!a) { + a = b; + } else { + if (a != b) { + add_edge(a, b); + } + a = NULL; + } + } + } + die_if_ferror(in, input_filename); + if (a) { + bb_simple_error_msg_and_die("odd input"); + } + free(line); + + /* + * Kahn's algorithm: + * - find a node that has no incoming edges, print and remove it + * - repeat until the graph is empty + * - if any nodes are left, they form cycles. + */ + cycles = 0; + while (G.nodes_len) { + struct node *n; + unsigned int i; + + /* Search for first node with no incoming edges */ + for (i = 0; i < G.nodes_len; i++) { + if (!G.nodes[i]->in_count) { + break; + } + } + if (i == G.nodes_len) { + /* Must be a cycle; arbitraily break it at node 0 */ + cycles++; + i = 0; +#ifndef TINY bb_error_msg("cycle at %s", G.nodes[i]->name); + fprintf(stderr, "tsort: cycle at %s\n", G.nodes[i]->name); +#endif + } + + /* Remove the node (need no longer maintain sort) */ + n = G.nodes[i]; + G.nodes[i] = G.nodes[--G.nodes_len]; + + /* And remove its outgoing edges */ + for (i = 0; i < n->out_count; i++) { + n->out[i]->in_count--; + } + free(n->out); + + puts(n->name); + free(n); + } + free(G.nodes); + + fflush_stdout_and_exit(cycles ? 1 : 0); +} From d+busybox at adaptive-enterprises.com Sun Feb 20 23:58:55 2022 From: d+busybox at adaptive-enterprises.com (David Leonard) Date: Mon, 21 Feb 2022 09:58:55 +1000 (AEST) Subject: [PATCH] tsort: new applet In-Reply-To: <20220220171141.714e853a@devuan> References: <82qrn0s-8q67-6r98-rqs-r4376r59r88n@nqncgvir-ragrecevfrf.pbz> <20220220171141.714e853a@devuan> Message-ID: <788o3p8p-r677-sn2n-3p33-n33so48o97rs@nqncgvir-ragrecevfrf.pbz> Thanks. Patch fixed, attached. By the way, is this the right default for config? > +//config: default n David On Sun, 20 Feb 2022, tito wrote: > some minor fixes inline. ... > + /* binry search for name */ > > Typo binry -> binary ... > +#ifndef TINY > > bb_error_msg("cycle at %s", G.nodes[i]->name); > > + fprintf(stderr, "tsort: cycle at %s\n", G.nodes[i]->name); > +#endif -------------- next part -------------- A non-text attachment was scrubbed... Name: tsort2.patch Type: text/x-diff Size: 9296 bytes Desc: URL: From bitsmaker at gmail.com Wed Feb 23 15:36:16 2022 From: bitsmaker at gmail.com (Bobby Mah) Date: Wed, 23 Feb 2022 08:36:16 -0700 Subject: Drop privileges for udhcp Message-ID: Hello folks! I would like udhcp to use setuid so that it can drop privileges after the server socket is built. However, the server socket is inside a loop and is re-created every time there's a bad packet. I am proposing moving the server socket out of the loop and letting udhcp die when a bad packet arrives. This way I can add the ability to drop the privileges after the server socket is created. Is there a reason to continue re-creating the server socket after a bad packet arrives? If not, then will the change I propose be deemed acceptable? Thanks, Bobby -------------- next part -------------- An HTML attachment was scrubbed... URL: From ghanson at arista.com Wed Feb 23 16:14:24 2022 From: ghanson at arista.com (Geoff Hanson) Date: Wed, 23 Feb 2022 08:14:24 -0800 Subject: udhcpc6 expects string for bootfile-param opt(60) In-Reply-To: References: <45cca76e-f2ec-078c-b60a-d1af9a8f91e7@petrovitsch.priv.at> Message-ID: Just following up on this patch. Are there any more comments on this? Thanks, Geoff On Tue, Feb 8, 2022 at 11:58 AM Geoff Hanson wrote: > Any further feedback on this? > > Anything more I need to do or is what I've provided sufficient for the bug > report? > > Thanks, > Geoff > > On Tue, Feb 1, 2022 at 12:53 PM Geoff Hanson wrote: > >> Hi Bernd. Can you look at my second attachment? As part of addressing the >> issue Xabier reported, >> I switched to using memcpy. >> >> Thanks, >> Geoff >> >> On Tue, Feb 1, 2022 at 12:36 PM Bernd Petrovitsch < >> bernd at petrovitsch.priv.at> wrote: >> >>> -Hi all! >>> >>> On 01.02.2022 18:12, Geoff Hanson wrote: >>> [...]> In most cases, there's no printf directive so this just means it's >>> > copying the string. >>> >>> Using some user-provided string as a format-string opens the possibility >>> ofexploits - since decades .... >>> > But this would cause problems in the case where the string did contain >>> %'s. >>> >>> So why just not only use strncpy(), strlcpy(), memcpy() or similar? >>> >>> Kind regards, >>> Bernd >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From steffen at sdaoden.eu Wed Feb 23 20:19:13 2022 From: steffen at sdaoden.eu (Steffen Nurpmeso) Date: Wed, 23 Feb 2022 21:19:13 +0100 Subject: Drop privileges for udhcp In-Reply-To: References: Message-ID: <20220223201913.s9Kg_%steffen@sdaoden.eu> Bobby Mah wrote in : |Hello folks! | |I would like udhcp to use setuid so that it can drop privileges after the |server socket is built. However, the server socket is inside a loop and is |re-created every time there's a bad packet. | |I am proposing moving the server socket out of the loop and letting udhcp |die when a bad packet arrives. This way I can add the ability to drop the |privileges after the server socket is created. | |Is there a reason to continue re-creating the server socket after a bad |packet arrives? If not, then will the change I propose be deemed accepta\ |ble? Ah and if you only could do something against the sleeps. That would be a miracle. --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt) From vda.linux at googlemail.com Fri Feb 25 17:13:30 2022 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Fri, 25 Feb 2022 18:13:30 +0100 Subject: CONFIG_FEATURE_UNIX_LOCAL In-Reply-To: References: Message-ID: On Mon, Feb 14, 2022 at 2:20 PM Spare Project wrote: > Using busybox and dropbear trying to blag unix socket forwarding without installing more software. > > nc -l local:/tmp/socket doesn?t create any socket ? Incorrect syntax. Should be: nc -l -s local:/tmp/socket From ariadne at dereferenced.org Sat Feb 26 18:11:30 2022 From: ariadne at dereferenced.org (Ariadne Conill) Date: Sat, 26 Feb 2022 18:11:30 +0000 Subject: [PATCH] ash: use memmove instead of mempcpy in subevalvar Message-ID: <20220226181130.6750-1-ariadne@dereferenced.org> While investigating a sporadic crash issue relating to variable substitution in Alpine Linux, we managed to get a reliable crash when building BusyBox with ASan, due to the source and destination overlapping for mempcpy, which resulted in sporadic data corruption outside ASan. Per POSIX, memcpy is not allowed to overlap source and destination, as mempcpy is a GNU-specific extension to mempcpy, the same semantics can be assumed. Accordingly, we use memmove instead, which does not have this limitation. Signed-off-by: Ariadne Conill --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index adb0f223a..6f256d4c3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7187,7 +7187,7 @@ subevalvar(char *start, char *str, int strloc, len = orig_len - pos; if (!quotes) { - loc = mempcpy(startp, startp + pos, len); + loc = memmove(startp, startp + pos, len); } else { for (vstr = startp; pos != 0; pos--) { if ((unsigned char)*vstr == CTLESC) -- 2.35.1 From hadrien.lacour at posteo.net Sat Feb 26 18:43:00 2022 From: hadrien.lacour at posteo.net (Hadrien Lacour) Date: Sat, 26 Feb 2022 18:43:00 +0000 Subject: [PATCH] ash: use memmove instead of mempcpy in subevalvar In-Reply-To: <20220226181130.6750-1-ariadne@dereferenced.org> References: <20220226181130.6750-1-ariadne@dereferenced.org> Message-ID: <20220226184300.b2wwslqxi4oo5o24@gentoo-zen5900x> On Sat, Feb 26, 2022 at 06:11:30PM +0000, Ariadne Conill wrote: > While investigating a sporadic crash issue relating to variable substitution in > Alpine Linux, we managed to get a reliable crash when building BusyBox with ASan, > due to the source and destination overlapping for mempcpy, which resulted in > sporadic data corruption outside ASan. > > Per POSIX, memcpy is not allowed to overlap source and destination, as mempcpy > is a GNU-specific extension to mempcpy, the same semantics can be assumed. > Accordingly, we use memmove instead, which does not have this limitation. > > Signed-off-by: Ariadne Conill > --- > shell/ash.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/shell/ash.c b/shell/ash.c > index adb0f223a..6f256d4c3 100644 > --- a/shell/ash.c > +++ b/shell/ash.c > @@ -7187,7 +7187,7 @@ subevalvar(char *start, char *str, int strloc, > len = orig_len - pos; > > if (!quotes) { > - loc = mempcpy(startp, startp + pos, len); > + loc = memmove(startp, startp + pos, len); > } else { > for (vstr = startp; pos != 0; pos--) { > if ((unsigned char)*vstr == CTLESC) > -- > 2.35.1 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > http://lists.busybox.net/mailman/listinfo/busybox Looks like the returned pointer isn't the same between the two functions; shouldn't it be `loc = memmove(...) + len` instead ? From ariadne at dereferenced.org Sat Feb 26 18:52:38 2022 From: ariadne at dereferenced.org (Ariadne Conill) Date: Sat, 26 Feb 2022 18:52:38 +0000 Subject: [PATCH v2] ash: use memmove instead of mempcpy in subevalvar Message-ID: <20220226185238.7792-1-ariadne@dereferenced.org> While investigating a sporadic crash issue relating to variable substitution in Alpine Linux, we managed to get a reliable crash when building BusyBox with ASan, due to the source and destination overlapping for mempcpy, which resulted in sporadic data corruption outside ASan. Per POSIX, memcpy is not allowed to overlap source and destination, as mempcpy is a GNU-specific extension to mempcpy, the same semantics can be assumed. Accordingly, we use memmove instead, which does not have this limitation. v2: Forgot to emulate mempcpy's dest+size return value, fixed. Signed-off-by: Ariadne Conill --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index adb0f223a..056954059 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7187,7 +7187,7 @@ subevalvar(char *start, char *str, int strloc, len = orig_len - pos; if (!quotes) { - loc = mempcpy(startp, startp + pos, len); + loc = memmove(startp, startp + pos, len) + len; } else { for (vstr = startp; pos != 0; pos--) { if ((unsigned char)*vstr == CTLESC) -- 2.35.1 From David.Laight at ACULAB.COM Sat Feb 26 22:09:47 2022 From: David.Laight at ACULAB.COM (David Laight) Date: Sat, 26 Feb 2022 22:09:47 +0000 Subject: [PATCH v2] ash: use memmove instead of mempcpy in subevalvar In-Reply-To: <20220226185238.7792-1-ariadne@dereferenced.org> References: <20220226185238.7792-1-ariadne@dereferenced.org> Message-ID: <082d47fef08446e59a2ddee483850d8f@AcuMS.aculab.com> From: busybox > Sent: 26 February 2022 18:53 > > While investigating a sporadic crash issue relating to variable substitution in > Alpine Linux, we managed to get a reliable crash when building BusyBox with ASan, > due to the source and destination overlapping for mempcpy, which resulted in > sporadic data corruption outside ASan. > > Per POSIX, memcpy is not allowed to overlap source and destination, as mempcpy > is a GNU-specific extension to mempcpy, the same semantics can be assumed. > Accordingly, we use memmove instead, which does not have this limitation. > > v2: Forgot to emulate mempcpy's dest+size return value, fixed. > > Signed-off-by: Ariadne Conill > --- > shell/ash.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/shell/ash.c b/shell/ash.c > index adb0f223a..056954059 100644 > --- a/shell/ash.c > +++ b/shell/ash.c > @@ -7187,7 +7187,7 @@ subevalvar(char *start, char *str, int strloc, > len = orig_len - pos; > > if (!quotes) { > - loc = mempcpy(startp, startp + pos, len); > + loc = memmove(startp, startp + pos, len) + len; I'd just not rely on the return value at all. Juat add: loc = startp + len; before of after the call. I'm actually intrigued that ash has picked up a glibc function I thought it was portable? The 'best' ash bug (which might now be fixed in the main sources) was running on the beginning of an on-stack buffer when removing the '\n' from the end of long $(....) substitutions. It usually just failed to remove a '\n', but it could remove an extra character - most likely on BE systems. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) From rob at landley.net Sun Feb 27 09:55:37 2022 From: rob at landley.net (Rob Landley) Date: Sun, 27 Feb 2022 03:55:37 -0600 Subject: FYI, Denys is from Ukraine. Message-ID: <828169c1-0c88-7e74-5094-018e29d356d7@landley.net> He moved out after college and last I heard he's living in Czech republic, but you might want to give him a little extra leeway on email response times right now anyway. Rob From ariadne at dereferenced.org Sun Feb 27 15:18:57 2022 From: ariadne at dereferenced.org (Ariadne Conill) Date: Sun, 27 Feb 2022 15:18:57 +0000 Subject: [PATCH] ash: use memmove instead of mempcpy in subevalvar Message-ID: <20220227151857.9266-1-ariadne@dereferenced.org> While investigating a sporadic crash issue relating to variable substitution in Alpine Linux, we managed to get a reliable crash when building BusyBox with ASan, due to the source and destination overlapping for mempcpy, which resulted in sporadic data corruption outside ASan. Per POSIX, memcpy is not allowed to overlap source and destination, as mempcpy is a GNU-specific extension to mempcpy, the same semantics can be assumed. Accordingly, we use memmove instead, which does not have this limitation. v2: Forgot to emulate mempcpy's dest+size return value, fixed. v3: Incorporate feedback from David Laight. Signed-off-by: Ariadne Conill --- shell/ash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index adb0f223a..8acd2d32e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7187,7 +7187,8 @@ subevalvar(char *start, char *str, int strloc, len = orig_len - pos; if (!quotes) { - loc = mempcpy(startp, startp + pos, len); + memmove(startp, startp + pos, len); + loc = startp + len; } else { for (vstr = startp; pos != 0; pos--) { if ((unsigned char)*vstr == CTLESC) -- 2.35.1 From soeren at soeren-tempel.net Mon Feb 28 07:36:50 2022 From: soeren at soeren-tempel.net (soeren at soeren-tempel.net) Date: Mon, 28 Feb 2022 08:36:50 +0100 Subject: [PATCH] ash: don't read past end of var in subvareval for bash substitutions Message-ID: <20220228073649.16485-1-soeren@soeren-tempel.net> From: S?ren Tempel Without this patch, BusyBox handles bash pattern substitutions without a terminating '/' character incorrectly. Consider the following shell script: _bootstrapver=5.0.211-r0 _referencesdir="/usr/${_bootstrapver/-*}/Sources" echo $_referencesdir This should output `/usr/5.0.211/Sources`. However, without this patch it instead outputs `/usr/5.0.211Sources`. This is due to the fact that BusyBox expects the bash pattern substitutions to always be terminated with a '/' (at least in this part of subvareval) and thus reads passed the substitution itself and consumes the '/' character which is part of the literal string. If there is no '/' after the substitution then BusyBox might perform an out-of-bounds read under certain circumstances. When replacing the bash pattern substitution with `${_bootstrapver/-*/}`, or with this patch applied, ash outputs the correct value. Signed-off-by: S?ren Tempel --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index adb0f223a..8097d51c3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7077,7 +7077,7 @@ subevalvar(char *start, char *str, int strloc, repl = NULL; break; } - if (*repl == '/') { + if (*repl == '/' || (unsigned char)*repl == CTLENDVAR) { *repl = '\0'; break; }