From ximo at planells.ie Thu Jan 1 22:37:18 2026 From: ximo at planells.ie (Ximo Planells Lerma) Date: Thu, 1 Jan 2026 22:37:18 +0000 Subject: [PATCH] Fix build when using -DVERSION_WITH_WRITEV Message-ID: <20260101223719.528975-1-ximo@planells.ie> echo.c and verror_msg.c have alternative implementations using writev but the code does not compile when the flag is defined because the non-writev code is still present so it fails due to double definition of echo_main and bb_verror_msg. This commit adds the appropriate #ifndef to both files to allow the compilation to finish successfully with and without the VERSION_WITH_WRITEV flag. Also it includes the that is needed to use writev. It can be tested with the following command and then running the echo applet: % make EXTRA_CFLAGS="-DVERSION_WITH_WRITEV" The code for the writev version may have been broken for 14+ years according to the git history so deleting it is another option. Signed-off-by: Ximo Planells Lerma --- coreutils/echo.c | 4 +++- libbb/verror_msg.c | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/coreutils/echo.c b/coreutils/echo.c index 2a48d4a90..2fb2e1948 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c @@ -80,6 +80,7 @@ * But this function is not standard. */ +#ifndef VERSION_WITH_WRITEV int echo_main(int argc UNUSED_PARAM, char **argv) { char **pp; @@ -194,6 +195,7 @@ int echo_main(int argc UNUSED_PARAM, char **argv) return err; } +#else // #ifndef VERSION_WITH_WRITEV /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. @@ -233,7 +235,6 @@ int echo_main(int argc UNUSED_PARAM, char **argv) * @(#)echo.c 8.1 (Berkeley) 5/31/93 */ -#ifdef VERSION_WITH_WRITEV /* We can't use stdio. * The reason for this is highly non-obvious. * echo_main is used from shell. Shell must correctly handle "echo foo" @@ -245,6 +246,7 @@ int echo_main(int argc UNUSED_PARAM, char **argv) * * Using writev instead, with 'direct' conversion of argv vector. */ +#include int echo_main(int argc, char **argv) { diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 74b608f4c..49b87d394 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -11,12 +11,17 @@ # include #endif +#ifdef VERSION_WITH_WRITEV +# include +#endif + #if ENABLE_FEATURE_SYSLOG static smallint syslog_level = LOG_ERR; #endif smallint logmode = LOGMODE_STDIO; const char *msg_eol = "\n"; +#ifndef VERSION_WITH_WRITEV void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) { char *msg, *msg1; @@ -97,7 +102,7 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) free(msg); } -#ifdef VERSION_WITH_WRITEV +#else // #ifdef VERSION_WITH_WRITEV /* Code size is approximately the same, but currently it's the only user * of writev in entire bbox. __libc_writev in uclibc is ~50 bytes. */ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) -- 2.34.1 From sertonix at posteo.net Thu Jan 1 23:04:32 2026 From: sertonix at posteo.net (Sertonix) Date: Thu, 01 Jan 2026 23:04:32 +0000 Subject: [PATCH] wget: fix --post-file with NUL bytes Message-ID: function old new delta wget_main 3444 3490 +46 .rodata 100926 100930 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 50/0) Total: 50 bytes --- networking/wget.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index ec3767793..8d2f9792c 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -252,6 +252,7 @@ struct globals { char *dir_prefix; #if ENABLE_FEATURE_WGET_LONG_OPTIONS char *post_data; + size_t post_size; char *post_file; char *extra_headers; unsigned char user_headers; /* Headers mentioned by the user */ @@ -1262,8 +1263,11 @@ static void download_one_url(const char *url) if (option_mask32 & WGET_OPT_POST_FILE) { int fd = xopen_stdin(G.post_file); - G.post_data = xmalloc_read(fd, NULL); + G.post_size = INT_MAX - 4095; + G.post_data = xmalloc_read(fd, &G.post_size); close(fd); + } else if (G.post_data) { + G.post_size = strlen(G.post_data); } if (G.post_data) { @@ -1274,11 +1278,11 @@ static void download_one_url(const char *url) ); } SENDFMT(sfp, - "Content-Length: %u\r\n" - "\r\n" - "%s", - (int) strlen(G.post_data), G.post_data + "Content-Length: %zu\r\n" + "\r\n", + G.post_size ); + fwrite(G.post_data, 1, G.post_size, sfp); } else #endif { -- 2.52.0 From wharms at bfs.de Mon Jan 12 12:57:14 2026 From: wharms at bfs.de (Walter Harms) Date: Mon, 12 Jan 2026 12:57:14 +0000 Subject: AW: [PATCH v2 1/1] wget: don't allow control characters or spaces in the URL In-Reply-To: <20251121092118.3562853-2-radoslav.kolev@suse.com> References: <20251121092118.3562853-1-radoslav.kolev@suse.com>, <20251121092118.3562853-2-radoslav.kolev@suse.com> Message-ID: <0574fc69dc4c4158ba99e76f27ea9ac1@bfs.de> did you consider isprint() (or friends) ? jm2c wh ________________________________________ Von: busybox im Auftrag von Radoslav Kolev Gesendet: Freitag, 21. November 2025 10:21:18 An: busybox at busybox.net Betreff: [PATCH v2 1/1] wget: don't allow control characters or spaces in the URL Fixes CVE-2025-60876 malicious URL can be used to inject HTTP headers in the request. Signed-off-by: Radoslav Kolev Reviewed-by: Emmanuel Deloget --- networking/wget.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/networking/wget.c b/networking/wget.c index ec3767793..fa555427b 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -536,6 +536,15 @@ static void parse_url(const char *src_url, struct host_info *h) { char *url, *p, *sp; + /* Fix for CVE-2025-60876 - don't allow control characters or spaces in the URL */ + /* otherwise a malicious URL can be used to inject HTTP headers in the request */ + const unsigned char *u = (void *) src_url; + while (*u) { + if (*u <= ' ') + bb_simple_error_msg_and_die("Unencoded control character found in the URL!"); + u++; + } + free(h->allocated); h->allocated = url = xstrdup(src_url); -- 2.51.1 _______________________________________________ busybox mailing list busybox at busybox.net https://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Sun Jan 18 01:45:21 2026 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Sun, 18 Jan 2026 02:45:21 +0100 Subject: [PATCH] cmp: stop skipping bytes if EOF is reached In-Reply-To: <20251206105633.41651-1-giorgitchankvetadze1997@gmail.com> References: <20251206105633.41651-1-giorgitchankvetadze1997@gmail.com> Message-ID: Applied, thank you On Sat, Dec 6, 2025 at 11:57?AM Giorgi Tchankvetadze wrote: > > Currently, if a skip value is larger than the file size, cmp will continue > to loop and call getc() until the skip count is satisfied, even though > EOF has been reached. > > For large skip values (e.g., 1 billion), this results in significant > CPU waste and execution time (e.g., 11 seconds on a modern CPU). > > This patch checks for EOF inside the skip loop and breaks early. > > Test case: > $ touch empty.txt > $ time ./busybox cmp empty.txt empty.txt 1000000000 1000000000 > > Before: > real 0m10.937s > > After: > real 0m0.002s > > Signed-off-by: Giorgi Tchankvetadze > --- > editors/cmp.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/editors/cmp.c b/editors/cmp.c > index ea86a2736..89539f8cf 100644 > --- a/editors/cmp.c > +++ b/editors/cmp.c > @@ -113,8 +113,8 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) > fmt = fmt_differ; > > if (ENABLE_DESKTOP) { > - while (skip1) { getc(fp1); skip1--; } > - while (skip2) { getc(fp2); skip2--; } > + while (skip1) { if (getc(fp1) == EOF) break; skip1--; } > + while (skip2) { if (getc(fp2) == EOF) break; skip2--; } > } > do { > if (max_count >= 0 && --max_count < 0) > -- > 2.47.3 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > https://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Sun Jan 18 02:10:52 2026 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Sun, 18 Jan 2026 03:10:52 +0100 Subject: [PATCH] md5/sha1sum: Honor the -b flag in the output In-Reply-To: <20251205224104.61464-1-martin@martin.st> References: <20251205224104.61464-1-martin@martin.st> Message-ID: Applied, thank you! On Fri, Dec 5, 2025 at 11:41?PM Martin Storsj? wrote: > > The output of md5sum/sha1sum contains a character to indicate > what mode was used to read the file - '*' for binary, and ' ' > for text or where binary is insignificant. > > This flag character makes a difference for the ffmpeg testsuite. > This testsuite contains a number of reference files (e.g. [1]), > containing the expected md5sum output for those files, which is > checked verbatim. > > By making busybox's md5sum honor this flag in the output, > ffmpeg's testsuite can run successfully on top of busybox. > > The flag is only partially implemented; in coreutils md5sum, > a later "-t" option overrides an earlier "-b" option. Here, > just check if a "-b" option was specified or not. Neither > flag affects how the files actually are read. > > [1] https://code.ffmpeg.org/FFmpeg/FFmpeg/src/commit/894da5ca7d742e4429ffb2af534fcda0103ef593/tests/ref/acodec/flac > > Signed-off-by: Martin Storsj? > --- > coreutils/md5_sha1_sum.c | 9 ++++++--- > testsuite/sha1sum.tests | 4 ++++ > 2 files changed, 10 insertions(+), 3 deletions(-) > > diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c > index 4506aeb56..3073ecddf 100644 > --- a/coreutils/md5_sha1_sum.c > +++ b/coreutils/md5_sha1_sum.c > @@ -159,6 +159,7 @@ enum { > #define FLAG_SILENT 1 > #define FLAG_CHECK 2 > #define FLAG_WARN 4 > +#define FLAG_BINARY 8 > > /* This might be useful elsewhere */ > static unsigned char *hash_bin_to_hex(unsigned char *hash_value, > @@ -277,13 +278,15 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv) > { > unsigned char *in_buf; > int return_value = EXIT_SUCCESS; > - unsigned flags; > + unsigned flags = 0; > #if ENABLE_SHA3SUM > unsigned sha3_width = 224; > #endif > > if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK) { > - /* -b "binary", -t "text" are ignored (shaNNNsum compat) */ > + /* -b "binary", -t "text" are mostly ignored (shaNNNsum compat); > + * the -b flag does set the '*' mode char in the output though, but > + * the -t flag doesn't override it. */ > /* -s and -w require -c */ > #if ENABLE_SHA3SUM > if (applet_name[3] == HASH_SHA3 && (!ENABLE_SHA384SUM || applet_name[4] != '8')) > @@ -375,7 +378,7 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv) > if (hash_value == NULL) { > return_value = EXIT_FAILURE; > } else { > - printf("%s %s\n", hash_value, *argv); > + printf("%s %c%s\n", hash_value, flags & FLAG_BINARY ? '*' : ' ', *argv); > free(hash_value); > } > } > diff --git a/testsuite/sha1sum.tests b/testsuite/sha1sum.tests > index e6ddb2a86..76c7f8288 100755 > --- a/testsuite/sha1sum.tests > +++ b/testsuite/sha1sum.tests > @@ -9,6 +9,10 @@ testing "sha1sum: one-space separated input for -c" \ > 'echo "da39a3ee5e6b4b0d3255bfef95601890afd80709 EMPTY" | sha1sum -c' \ > "EMPTY: OK\n" \ > "" "" > +testing "sha1sum: -b flag in output" \ > + 'sha1sum -b EMPTY' \ > + "da39a3ee5e6b4b0d3255bfef95601890afd80709 *EMPTY\n" \ > + "" "" > SKIP= > rm EMPTY > > -- > 2.43.0 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > https://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Sun Jan 18 02:20:17 2026 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Sun, 18 Jan 2026 03:20:17 +0100 Subject: [PATCH v3] adduser: remove preconfigured GECOS full name field In-Reply-To: <20251125134649.789586-1-achill@achill.org> References: <20251125134649.789586-1-achill@achill.org> Message-ID: Applied, thank you. On Tue, Nov 25, 2025 at 2:53?PM Achill Gilgenast wrote: > > Pre-configuring "Linux User" as Full Name is confusing a lot of users > downstream.[1] For example, in geary e-mails were sent out as "Linux > User"[2] and I also saw a couple of git commits with this name. This name > does not bring any more improvements than just leaving this field > empty, and let applications most likely fallback to the username. > > Alternative would be to set the field to `&` (Capitalized username, > according to passwd(5)) or that we just set the GECOS field downstream. > > [1] https://gitlab.postmarketos.org/postmarketOS/pmbootstrap/-/issues/2214 > [2] https://gitlab.gnome.org/GNOME/geary/-/issues/1486 > > Signed-off-by: Achill Gilgenast > --- > loginutils/adduser.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/loginutils/adduser.c b/loginutils/adduser.c > index d3c795afa48b..bfab05203241 100644 > --- a/loginutils/adduser.c > +++ b/loginutils/adduser.c > @@ -196,7 +196,7 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) > bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root); > } > > - pw.pw_gecos = (char *)"Linux User,,,"; > + pw.pw_gecos = (char *)""; > /* We assume that newly created users "inherit" root's shell setting */ > pw.pw_shell = xstrdup(get_shell_name()); /* might come from getpwnam(), need to make a copy */ > pw.pw_dir = NULL; > -- > 2.52.0 > _______________________________________________ > busybox mailing list > busybox at busybox.net > https://lists.busybox.net/mailman/listinfo/busybox From polzer at fastmail.com Sun Jan 18 02:32:00 2026 From: polzer at fastmail.com (Leslie P. Polzer) Date: Sun, 18 Jan 2026 10:32:00 +0800 Subject: =?UTF-8?Q?Re:_Fuzzing_harnesses_for_BusyBox_(OSS-Fuzz_prep)_=E2=80=94_wo?= =?UTF-8?Q?uld_this_be_welcome=3F?= In-Reply-To: <0e5eaa28-616c-450e-912e-65fc4b2d04ae@app.fastmail.com> References: <0e5eaa28-616c-450e-912e-65fc4b2d04ae@app.fastmail.com> Message-ID: <609b7495-3bc3-4aff-ba3e-ded7db6d92fe@app.fastmail.com> Greetings, this probably got lost in the holiday slump. Any views on this? Thanks! Leslie On Fri, Dec 19, 2025, at 5:11 PM, Leslie P. Polzer wrote: > Hi BusyBox maintainers, > > I?m preparing a small OSS-Fuzz integration effort for BusyBox > and wanted to check if you?d be open to fuzzing harnesses > living in-tree. > > The initial idea is a small directory with a `make fuzzers` target > (not built by default), and a couple of tiny harnesses focused on > libbb parsers (base64/base32 to start, then higher?value parsers > like archives/volume_id/httpd parsing). > > OSS-Fuzz can then fuzz continuously at no cost, finding bugs > before they become active exploits. > > Would this be welcome upstream? Happy to answer any questions. > > Thanks, > > Leslie -------------- next part -------------- An HTML attachment was scrubbed... URL: From vda.linux at googlemail.com Sun Jan 18 09:59:52 2026 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Sun, 18 Jan 2026 10:59:52 +0100 Subject: [PATCHv2] procps: new applet: vmstat In-Reply-To: <35p0or73-3n40-0099-4o7r-pp84spno20n3@nqncgvir-ragrecevfrf.pbz> References: <35p0or73-3n40-0099-4o7r-pp84spno20n3@nqncgvir-ragrecevfrf.pbz> Message-ID: Applied, thank you. On Thu, Nov 13, 2025 at 10:52?AM David Leonard wrote: > > > v2 > > * fixed small bugs in error handling, averaging > * fixed compiler warning > * removed some dev/debug code > > > Adds a compact vmstat applet that matches the default behaviour > of procps's vmstat. > > function old new delta > vmstat_main - 872 +872 > load_row - 852 +852 > print_row - 322 +322 > coldescs - 239 +239 > .rodata 99999 100119 +120 > find_col - 108 +108 > packed_usage 34738 34759 +21 > applet_main 3224 3232 +8 > applet_names 2782 2789 +7 > ------------------------------------------------------------------------------ > (add/remove: 6/0 grow/shrink: 4/0 up/down: 2549/0) Total: 2549 bytes > text data bss dec hex filename > 1052603 16691 1664 1070958 10576e busybox_old > 1055168 16699 1664 1073531 10617b busybox_unstripped > --- > procps/vmstat.c | 426 ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 426 insertions(+) > create mode 100644 procps/vmstat.c > > diff --git a/procps/vmstat.c b/procps/vmstat.c > new file mode 100644 > index 000000000..bccd27d63 > --- /dev/null > +++ b/procps/vmstat.c > @@ -0,0 +1,426 @@ > +/* vi: set sw=4 ts=4: */ > +/* > + * Report virtual memory statistics. > + * > + * Copyright (C) 2025 David Leonard > + * > + * Licensed under GPLv2, see file LICENSE in this source tree. > + */ > +//config:config VMSTAT > +//config: bool "vmstat (3 kb)" > +//config: default y > +//config: help > +//config: Report virtual memory statistics > + > +//applet:IF_VMSTAT(APPLET(vmstat, BB_DIR_BIN, BB_SUID_DROP)) > + > +//kbuild:lib-$(CONFIG_VMSTAT) += vmstat.o > + > +#include "libbb.h" > +#include "common_bufsiz.h" > + > +/* Must match option string! */ > +enum { > + OPT_n = 1 << 0, > +}; > + > +#define FROM_PROC_STAT "\1" > +#define FROM_PROC_STAT_CPU "\2" > +#define FROM_PROC_VMSTAT "\3" > +#define FROM_PROC_MEMINFO "\4" > +#define M_DELTA "\x81" /* differentiate */ > +#define M_DPERCENT "\x83" /* DELTA + sum and scale to 100 */ > +#define M_DECREMENT "\x84" /* decrement (exclude self proc) */ > +#define PSEUDO_SWPD "_1" /* SwapTotal - SwapFree */ > +#define PSEUDO_CACHE "_2" /* Cached + SReclaimable */ > + > +/* Column descriptors */ > +static const char coldescs[] = > + /* [grplabel\0] (\width label\0 from [m_mod] fromspec\0)+ */ > + "procs\0" "\2r\0" FROM_PROC_STAT M_DECREMENT "procs_running\0" > + "\2b\0" FROM_PROC_STAT "procs_blocked\0" > + "memory\0" "\6swpd\0" FROM_PROC_MEMINFO PSEUDO_SWPD "\0" > + "\6free\0" FROM_PROC_MEMINFO "MemFree\0" > + "\6buff\0" FROM_PROC_MEMINFO "Buffers\0" > + "\6cache\0" FROM_PROC_MEMINFO PSEUDO_CACHE "\0" > + "swap\0" "\4si\0" FROM_PROC_VMSTAT M_DELTA "pswpin\0" > + "\4so\0" FROM_PROC_VMSTAT M_DELTA "pswpout\0" > + "io\0" "\5bi\0" FROM_PROC_VMSTAT M_DELTA "pgpgin\0" > + "\5bo\0" FROM_PROC_VMSTAT M_DELTA "pgpgout\0" > + "system\0" "\4in\0" FROM_PROC_STAT M_DELTA "intr\0" > + "\4cs\0" FROM_PROC_STAT M_DELTA "ctxt\0" > + "cpu\0" "\2us\0" FROM_PROC_STAT_CPU M_DPERCENT "\x0d" /* user */ > + "\2sy\0" FROM_PROC_STAT_CPU M_DPERCENT "\x0b" /* system */ > + "\2id\0" FROM_PROC_STAT_CPU M_DPERCENT "\x04" /* idle */ > + "\2wa\0" FROM_PROC_STAT_CPU M_DPERCENT "\x05" /* iowait */ > + "\2st\0" FROM_PROC_STAT_CPU M_DPERCENT "\x08" /* steal */ > + "\2gu\0" FROM_PROC_STAT_CPU M_DPERCENT "\x0c" /* guest */ > + ; > + > +/* Packed row data from coldescs[] is decoded into this structure */ > +struct col { > + const char *grplabel; > + const char *label; > + const char *fromspec; > + unsigned char from; > + unsigned char width; > + unsigned char mod; > +#define MOD_DELTA 0x01 > +#define MOD_PERCENT 0x02 > +#define MOD_DECREMENT 0x04 > +}; > + > +/* Number of columns defined in coldescs[] */ > +#define NCOLS (2+4+2+2+2+6) > + > +/* Globals. Sort by size and access frequency. */ > +struct globals { > + unsigned data1[NCOLS]; > + unsigned data2[NCOLS]; > +}; > +#define G (*(struct globals*)bb_common_bufsiz1) > +#define INIT_G() do { \ > + /* memset(&G, 0, sizeof G); */ \ > +} while (0) > + > + > +//usage:#define vmstat_trivial_usage > +//usage: "[-n] [INTERVAL [COUNT]]" > +//usage:#define vmstat_full_usage "\n\n" > +//usage: "Report virtual memory statistics\n" > +//usage: "\n -n Display the header only once" > + > +/* > + * Advance an iterator over the coldescs[] packed descriptors. > + * col_return - pointer to storage to hold the next unpacked descriptor. > + * cp - pointer to iterator storage; should be initialised with coldescs. > + * Returns 1 when *cp has been advanced, and *col_return filled > + * (i.e. col_return->label will not be NULL). > + * Returns 0 when coldescs[] has been exhausted, and sets col_return->label > + * and col_return->grplabel to NULL. > + */ > +static ALWAYS_INLINE bool next_col(struct col *col_return, const char **cp) > +{ > + if (!**cp) { > + col_return->label = NULL; > + col_return->grplabel = NULL; > + return 0; > + } > + if (**cp > ' ') { > + /* Only the first column of a group gets the grplabel */ > + col_return->grplabel = *cp; > + while (*(*cp)++) > + ; /* Skip over the grplabel */ > + } else > + col_return->grplabel = NULL; > + col_return->width = *(*cp)++; > + col_return->label = *cp; > + while (*(*cp)++) > + ; /* Skip over the label */ > + col_return->from = *(*cp)++; > + if (**cp & 0x80) > + col_return->mod = *(*cp)++; > + else > + col_return->mod = 0; > + col_return->fromspec = *cp; > + while (*(*cp)++ >= ' ') > + ; /* Skip over the fromspec */ > + return 1; > +} > + > +/* Compares two fromspec strings for equality. > + * A fromspec can be a C string, or be terminated inclusively with > + * a byte 1..31. */ > +static bool fromspec_equal(const char *fs1, const char *fs2) > +{ > + while (*fs1 == *fs2) { > + if (*fs1 < ' ') > + return 1; > + fs1++; > + fs2++; > + } > + return 0; > + > +} > + > +/* > + * Finds a column in coldescs[] that has the the given from and fromspec. > + * Returns the index if found, otherwise -1. > + */ > +static int find_col(unsigned char from, const char *fromspec) > +{ > + const char *coli; > + struct col col; > + int i; > + > + for (i = 0, coli = coldescs; next_col(&col, &coli); i++) > + if (col.from == from && > + fromspec_equal(col.fromspec, fromspec)) > + return i; > + return -1; > +} > + > +/* > + * Reads current system state into the data array elements corresponding > + * to coldescs[] columns. > + */ > +static void load_row(unsigned data[static NCOLS]) > +{ > + FILE *fp; > + char label[32]; > + char line[256]; > + int colnum; > + unsigned SwapFree = 0; > + unsigned SwapTotal = 0; > + unsigned Cached = 0; > + unsigned SReclaimable = 0; > + > + memset(data, 0, NCOLS * sizeof *data); > + > + /* > + * Open each FROM_* source and read all their items. These are > + * generally labeled integer items. As we read each item, hunt > + * through coldescs[] to see if a column uses it and, if one does, > + * store the item's value in the corresponding data[] element. > + */ > + > + /* FROM_PROC_STAT and FROM_PROC_STAT_CPU */ > + fp = xfopen_for_read("/proc/stat"); > + while (fgets(line, sizeof(line), fp)) { > + enum stat_cpu { > + STAT_CPU_user = 1, > + STAT_CPU_nice = 2, > + STAT_CPU_system = 3, > + STAT_CPU_idle = 4, > + STAT_CPU_iowait = 5, > + STAT_CPU_irq = 6, > + STAT_CPU_softirq = 7, > + STAT_CPU_steal = 8, > + STAT_CPU_guest = 9, /* included in user */ > + STAT_CPU_guest_nice = 10, /* included in nice */ > + /* computed columns */ > + STAT_CPU_pseudo_sy = 0xb, /* system + irq + softirq */ > + STAT_CPU_pseudo_gu = 0xc, /* guest + guest_nice */ > + STAT_CPU_pseudo_us = 0xd, /* user + nice - pseudo_gu */ > + _STAT_CPU_max > + }; > + unsigned num[_STAT_CPU_max]; > + int n = sscanf(line, > + "%31s %u %u %u %u %u %u %u %u %u %u", > + label, > + &num[STAT_CPU_user], > +# define _STAT_CPU_first STAT_CPU_user > + &num[STAT_CPU_nice], > + &num[STAT_CPU_system], > + &num[STAT_CPU_idle], > + &num[STAT_CPU_iowait], > + &num[STAT_CPU_irq], > + &num[STAT_CPU_softirq], > + &num[STAT_CPU_steal], > + &num[STAT_CPU_guest], > + &num[STAT_CPU_guest_nice]); > + if (n == 11 && strcmp(label, "cpu") == 0) { > + const char *coli; > + struct col col; > + int i; > + > + num[STAT_CPU_pseudo_sy] = num[STAT_CPU_system] > + + num[STAT_CPU_irq] > + + num[STAT_CPU_softirq] > + ; > + num[STAT_CPU_pseudo_gu] = num[STAT_CPU_guest] > + + num[STAT_CPU_guest_nice] > + ; > + num[STAT_CPU_pseudo_us] = num[STAT_CPU_user] > + + num[STAT_CPU_nice] > + - num[STAT_CPU_pseudo_gu] > + ; > + for (i = 0, coli = coldescs; next_col(&col, &coli); i++) > + if (col.from == *FROM_PROC_STAT_CPU) > + data[i] = num[(int)*col.fromspec]; > + } > + else if (n >= 2 && > + (colnum = find_col(*FROM_PROC_STAT, label)) != -1) > + data[colnum] = num[_STAT_CPU_first]; > + } > + fclose(fp); > + > + /* FROM_PROC_VMSTAT */ > + fp = xfopen_for_read("/proc/vmstat"); > + while (fgets(line, sizeof(line), fp)) { > + unsigned num; > + > + if (sscanf(line, "%31s %u", label, &num) == 2 && > + (colnum = find_col(*FROM_PROC_VMSTAT, label)) != -1) > + data[colnum] = num; > + } > + fclose(fp); > + > + /* FROM_PROC_MEMINFO */ > + fp = xfopen_for_read("/proc/meminfo"); > + while (fgets(line, sizeof(line), fp)) { > + unsigned num; > + > + if (sscanf(line, "%31[^:]: %u", label, &num) == 2) { > + /* Store some values for computed (pseudo) values */ > + if (strcmp(label, "SwapTotal") == 0) > + SwapTotal = num; > + else if (strcmp(label, "SwapFree") == 0) > + SwapFree = num; > + else if (strcmp(label, "Cached") == 0) > + Cached = num; > + else if (strcmp(label, "SReclaimable") == 0) > + SReclaimable = num; > + > + if ((colnum = find_col(*FROM_PROC_MEMINFO, > + label)) != -1) > + data[colnum] = num; > + } > + } > + fclose(fp); > + > + /* "Pseudo" items computed from other items */ > + if ((colnum = find_col(*FROM_PROC_MEMINFO, PSEUDO_SWPD)) != -1) > + data[colnum] = SwapTotal - SwapFree; > + if ((colnum = find_col(*FROM_PROC_MEMINFO, PSEUDO_CACHE)) != -1) > + data[colnum] = Cached + SReclaimable; > +} > + > +/* Modify, format and print a row of data values */ > +static void print_row(const unsigned data[static NCOLS], > + const unsigned old_data[static NCOLS]) > +{ > + const char *coli; > + struct col col; > + smalluint i; > + bool is_first; > + unsigned percent_sum = 0; > + > + for (coli = coldescs, i = 0; next_col(&col, &coli); i++) > + if (col.mod & MOD_PERCENT) { > + unsigned value = data[i]; > + if (col.mod & MOD_DELTA) > + value -= old_data[i]; > + percent_sum += value; > + } > + > + is_first = 1; > + for (coli = coldescs, i = 0; next_col(&col, &coli); i++) { > + unsigned value = data[i]; > + > + if (col.mod & MOD_DELTA) > + value -= old_data[i]; > + if (col.mod & MOD_PERCENT) > + value = percent_sum ? 100 * value / percent_sum : 0; > + if ((col.mod & MOD_DECREMENT) && value) > + value--; > + printf(" %*u" + is_first, col.width, value); > + is_first = 0; > + } > + bb_putchar('\n'); > +} > + > +/* Print column header rows */ > +static void print_header(void) > +{ > + const char *coli; > + struct col col; > + bool is_first; > + > + /* First header row is the group labels */ > + coli = coldescs; > + next_col(&col, &coli); > + is_first = 1; > + while (col.label) { > + const char *grplabel = col.grplabel; > + smalluint gllen = strlen(grplabel); > + smalluint grpwidth = col.width; > + smalluint nhy = 0; > + > + /* Sum the column widths */ > + next_col(&col, &coli); > + while (col.label && !col.grplabel) { > + grpwidth += 1 + col.width; > + next_col(&col, &coli); > + } > + > + if (is_first) > + is_first = 0; > + else > + bb_putchar(' '); > + > + /* Centre the grplabel within grpwidth hyphens. */ > + while (gllen < grpwidth) { > + bb_putchar('-'); > + grpwidth--; > + if (gllen < grpwidth) > + grpwidth--, nhy++; > + } > + while (*grplabel) > + bb_putchar(*grplabel++); > + while (nhy--) > + bb_putchar('-'); > + } > + bb_putchar('\n'); > + > + /* Second header row is right-justified column labels */ > + coli = coldescs; > + is_first = 1; > + while (next_col(&col, &coli)) { > + printf(" %*s" + is_first, col.width, col.label); > + is_first = 0; > + } > + bb_putchar('\n'); > +} > + > +int vmstat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; > +int vmstat_main(int argc UNUSED_PARAM, char **argv) > +{ > + int opt; > + unsigned interval = 0; > + int count = 1; > + unsigned height = 24; > + unsigned rows; > + > + INIT_G(); > + > + /* Parse and process arguments */ > + opt = getopt32(argv, "n"); > + argv += optind; > + > + if (*argv) { > + interval = xatoi_positive(*argv); > + count = (interval != 0 ? -1 : 1); > + argv++; > + if (*argv) > + count = xatoi_positive(*argv); > + } > + > + /* Prepare to re-print the header row after it scrolls off */ > + if (opt & OPT_n) > + height = 0; > + else > + get_terminal_width_height(STDOUT_FILENO, NULL, &height); > + > + /* Main loop */ > + for (rows = 0;; rows++) { > + if (!rows || (height > 5 && (rows % (height - 3)) == 0)) > + print_header(); > + > + /* Flip between using data1/2 and data2/1 for old/new */ > + if (rows & 1) { > + load_row(G.data1); > + print_row(G.data1, G.data2); > + } else { > + load_row(G.data2); > + print_row(G.data2, G.data1); > + } > + > + if (count > 0 && --count == 0) > + break; > + > + sleep(interval); > + } > + > + return EXIT_SUCCESS; > +} > -- > 2.43.0 > > _______________________________________________ > busybox mailing list > busybox at busybox.net > https://lists.busybox.net/mailman/listinfo/busybox From achill at achill.org Sun Jan 18 16:02:20 2026 From: achill at achill.org (Achill Gilgenast) Date: Sun, 18 Jan 2026 17:02:20 +0100 Subject: [PATCH v3] adduser: remove preconfigured GECOS full name field In-Reply-To: References: <20251125134649.789586-1-achill@achill.org> Message-ID: On Sun Jan 18, 2026 at 3:20 AM CET, Denys Vlasenko wrote: > Applied, thank you. Thank you very much! :3 > > On Tue, Nov 25, 2025 at 2:53?PM Achill Gilgenast wrote: >> >> Pre-configuring "Linux User" as Full Name is confusing a lot of users >> downstream.[1] For example, in geary e-mails were sent out as "Linux >> User"[2] and I also saw a couple of git commits with this name. This name >> does not bring any more improvements than just leaving this field >> empty, and let applications most likely fallback to the username. >> >> Alternative would be to set the field to `&` (Capitalized username, >> according to passwd(5)) or that we just set the GECOS field downstream. >> >> [1] https://gitlab.postmarketos.org/postmarketOS/pmbootstrap/-/issues/2214 >> [2] https://gitlab.gnome.org/GNOME/geary/-/issues/1486 >> >> Signed-off-by: Achill Gilgenast >> --- >> loginutils/adduser.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/loginutils/adduser.c b/loginutils/adduser.c >> index d3c795afa48b..bfab05203241 100644 >> --- a/loginutils/adduser.c >> +++ b/loginutils/adduser.c >> @@ -196,7 +196,7 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) >> bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root); >> } >> >> - pw.pw_gecos = (char *)"Linux User,,,"; >> + pw.pw_gecos = (char *)""; >> /* We assume that newly created users "inherit" root's shell setting */ >> pw.pw_shell = xstrdup(get_shell_name()); /* might come from getpwnam(), need to make a copy */ >> pw.pw_dir = NULL; >> -- >> 2.52.0 >> _______________________________________________ >> busybox mailing list >> busybox at busybox.net >> https://lists.busybox.net/mailman/listinfo/busybox From vda.linux at googlemail.com Mon Jan 19 12:48:05 2026 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Mon, 19 Jan 2026 13:48:05 +0100 Subject: =?UTF-8?Q?Re=3A_Fuzzing_harnesses_for_BusyBox_=28OSS=2DFuzz_prep=29_?= =?UTF-8?Q?=E2=80=94_would_this_be_welcome=3F?= In-Reply-To: <609b7495-3bc3-4aff-ba3e-ded7db6d92fe@app.fastmail.com> References: <0e5eaa28-616c-450e-912e-65fc4b2d04ae@app.fastmail.com> <609b7495-3bc3-4aff-ba3e-ded7db6d92fe@app.fastmail.com> Message-ID: Good day Laslie, Sounds interesting. Show the patch when it's ready. On Sun, Jan 18, 2026 at 3:41?AM Leslie P. Polzer wrote: > > Greetings, > > this probably got lost in the holiday slump. > > Any views on this? > > Thanks! > > Leslie > > > On Fri, Dec 19, 2025, at 5:11 PM, Leslie P. Polzer wrote: > > Hi BusyBox maintainers, > > I?m preparing a small OSS-Fuzz integration effort for BusyBox > and wanted to check if you?d be open to fuzzing harnesses > living in-tree. > > The initial idea is a small directory with a `make fuzzers` target > (not built by default), and a couple of tiny harnesses focused on > libbb parsers (base64/base32 to start, then higher?value parsers > like archives/volume_id/httpd parsing). > > OSS-Fuzz can then fuzz continuously at no cost, finding bugs > before they become active exploits. > > Would this be welcome upstream? Happy to answer any questions. > > Thanks, > > Leslie > > > _______________________________________________ > busybox mailing list > busybox at busybox.net > https://lists.busybox.net/mailman/listinfo/busybox From gerickson at nuovations.com Mon Jan 19 19:19:52 2026 From: gerickson at nuovations.com (Grant Erickson) Date: Mon, 19 Jan 2026 11:19:52 -0800 Subject: [PATCH v5 1/1] syslogd: Add a configurable option to log timestamps in UTC. Message-ID: <20260119191952.3988409-1-gerickson@nuovations.com> This adds a configurable option 'FEATURE_SYSLOGD_UTC' enabling a command line option ('-u') that directs syslogd to log timestamps in Coordinated Universal Time (UTC) rather than in local time. --- sysklogd/syslogd.c | 61 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 2cbb22b6d1b4..40644fb97484 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -35,6 +35,15 @@ //config: This enables syslogd to rotate the message files //config: on his own. No need to use an external rotate script. //config: +//config:config FEATURE_SYSLOGD_UTC +//config: bool "Optionally log timestamps in UTC" +//config: default n +//config: depends on SYSLOGD +//config: help +//config: This enables a command line option ('-u') that directs +//config: syslogd to log timestamps in Coordinated Universal Time +//config: (UTC) rather than in local time. +//config: //config:config FEATURE_REMOTE_LOG //config: bool "Remote Log support" //config: default y @@ -147,6 +156,9 @@ //usage: ) //usage: "\n -l N Log only messages more urgent than prio N (1-8)" //usage: "\n -S Smaller output" +//usage: IF_FEATURE_SYSLOGD_UTC( +//usage: "\n -u Log timestamps in Coordinated Universal Time (UTC)" +//usage: ) //usage: "\n -t Strip client-generated timestamps" //usage: IF_FEATURE_SYSLOGD_DUP( //usage: "\n -D Drop duplicates" @@ -333,6 +345,7 @@ enum { IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f IF_FEATURE_KMSG_SYSLOG( OPTBIT_kmsg ,) // -K + IF_FEATURE_SYSLOGD_UTC( OPTBIT_utc ,) // -u OPT_mark = 1 << OPTBIT_mark , OPT_nofork = 1 << OPTBIT_nofork , @@ -348,6 +361,7 @@ enum { OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, + OPT_utc = IF_FEATURE_SYSLOGD_UTC( (1 << OPTBIT_utc )) + 0, }; #define OPTION_STR "m:nO:l:St" \ IF_FEATURE_ROTATE_LOGFILE("s:" ) \ @@ -357,7 +371,8 @@ enum { IF_FEATURE_IPC_SYSLOG( "C::") \ IF_FEATURE_SYSLOGD_DUP( "D" ) \ IF_FEATURE_SYSLOGD_CFG( "f:" ) \ - IF_FEATURE_KMSG_SYSLOG( "K" ) + IF_FEATURE_KMSG_SYSLOG( "K" ) \ + IF_FEATURE_SYSLOGD_UTC( "u" ) #define OPTION_DECL *opt_m, *opt_l \ IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \ IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \ @@ -818,6 +833,25 @@ static void parse_fac_prio_20(int pri, char *res20) snprintf(res20, 20, "<%d>", pri); } +static char *timestamp_from_time(const time_t *time) +{ + char *timestamp = NULL; + + if (time) { +#if ENABLE_FEATURE_SYSLOGD_UTC + if (option_mask32 & OPT_utc) + timestamp = asctime(gmtime(time)); + else + timestamp = asctime(localtime(time)); +#else + timestamp = ctime(time); +#endif + timestamp += 4; /* skip day of week */ + } + + return timestamp; +} + /* len parameter is used only for "is there a timestamp?" check. * NB: some callers cheat and supply len==0 when they know * that there is no timestamp, short-circuiting the test. */ @@ -833,8 +867,29 @@ static void timestamp_and_log(int pri, char *msg, int len) ) { if (!(option_mask32 & OPT_timestamp)) { /* use message timestamp */ +#if ENABLE_FEATURE_SYSLOGD_UTC + if (option_mask32 & OPT_utc) { + struct tm parsed, local; + now = time(NULL); + localtime_r(&now, &local); + if (strptime(msg, "%h %e %T", &parsed) != NULL) { + parsed.tm_gmtoff = local.tm_gmtoff; + parsed.tm_zone = local.tm_zone; + parsed.tm_year = local.tm_year; + parsed.tm_isdst = local.tm_isdst; + now = mktime(&parsed); + timestamp = asctime(gmtime(&now)) + 4; + } else { + timestamp = msg; + } + } else { + timestamp = msg; + now = 0; + } +#else timestamp = msg; now = 0; +#endif } msg += 16; } @@ -844,7 +899,7 @@ static void timestamp_and_log(int pri, char *msg, int len) struct timeval tv; xgettimeofday(&tv); now = tv.tv_sec; - timestamp = ctime(&now) + 4; /* skip day of week */ + timestamp = timestamp_from_time(&now); /* overwrite year by milliseconds, zero terminate */ sprintf(timestamp + 15, ".%03u", (unsigned)tv.tv_usec / 1000u); } else { @@ -853,7 +908,7 @@ static void timestamp_and_log(int pri, char *msg, int len) #else if (!timestamp) { time(&now); - timestamp = ctime(&now) + 4; /* skip day of week */ + timestamp = timestamp_from_time(&now); } timestamp[15] = '\0'; #endif -- 2.45.0 From gerickson at nuovations.com Mon Jan 19 19:27:45 2026 From: gerickson at nuovations.com (Grant Erickson) Date: Mon, 19 Jan 2026 11:27:45 -0800 Subject: [PATCH v3 1/3] syslogd: Use a local to track whether a message has a timestamp. In-Reply-To: References: Message-ID: <3e6f47e3a6010e672c8d39d02df97420ffa1a28a.1768850836.git.gerickson@nuovations.com> This improves self-documentation and readability of the code. --- sysklogd/syslogd.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 40644fb97484..22bd76bf5087 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -857,14 +857,16 @@ static char *timestamp_from_time(const time_t *time) * that there is no timestamp, short-circuiting the test. */ static void timestamp_and_log(int pri, char *msg, int len) { + /* Jan 18 00:11:22 msg... */ + /* 01234567890123456 */ + const bool msg_has_timestamp = (len >= 16 && + msg[ 3] == ' ' && msg[ 6] == ' ' && + msg[ 9] == ':' && msg[12] == ':' && + msg[15] == ' '); char *timestamp = NULL; time_t now; - /* Jan 18 00:11:22 msg... */ - /* 01234567890123456 */ - if (len >= 16 && msg[3] == ' ' && msg[6] == ' ' - && msg[9] == ':' && msg[12] == ':' && msg[15] == ' ' - ) { + if (msg_has_timestamp) { if (!(option_mask32 & OPT_timestamp)) { /* use message timestamp */ #if ENABLE_FEATURE_SYSLOGD_UTC -- 2.45.0 From gerickson at nuovations.com Mon Jan 19 19:27:44 2026 From: gerickson at nuovations.com (Grant Erickson) Date: Mon, 19 Jan 2026 11:27:44 -0800 Subject: [PATCH v3 0/3] syslogd: Add a configurable option to log timestamps in ISO 8601 format Message-ID: This provides unification for the several syslogd options that influence handling and formatting of log timestamps and adds a new configuration and option. First, this unifies the handling of messages with a client-generated timestamps when both 'FEATURE_SYSLOGD_PRECISE_TIMESTAMPS' and 'FEATURE_SYSLOGD_UTC' are asserted. In particular, to support the intermix of client-generated and server-generated timestamps, the former are zero-padded such that the timestamp "column" of a log file is consistent in format. Second, this adds a configurable option 'FEATURE_SYSLOGD_ISO8601FMT' enabling a command line option ('-I', with semantics similar to 'date') that directs syslogd to log timestamps in ISO 8601 format. Precision in seconds (the default), milliseconds, and microseconds are supported. Without the 'FEATURE_SYSLOGD_UTC' configuration and its '-u' option, outputs are of the form: YYYY-MM-DDThh:mm:ss?hhmm (seconds) YYYY-MM-DDThh:mm:ss.sss?hhmm (milliseconds) YYYY-MM-DDThh:mm:ss.uuuuuu?hhmm (microseconds) with the 'FEATURE_SYSLOGD_UTC' configuration and its '-u' option, outputs are of the form: YYYY-MM-DDThh:mm:ssZ (seconds) YYYY-MM-DDThh:mm:ss.sssZ (milliseconds) YYYY-MM-DDThh:mm:ss.uuuuuuZ (microseconds) With all three of the follow options asserted: * FEATURE_SYSLOGD_PRECISE_TIMESTAMPS * FEATURE_SYSLOGD_UTC * FEATURE_SYSLOGD_ISO8601FMT there are a total of twenty (20) possible test cases of which sixteen (16) are unique (several of which are defaults): 1. syslogd -O - -n 2. syslogd -O - -n -u 3. syslogd -O - -n -I 4. syslogd -O - -n -Is 5. syslogd -O - -n -Ims 6. syslogd -O - -n -Ius 7. syslogd -O - -n -I -u 8. syslogd -O - -n -Is -u 9. syslogd -O - -n -Ims -u 10. syslogd -O - -n -Ius -u 11. syslogd -O - -n -t 12. syslogd -O - -n -t -u 13. syslogd -O - -n -t -I 14. syslogd -O - -n -t -Is 15. syslogd -O - -n -t -Ims 16. syslogd -O - -n -t -Ius 17. syslogd -O - -n -t -I -u 18. syslogd -O - -n -t -Is -u 19. syslogd -O - -n -t -Ims -u 20. syslogd -O - -n -t -Ius -u which result in the following test output, generated interactively with 'logger' over ssh: 2025-03-28T20:10:11-0600 [19205453]# ./busybox syslogd -O - -n Mar 28 20:10:54.824 19205453 syslog.info syslogd started: BusyBox v1.36.1 Mar 28 20:10:59.000 19205453 auth.info sshd-session[940]: Accepted publickey for test from 192.168.1.94 port 44522 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE Mar 28 20:10:59.000 19205453 user.info test[42]: busybox syslogd test. Mar 28 20:10:59.000 19205453 auth.info sshd-session[942]: Received disconnect from 192.168.1.94 port 44522:11: disconnected by user Mar 28 20:10:59.000 19205453 auth.info sshd-session[942]: Disconnected from user test 192.168.1.94 port 44522 Mar 28 20:11:09.185 19205453 syslog.info syslogd exiting 2025-03-28T20:11:09-0600 [19205453]# ./busybox syslogd -O - -n -u Mar 29 02:11:11.742 19205453 syslog.info syslogd started: BusyBox v1.36.1 Mar 29 02:11:14.000 19205453 auth.info sshd-session[945]: Accepted publickey for test from 192.168.1.94 port 45900 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE Mar 29 02:11:14.000 19205453 user.info test[42]: busybox syslogd test. Mar 29 02:11:14.000 19205453 auth.info sshd-session[947]: Received disconnect from 192.168.1.94 port 45900:11: disconnected by user Mar 29 02:11:14.000 19205453 auth.info sshd-session[947]: Disconnected from user test 192.168.1.94 port 45900 Mar 29 02:11:21.280 19205453 syslog.info syslogd exiting 2025-03-28T20:11:21-0600 [19205453]# ./busybox syslogd -O - -n -I 2025-03-28T20:11:25-0600 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-28T20:11:30-0600 19205453 auth.info sshd-session[950]: Accepted publickey for test from 192.168.1.94 port 45842 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-28T20:11:30-0600 19205453 user.info test[42]: busybox syslogd test. 2025-03-28T20:11:30-0600 19205453 auth.info sshd-session[952]: Received disconnect from 192.168.1.94 port 45842:11: disconnected by user 2025-03-28T20:11:30-0600 19205453 auth.info sshd-session[952]: Disconnected from user test 192.168.1.94 port 45842 2025-03-28T20:11:34-0600 19205453 syslog.info syslogd exiting 2025-03-28T20:11:34-0600 [19205453]# ./busybox syslogd -O - -n -Is 2025-03-28T20:11:35-0600 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-28T20:11:38-0600 19205453 auth.info sshd-session[955]: Accepted publickey for test from 192.168.1.94 port 46904 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-28T20:11:38-0600 19205453 user.info test[42]: busybox syslogd test. 2025-03-28T20:11:38-0600 19205453 auth.info sshd-session[957]: Received disconnect from 192.168.1.94 port 46904:11: disconnected by user 2025-03-28T20:11:38-0600 19205453 auth.info sshd-session[957]: Disconnected from user test 192.168.1.94 port 46904 2025-03-28T20:11:41-0600 19205453 syslog.info syslogd exiting 2025-03-28T20:11:41-0600 [19205453]# ./busybox syslogd -O - -n -Ims 2025-03-28T20:11:45.942-0600 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-28T20:11:49.000-0600 19205453 auth.info sshd-session[960]: Accepted publickey for test from 192.168.1.94 port 35262 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-28T20:11:49.000-0600 19205453 user.info test[42]: busybox syslogd test. 2025-03-28T20:11:49.000-0600 19205453 auth.info sshd-session[962]: Received disconnect from 192.168.1.94 port 35262:11: disconnected by user 2025-03-28T20:11:49.000-0600 19205453 auth.info sshd-session[962]: Disconnected from user test 192.168.1.94 port 35262 2025-03-28T20:11:54.296-0600 19205453 syslog.info syslogd exiting 2025-03-28T20:11:54-0600 [19205453]# ./busybox syslogd -O - -n -Ius 2025-03-28T20:11:58.332879-0600 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-28T20:12:02.000000-0600 19205453 auth.info sshd-session[965]: Accepted publickey for test from 192.168.1.94 port 42812 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-28T20:12:02.000000-0600 19205453 user.info test[42]: busybox syslogd test. 2025-03-28T20:12:02.000000-0600 19205453 auth.info sshd-session[967]: Received disconnect from 192.168.1.94 port 42812:11: disconnected by user 2025-03-28T20:12:02.000000-0600 19205453 auth.info sshd-session[967]: Disconnected from user test 192.168.1.94 port 42812 2025-03-28T20:12:08.350903-0600 19205453 syslog.info syslogd exiting 2025-03-28T20:12:08-0600 [19205453]# ./busybox syslogd -O - -n -I -u 2025-03-29T02:12:18Z 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-29T02:12:21Z 19205453 auth.info sshd-session[970]: Accepted publickey for test from 192.168.1.94 port 59600 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-29T02:12:21Z 19205453 user.info test[42]: busybox syslogd test. 2025-03-29T02:12:21Z 19205453 auth.info sshd-session[972]: Received disconnect from 192.168.1.94 port 59600:11: disconnected by user 2025-03-29T02:12:21Z 19205453 auth.info sshd-session[972]: Disconnected from user test 192.168.1.94 port 59600 2025-03-29T02:12:24Z 19205453 syslog.info syslogd exiting 2025-03-28T20:12:24-0600 [19205453]# ./busybox syslogd -O - -n -Is -u 2025-03-29T02:12:27Z 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-29T02:12:30Z 19205453 auth.info sshd-session[975]: Accepted publickey for test from 192.168.1.94 port 49052 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-29T02:12:30Z 19205453 user.info test[42]: busybox syslogd test. 2025-03-29T02:12:30Z 19205453 auth.info sshd-session[977]: Received disconnect from 192.168.1.94 port 49052:11: disconnected by user 2025-03-29T02:12:30Z 19205453 auth.info sshd-session[977]: Disconnected from user test 192.168.1.94 port 49052 2025-03-29T02:12:33Z 19205453 syslog.info syslogd exiting 2025-03-28T20:12:33-0600 [19205453]# ./busybox syslogd -O - -n -Ims -u 2025-03-29T02:12:37.756Z 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-29T02:12:40.000Z 19205453 auth.info sshd-session[980]: Accepted publickey for test from 192.168.1.94 port 33894 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-29T02:12:40.000Z 19205453 user.info test[42]: busybox syslogd test. 2025-03-29T02:12:40.000Z 19205453 auth.info sshd-session[982]: Received disconnect from 192.168.1.94 port 33894:11: disconnected by user 2025-03-29T02:12:40.000Z 19205453 auth.info sshd-session[982]: Disconnected from user test 192.168.1.94 port 33894 2025-03-29T02:13:06.782Z 19205453 syslog.info syslogd exiting 2025-03-28T20:13:06-0600 [19205453]# ./busybox syslogd -O - -n -Ius -u 2025-03-29T02:13:09.593088Z 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-29T02:13:12.000000Z 19205453 auth.info sshd-session[986]: Accepted publickey for test from 192.168.1.94 port 49542 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-29T02:13:12.000000Z 19205453 user.info test[42]: busybox syslogd test. 2025-03-29T02:13:12.000000Z 19205453 auth.info sshd-session[988]: Received disconnect from 192.168.1.94 port 49542:11: disconnected by user 2025-03-29T02:13:12.000000Z 19205453 auth.info sshd-session[988]: Disconnected from user test 192.168.1.94 port 49542 2025-03-29T02:13:12.000000Z 19205453 daemon.info connmand[529]: ntp: adjust (slew): +0.000051 sec 2025-03-29T02:13:19.679452Z 19205453 syslog.info syslogd exiting 2025-03-28T20:13:19-0600 [19205453]# ./busybox syslogd -O - -n -t Mar 28 20:15:22.452 19205453 syslog.info syslogd started: BusyBox v1.36.1 Mar 28 20:15:24.606 19205453 auth.info sshd-session[992]: Accepted publickey for test from 192.168.1.94 port 36734 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE Mar 28 20:15:24.682 19205453 user.info test[42]: busybox syslogd test. Mar 28 20:15:24.684 19205453 auth.info sshd-session[994]: Received disconnect from 192.168.1.94 port 36734:11: disconnected by user Mar 28 20:15:24.684 19205453 auth.info sshd-session[994]: Disconnected from user test 192.168.1.94 port 36734 Mar 28 20:15:28.262 19205453 syslog.info syslogd exiting 2025-03-28T20:15:28-0600 [19205453]# ./busybox syslogd -O - -n -t -u Mar 29 02:15:33.963 19205453 syslog.info syslogd started: BusyBox v1.36.1 Mar 29 02:15:36.646 19205453 auth.info sshd-session[997]: Accepted publickey for test from 192.168.1.94 port 47486 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE Mar 29 02:15:36.719 19205453 user.info test[42]: busybox syslogd test. Mar 29 02:15:36.721 19205453 auth.info sshd-session[999]: Received disconnect from 192.168.1.94 port 47486:11: disconnected by user Mar 29 02:15:36.722 19205453 auth.info sshd-session[999]: Disconnected from user test 192.168.1.94 port 47486 Mar 29 02:15:42.726 19205453 syslog.info syslogd exiting 2025-03-28T20:15:42-0600 [19205453]# ./busybox syslogd -O - -n -t -I 2025-03-28T20:15:44-0600 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-28T20:15:47-0600 19205453 auth.info sshd-session[1002]: Accepted publickey for test from 192.168.1.94 port 40804 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-28T20:15:47-0600 19205453 user.info test[42]: busybox syslogd test. 2025-03-28T20:15:47-0600 19205453 auth.info sshd-session[1004]: Received disconnect from 192.168.1.94 port 40804:11: disconnected by user 2025-03-28T20:15:47-0600 19205453 auth.info sshd-session[1004]: Disconnected from user test 192.168.1.94 port 40804 2025-03-28T20:15:55-0600 19205453 syslog.info syslogd exiting 2025-03-28T20:15:55-0600 [19205453]# ./busybox syslogd -O - -n -t -Is 2025-03-28T20:15:58-0600 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-28T20:16:00-0600 19205453 auth.info sshd-session[1007]: Accepted publickey for test from 192.168.1.94 port 59882 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-28T20:16:00-0600 19205453 user.info test[42]: busybox syslogd test. 2025-03-28T20:16:00-0600 19205453 auth.info sshd-session[1009]: Received disconnect from 192.168.1.94 port 59882:11: disconnected by user 2025-03-28T20:16:00-0600 19205453 auth.info sshd-session[1009]: Disconnected from user test 192.168.1.94 port 59882 2025-03-28T20:16:03-0600 19205453 syslog.info syslogd exiting 2025-03-28T20:16:04-0600 [19205453]# ./busybox syslogd -O - -n -t -Ims 2025-03-28T20:16:16.742-0600 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-28T20:16:19.040-0600 19205453 auth.info sshd-session[1013]: Accepted publickey for test from 192.168.1.94 port 43856 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-28T20:16:19.115-0600 19205453 user.info test[42]: busybox syslogd test. 2025-03-28T20:16:19.119-0600 19205453 auth.info sshd-session[1015]: Received disconnect from 192.168.1.94 port 43856:11: disconnected by user 2025-03-28T20:16:19.119-0600 19205453 auth.info sshd-session[1015]: Disconnected from user test 192.168.1.94 port 43856 2025-03-28T20:16:25.382-0600 19205453 syslog.info syslogd exiting 2025-03-28T20:16:25-0600 [19205453]# ./busybox syslogd -O - -n -t -Ius 2025-03-28T20:16:27.542901-0600 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-28T20:16:29.717165-0600 19205453 auth.info sshd-session[1018]: Accepted publickey for test from 192.168.1.94 port 54902 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-28T20:16:29.792157-0600 19205453 user.info test[42]: busybox syslogd test. 2025-03-28T20:16:29.794654-0600 19205453 auth.info sshd-session[1020]: Received disconnect from 192.168.1.94 port 54902:11: disconnected by user 2025-03-28T20:16:29.795390-0600 19205453 auth.info sshd-session[1020]: Disconnected from user test 192.168.1.94 port 54902 2025-03-28T20:16:31.518777-0600 19205453 syslog.info syslogd exiting 2025-03-28T20:16:31-0600 [19205453]# ./busybox syslogd -O - -n -t -I -u 2025-03-29T02:16:36Z 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-29T02:16:39Z 19205453 auth.info sshd-session[1023]: Accepted publickey for test from 192.168.1.94 port 37222 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-29T02:16:39Z 19205453 user.info test[42]: busybox syslogd test. 2025-03-29T02:16:39Z 19205453 auth.info sshd-session[1025]: Received disconnect from 192.168.1.94 port 37222:11: disconnected by user 2025-03-29T02:16:39Z 19205453 auth.info sshd-session[1025]: Disconnected from user test 192.168.1.94 port 37222 2025-03-29T02:16:45Z 19205453 syslog.info syslogd exiting 2025-03-28T20:16:46-0600 [19205453]# ./busybox syslogd -O - -n -t -Is -u 2025-03-29T02:16:47Z 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-29T02:16:49Z 19205453 auth.info sshd-session[1028]: Accepted publickey for test from 192.168.1.94 port 50590 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-29T02:16:49Z 19205453 user.info test[42]: busybox syslogd test. 2025-03-29T02:16:49Z 19205453 auth.info sshd-session[1030]: Received disconnect from 192.168.1.94 port 50590:11: disconnected by user 2025-03-29T02:16:49Z 19205453 auth.info sshd-session[1030]: Disconnected from user test 192.168.1.94 port 50590 2025-03-29T02:16:59Z 19205453 syslog.info syslogd exiting 2025-03-28T20:16:59-0600 [19205453]# ./busybox syslogd -O - -n -t -Ims -u 2025-03-29T02:16:59.792Z 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-29T02:17:03.189Z 19205453 auth.info sshd-session[1033]: Accepted publickey for test from 192.168.1.94 port 59012 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-29T02:17:03.263Z 19205453 user.info test[42]: busybox syslogd test. 2025-03-29T02:17:03.267Z 19205453 auth.info sshd-session[1035]: Received disconnect from 192.168.1.94 port 59012:11: disconnected by user 2025-03-29T02:17:03.267Z 19205453 auth.info sshd-session[1035]: Disconnected from user test 192.168.1.94 port 59012 2025-03-29T02:17:11.750Z 19205453 syslog.info syslogd exiting 2025-03-28T20:17:11-0600 [19205453]# ./busybox syslogd -O - -n -t -Ius -u 2025-03-29T02:17:13.063079Z 19205453 syslog.info syslogd started: BusyBox v1.36.1 2025-03-29T02:17:15.512774Z 19205453 auth.info sshd-session[1038]: Accepted publickey for test from 192.168.1.94 port 34840 ssh2: RSA SHA256:hvjEhxYOZchXOw6JKONWGR0Aei/02ef3bSvt5UF6/SE 2025-03-29T02:17:15.592759Z 19205453 user.info test[42]: busybox syslogd test. 2025-03-29T02:17:15.596451Z 19205453 auth.info sshd-session[1040]: Received disconnect from 192.168.1.94 port 34840:11: disconnected by user 2025-03-29T02:17:15.596526Z 19205453 auth.info sshd-session[1040]: Disconnected from user test 192.168.1.94 port 34840 2025-03-29T02:17:18.254941Z 19205453 syslog.info syslogd exiting Grant Erickson (3): syslogd: Use a local to track whether a message has a timestamp. syslogd: Unify messages with client timestamps when both PRECISE and UTC are enabled. syslogd: Add a configurable option to log timestamps in ISO 8601 format sysklogd/syslogd.c | 288 ++++++++++++++++++++++++++++++++------------- 1 file changed, 204 insertions(+), 84 deletions(-) -- 2.45.0 From gerickson at nuovations.com Mon Jan 19 19:27:46 2026 From: gerickson at nuovations.com (Grant Erickson) Date: Mon, 19 Jan 2026 11:27:46 -0800 Subject: [PATCH v3 2/3] syslogd: Unify messages with client timestamps when both PRECISE and UTC are enabled. In-Reply-To: References: Message-ID: <4f181c31e95976403af49caea25a4b1344bb1c5b.1768850836.git.gerickson@nuovations.com> This unifies the handling of messages with a client-generated timestamps when both ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS and ENABLE_FEATURE_SYSLOGD_UTC are asserted. In particular, to support the intermix of client-generated and server-generated timestamps, the former are zero-padded such that the timestamp "column" of a log file is consistent in format. --- sysklogd/syslogd.c | 123 +++++++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 42 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 22bd76bf5087..d9d7ac266b01 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -833,25 +833,47 @@ static void parse_fac_prio_20(int pri, char *res20) snprintf(res20, 20, "<%d>", pri); } -static char *timestamp_from_time(const time_t *time) +static void get_time(struct timeval *tvp) { - char *timestamp = NULL; + if (tvp) { +#if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_ISO8601FMT + xgettimeofday(tvp); +#else + time(&tvp->tv_sec); +#endif + } +} + +static struct tm * decompose_time(struct timeval *tvp, struct tm *tmp) +{ + struct tm *tm; - if (time) { #if ENABLE_FEATURE_SYSLOGD_UTC - if (option_mask32 & OPT_utc) - timestamp = asctime(gmtime(time)); - else - timestamp = asctime(localtime(time)); + if (option_mask32 & OPT_utc) + tm = gmtime_r(&tvp->tv_sec, tmp); + else + tm = localtime_r(&tvp->tv_sec, tmp); #else - timestamp = ctime(time); + tm = localtime_r(&tvp->tv_sec, tmp); #endif - timestamp += 4; /* skip day of week */ + + return tm; +} + +static struct tm * generate_time(struct timeval *tvp, struct tm *tmp) +{ + struct tm *tm = NULL; + + if (tvp && tmp) { + get_time(tvp); + + tm = decompose_time(tvp, tmp); } - return timestamp; + return tm; } + /* len parameter is used only for "is there a timestamp?" check. * NB: some callers cheat and supply len==0 when they know * that there is no timestamp, short-circuiting the test. */ @@ -863,56 +885,73 @@ static void timestamp_and_log(int pri, char *msg, int len) msg[ 3] == ' ' && msg[ 6] == ' ' && msg[ 9] == ':' && msg[12] == ':' && msg[15] == ' '); + const char *format="%h %e %T"; char *timestamp = NULL; - time_t now; + char timestampbuf[20]; + /* MMM DD hh:mm:ss default */ + /* 0123456789012345 - 16 */ + /* MMM DD hh:mm:ss.mmm ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS */ + /* 01234567890123456789 - 20 */ + struct timeval tvnow; +#if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_UTC + struct tm parsed; +#endif + struct tm tmnow, *tmp = NULL; + size_t n = 0; if (msg_has_timestamp) { if (!(option_mask32 & OPT_timestamp)) { /* use message timestamp */ +#if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_UTC + struct tm local; + get_time(&tvnow); + localtime_r(&tvnow.tv_sec, &local); + if (strptime(msg, format, &parsed) != NULL) { + parsed.tm_gmtoff = local.tm_gmtoff; + parsed.tm_zone = local.tm_zone; + parsed.tm_year = local.tm_year; + parsed.tm_isdst = local.tm_isdst; + + tvnow.tv_sec = mktime(&parsed); + tvnow.tv_usec = 0; + #if ENABLE_FEATURE_SYSLOGD_UTC - if (option_mask32 & OPT_utc) { - struct tm parsed, local; - now = time(NULL); - localtime_r(&now, &local); - if (strptime(msg, "%h %e %T", &parsed) != NULL) { - parsed.tm_gmtoff = local.tm_gmtoff; - parsed.tm_zone = local.tm_zone; - parsed.tm_year = local.tm_year; - parsed.tm_isdst = local.tm_isdst; - now = mktime(&parsed); - timestamp = asctime(gmtime(&now)) + 4; + if (option_mask32 & OPT_utc) { + tmp = gmtime_r(&tvnow.tv_sec, &tmnow); } else { - timestamp = msg; + tmp = &parsed; } +#else + tmp = &parsed; +#endif /* ENABLE_FEATURE_SYSLOGD_UTC */ } else { - timestamp = msg; - now = 0; + tmp = decompose_time(&tvnow, &tmnow); } #else timestamp = msg; - now = 0; -#endif + timestamp[15] = '\0'; + tvnow.tv_sec = 0; + tvnow.tv_usec = 0; +#endif /* ENABLE_FEATURE_SYSLOGD_UTC */ } msg += 16; } + if (!tmp) { + tmp = generate_time(&tvnow, &tmnow); + } + #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS - if (!timestamp) { - struct timeval tv; - xgettimeofday(&tv); - now = tv.tv_sec; - timestamp = timestamp_from_time(&now); - /* overwrite year by milliseconds, zero terminate */ - sprintf(timestamp + 15, ".%03u", (unsigned)tv.tv_usec / 1000u); - } else { - timestamp[15] = '\0'; + if (tmp && !timestamp) { + n = strftime(timestampbuf + n, sizeof(timestampbuf) - n, format, tmp); + snprintf(timestampbuf + n, sizeof(timestampbuf) - n, ".%03lu", tvnow.tv_usec / 1000u); + timestamp = timestampbuf; } #else - if (!timestamp) { - time(&now); - timestamp = timestamp_from_time(&now); + if (tmp && !timestamp) { + strftime(timestampbuf + n, sizeof(timestampbuf) - n, format, tmp); + timestamp = timestampbuf; } - timestamp[15] = '\0'; #endif if (option_mask32 & OPT_kmsg) { @@ -938,7 +977,7 @@ static void timestamp_and_log(int pri, char *msg, int len) for (rule = G.log_rules; rule; rule = rule->next) { if (rule->enabled_facility_priomap[facility] & prio_bit) { - log_locally(now, G.printbuf, rule->file); + log_locally(tvnow.tv_sec, G.printbuf, rule->file); match = 1; } } @@ -953,7 +992,7 @@ static void timestamp_and_log(int pri, char *msg, int len) return; } #endif - log_locally(now, G.printbuf, &G.logFile); + log_locally(tvnow.tv_sec, G.printbuf, &G.logFile); } } -- 2.45.0 From gerickson at nuovations.com Mon Jan 19 19:27:47 2026 From: gerickson at nuovations.com (Grant Erickson) Date: Mon, 19 Jan 2026 11:27:47 -0800 Subject: [PATCH v3 3/3] syslogd: Add a configurable option to log timestamps in ISO 8601 format In-Reply-To: References: Message-ID: <67440dc463e277a6d65ed1155e6cedfbcf15a1dc.1768850836.git.gerickson@nuovations.com> This adds a configurable option 'FEATURE_SYSLOGD_ISO8601FMT' enabling a command line option ('-I', with semantics similar to 'date') that directs syslogd to log timestamps in ISO 8601 format. Precision in seconds (the default), milliseconds, and microseconds are supported. Without the 'FEATURE_SYSLOGD_UTC' configuration and its '-u' option, outputs are of the form: YYYY-MM-DDThh:mm:ss?hhmm (seconds) YYYY-MM-DDThh:mm:ss.sss?hhmm (milliseconds) YYYY-MM-DDThh:mm:ss.uuuuuu?hhmm (microseconds) with the 'FEATURE_SYSLOGD_UTC' configuration and its '-u' option, outputs are of the form: YYYY-MM-DDThh:mm:ssZ (seconds) YYYY-MM-DDThh:mm:ss.sssZ (milliseconds) YYYY-MM-DDThh:mm:ss.uuuuuuZ (microseconds) --- sysklogd/syslogd.c | 155 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 38 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index d9d7ac266b01..368e5f7a68de 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -44,6 +44,15 @@ //config: syslogd to log timestamps in Coordinated Universal Time //config: (UTC) rather than in local time. //config: +//config:config FEATURE_SYSLOGD_ISO8601FMT +//config: bool "Log timestamps in ISO 8601 format" +//config: default n +//config: depends on SYSLOGD +//config: help +//config: This enables a command line option ('-I') that directs +//config: syslogd to log timestamps in ISO 8601 format with second, +//config: millisecond, or microsecond resolution. +//config: //config:config FEATURE_REMOTE_LOG //config: bool "Remote Log support" //config: default y @@ -159,6 +168,10 @@ //usage: IF_FEATURE_SYSLOGD_UTC( //usage: "\n -u Log timestamps in Coordinated Universal Time (UTC)" //usage: ) +//usage: IF_FEATURE_SYSLOGD_ISO8601FMT( +//usage: "\n -I[SPEC] Log timestamps in ISO 8601 format" +//usage: "\n SPEC=seconds (default), ms, or us" +//usage: ) //usage: "\n -t Strip client-generated timestamps" //usage: IF_FEATURE_SYSLOGD_DUP( //usage: "\n -D Drop duplicates" @@ -272,6 +285,9 @@ IF_FEATURE_SYSLOGD_CFG( \ IF_FEATURE_KMSG_SYSLOG( \ int kmsgfd; \ int primask; \ +) \ +IF_FEATURE_SYSLOGD_ISO8601FMT( \ + int iso8601fmt; \ ) struct init_globals { @@ -298,7 +314,7 @@ struct globals { /* ...then sprintf into printbuf, adding timestamp (15 or 19 chars), * host (64), fac.prio (20) to the message */ /* (growth by: 15 + 64 + 20 + delims = ~110) */ - char printbuf[MAX_READ*2 + 128]; + char printbuf[MAX_READ*2 + 144]; }; static const struct init_globals init_data = { @@ -337,15 +353,16 @@ enum { OPTBIT_loglevel, // -l OPTBIT_small, // -S OPTBIT_timestamp, // -t - IF_FEATURE_ROTATE_LOGFILE(OPTBIT_filesize ,) // -s - IF_FEATURE_ROTATE_LOGFILE(OPTBIT_rotatecnt ,) // -b - IF_FEATURE_REMOTE_LOG( OPTBIT_remotelog ,) // -R - IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L - IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C - IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D - IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f - IF_FEATURE_KMSG_SYSLOG( OPTBIT_kmsg ,) // -K - IF_FEATURE_SYSLOGD_UTC( OPTBIT_utc ,) // -u + IF_FEATURE_ROTATE_LOGFILE( OPTBIT_filesize ,) // -s + IF_FEATURE_ROTATE_LOGFILE( OPTBIT_rotatecnt ,) // -b + IF_FEATURE_REMOTE_LOG( OPTBIT_remotelog ,) // -R + IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L + IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C + IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D + IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f + IF_FEATURE_KMSG_SYSLOG( OPTBIT_kmsg ,) // -K + IF_FEATURE_SYSLOGD_UTC( OPTBIT_utc ,) // -u + IF_FEATURE_SYSLOGD_ISO8601FMT(OPTBIT_iso8601fmt ,) // -I OPT_mark = 1 << OPTBIT_mark , OPT_nofork = 1 << OPTBIT_nofork , @@ -353,38 +370,41 @@ enum { OPT_loglevel = 1 << OPTBIT_loglevel, OPT_small = 1 << OPTBIT_small , OPT_timestamp = 1 << OPTBIT_timestamp, - OPT_filesize = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_filesize )) + 0, - OPT_rotatecnt = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_rotatecnt )) + 0, - OPT_remotelog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_remotelog )) + 0, - OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0, - OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, - OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, - OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, - OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, + OPT_filesize = IF_FEATURE_ROTATE_LOGFILE( (1 << OPTBIT_filesize )) + 0, + OPT_rotatecnt = IF_FEATURE_ROTATE_LOGFILE( (1 << OPTBIT_rotatecnt )) + 0, + OPT_remotelog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_remotelog )) + 0, + OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0, + OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, + OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, + OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, + OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, OPT_utc = IF_FEATURE_SYSLOGD_UTC( (1 << OPTBIT_utc )) + 0, + OPT_iso8601fmt = IF_FEATURE_SYSLOGD_ISO8601FMT((1 << OPTBIT_iso8601fmt )) + 0, }; #define OPTION_STR "m:nO:l:St" \ - IF_FEATURE_ROTATE_LOGFILE("s:" ) \ - IF_FEATURE_ROTATE_LOGFILE("b:" ) \ - IF_FEATURE_REMOTE_LOG( "R:*") \ - IF_FEATURE_REMOTE_LOG( "L" ) \ - IF_FEATURE_IPC_SYSLOG( "C::") \ - IF_FEATURE_SYSLOGD_DUP( "D" ) \ - IF_FEATURE_SYSLOGD_CFG( "f:" ) \ - IF_FEATURE_KMSG_SYSLOG( "K" ) \ - IF_FEATURE_SYSLOGD_UTC( "u" ) + IF_FEATURE_ROTATE_LOGFILE( "s:" ) \ + IF_FEATURE_ROTATE_LOGFILE( "b:" ) \ + IF_FEATURE_REMOTE_LOG( "R:*") \ + IF_FEATURE_REMOTE_LOG( "L" ) \ + IF_FEATURE_IPC_SYSLOG( "C::") \ + IF_FEATURE_SYSLOGD_DUP( "D" ) \ + IF_FEATURE_SYSLOGD_CFG( "f:" ) \ + IF_FEATURE_KMSG_SYSLOG( "K" ) \ + IF_FEATURE_SYSLOGD_UTC( "u" ) \ + IF_FEATURE_SYSLOGD_ISO8601FMT("I::") #define OPTION_DECL *opt_m, *opt_l \ - IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \ - IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \ - IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) \ - IF_FEATURE_SYSLOGD_CFG( ,*opt_f = NULL) + IF_FEATURE_ROTATE_LOGFILE( ,*opt_s) \ + IF_FEATURE_ROTATE_LOGFILE( ,*opt_b) \ + IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) \ + IF_FEATURE_SYSLOGD_CFG( ,*opt_f = NULL) \ + IF_FEATURE_SYSLOGD_ISO8601FMT(,*opt_I = NULL) #define OPTION_PARAM &opt_m, &(G.logFile.path), &opt_l \ - IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \ - IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \ - IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \ - IF_FEATURE_IPC_SYSLOG( ,&opt_C) \ - IF_FEATURE_SYSLOGD_CFG( ,&opt_f) - + IF_FEATURE_ROTATE_LOGFILE( ,&opt_s) \ + IF_FEATURE_ROTATE_LOGFILE( ,&opt_b) \ + IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \ + IF_FEATURE_IPC_SYSLOG( ,&opt_C) \ + IF_FEATURE_SYSLOGD_CFG( ,&opt_f) \ + IF_FEATURE_SYSLOGD_ISO8601FMT(,&opt_I) #if ENABLE_FEATURE_SYSLOGD_CFG static const CODE* find_by_name(char *name, const CODE* c_set) @@ -873,6 +893,21 @@ static struct tm * generate_time(struct timeval *tvp, struct tm *tmp) return tm; } +#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT +static void append_zone_string(char *timestamp, size_t max, const struct tm *tmp) +{ + if (timestamp && tmp) { +#if ENABLE_FEATURE_SYSLOGD_UTC + if (option_mask32 & OPT_utc) + snprintf(timestamp, max, "%c", 'Z'); + else + strftime(timestamp, max, "%z", tmp); +#else + strftime(timestamp, max, "%z", tmp); +#endif + } +} +#endif /* len parameter is used only for "is there a timestamp?" check. * NB: some callers cheat and supply len==0 when they know @@ -887,11 +922,15 @@ static void timestamp_and_log(int pri, char *msg, int len) msg[15] == ' '); const char *format="%h %e %T"; char *timestamp = NULL; - char timestampbuf[20]; + char timestampbuf[32]; /* MMM DD hh:mm:ss default */ /* 0123456789012345 - 16 */ /* MMM DD hh:mm:ss.mmm ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS */ /* 01234567890123456789 - 20 */ + /* YYYY-MM-DDThh:mm:ss.uuuuuuZ OPT_utc & OPT_iso8601fmt */ + /* 0123456789012345678901234567 - 28 */ + /* YYYY-MM-DDThh:mm:ss.uuuuuu+hhmm OPT_iso8601fmt */ + /* 01234567890123456789012345678901 - 32 */ struct timeval tvnow; #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_UTC struct tm parsed; @@ -941,6 +980,33 @@ static void timestamp_and_log(int pri, char *msg, int len) tmp = generate_time(&tvnow, &tmnow); } +#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT + if (tmp && !timestamp && G.iso8601fmt >= 0) { + format = "%FT%T"; + /* -I[SPEC]: 0:seconds 1:ms 2:us */ + n = strftime(timestampbuf + n, sizeof(timestampbuf) - n, format, tmp); + + if (G.iso8601fmt == 1 || G.iso8601fmt == 2) { + const char *iso8601fracfmt; + unsigned long divisor; + + if (G.iso8601fmt == 1) { + iso8601fracfmt = ".%03lu"; + divisor = 1000u; + } else { + iso8601fracfmt = ".%06lu"; + divisor = 1u; + } + + n += snprintf(timestampbuf + n, sizeof(timestampbuf) - n, iso8601fracfmt, tvnow.tv_usec / divisor); + } + + append_zone_string(timestampbuf + n, sizeof(timestampbuf) - n, tmp); + + timestamp = timestampbuf; + } +#endif /* ENABLE_FEATURE_SYSLOGD_ISO8601FMT */ + #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS if (tmp && !timestamp) { n = strftime(timestampbuf + n, sizeof(timestampbuf) - n, format, tmp); @@ -1138,6 +1204,19 @@ static int NOINLINE syslogd_init(char **argv) #if ENABLE_FEATURE_IPC_SYSLOG if (opt_C) // -Cn G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; +#endif +#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT + G.iso8601fmt = -1; + if (opts & OPT_iso8601fmt) { + G.iso8601fmt = 0; /* default is seconds */ + if (opt_I) { + static const char iso8601fmts[] ALIGN1 = + "seconds\0""ms\0""us\0"; + G.iso8601fmt = index_in_substrings(iso8601fmts, opt_I); + if (G.iso8601fmt < 0) + bb_show_usage(); + } + } #endif /* If they have not specified remote logging, then log locally */ if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R -- 2.45.0 From vda.linux at googlemail.com Mon Jan 19 19:28:50 2026 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Mon, 19 Jan 2026 20:28:50 +0100 Subject: [PATCH v13 01/17] libbb: mask xvfork to xfork on MMU targets In-Reply-To: <20251116230849.133134-2-tashernadav@gmail.com> References: <20251116230849.133134-1-tashernadav@gmail.com> <20251116230849.133134-2-tashernadav@gmail.com> Message-ID: On Mon, Nov 17, 2025 at 12:09?AM Nadav Tasher wrote: > > Using xfork() instead of xvfork() on MMU targets improves > security and stability. > Memory efficiency differences are negligable since most > kernels implement fork() with CoW. In fact, you should go into opposite direction: whenever it's not incurring difficulties, you should use vfork(). fork() is much slower. Especially if forking a process with large memory footprint. It can take something like 50-100 milliseconds even on lightly loaded machine. Yes, CoW means that the dirtied pages of the process do not need to be copied, but the whole kernel-side paging structure needs to be. If you examine in the kernel what fork() does with the paging structures, you'll realize that fork() essentially flushes the entire TLB, and the amount of newly allocated and updated pages in new paging data structures (at least a dozen pages) is large enough to flush today's CPUs L1 data cache (<=64 kbytes). In comparison, vfork() does not touch paging structures at all, it barely needs any kernel-side allocations: essentially, it only allocates new task_struct and associated small structures. From vda.linux at googlemail.com Mon Jan 19 20:58:24 2026 From: vda.linux at googlemail.com (Denys Vlasenko) Date: Mon, 19 Jan 2026 21:58:24 +0100 Subject: [PATCH v13 00/17] Making BusyBox self-contained In-Reply-To: <20251116230849.133134-1-tashernadav@gmail.com> References: <20251116230849.133134-1-tashernadav@gmail.com> Message-ID: Good day Nadav. Looks like you did a lot of work. I would like to incorporate what is useful, and discuss the changes I do not understand. By "making BusyBox self-contained", what do you have in mind? self-contained as in independent? Independent from what? On Mon, Nov 17, 2025 at 12:09?AM Nadav Tasher wrote: > libbb: mask xvfork to xfork on MMU targets Above seems to be unnecessary. > libbb: implement clone_string_array > libbb: implement close_cloexec_fds > libbb: implement reset_all_signals > libbb: implement bb_execXX function family to handle applet executions > libbb: make spawn and spawn_and_wait use bb_execvp > libbb: implement bb_system using spawn_and_wait libbb changes like these need to go in with the corresponding change which needs them. +config FEATURE_TRY_BASENAME_APPLETS + bool "fake PATH lookup using basename" + default n + depends on FEATURE_PREFER_APPLETS + help + This makes applet lookup try the basename of the applet name given, + essentially allowing applet execution by absolute path. This might be useful. Perhaps you can add a short explanation in *what use case* you find it useful? It's not "faking" PATH lookup: PATH lookup is not done on filenames with slashes. This needs a better name and description. FEATURE_PREFER_APPLETS_IN_BASENAME? Still not really satisfactorily explanatory. FEATURE_PREFER_APPLETS_EVEN_WITH_PATH? That's... wordy, but hopefully not misleading? + This feature extends the "exec prefers applets" feature. Above part of the description is not necessary. +config FEATURE_FORCE_APPLETS + bool "only use applets" + default n + depends on FEATURE_PREFER_APPLETS + help + This is an experimental option which makes exec calls fail when trying + to execute external binaries that are not part of busybox. Why is this useful? Please add a short explanation in *what use case* you find it useful. If we are adding these CONFIGs, they need to go in as a separate patch which adds just that change, with no other changes. In fact, it can be a separate patch, applied to the current tree, not a part of a large patch set - easier to review and apply. > applets: change system() calls to bb_system() > libbb: make bb_system use get_shell_name to find shell These two changes make sense in the spirit of FEATURE_PREFER_APPLETS: users may want to use an internal shell instead of external "/bin/sh", as defined by libc system() API. Perhaps they do not want to depend on existence of "/bin/sh". Maybe call it FEATURE_PREFER_INTERNAL_SHELL? There is already support for having internal shell even if neither ash nor hush is selected as applet: shell/hush.c // This option is visible (has a description) to make it possible to select // a "scripted" applet (such as NOLOGIN) but avoid selecting any shells: //config:config SHELL_HUSH //config: bool "Internal shell for embedded script support" //config: default n This means that bb_system() can simply follow this existing example how to call internal shells: int scripted_main(int argc UNUSED_PARAM, char **argv) { int script = find_script_by_name(applet_name); if (script >= 0) # if ENABLE_SHELL_ASH return ash_main(-script - 1, argv); # elif ENABLE_SHELL_HUSH return hush_main(-script - 1, argv); # else return 1; # endif return 0; } Can you send a separate patch (not a part of a larger patch set) which implements this? > libbb: allow forcing all applets to behave as NOEXEC applets Maybe makes sense. If you describe a case where you are using it. I suspect this *requires* aliasing vfork() to fork() to avoid a lot of problems? > shell: support shell aliases for ash and hush IOW: instead of support for just "bash" alias, you want support for arbitrary shell name aliases. Good idea! Can you send a separate patch (not a part of a larger patch set) which implements this? > applets: use bb_execXX functions instead of direct exec calls The above change needs to be combined with "libbb: implement bb_execXX" change so that it's easier to review and (1) see why bb_execXX are useful, and (2) be sure we aren't breaking things. > ash: use bb_execve to execute commands and applets in tryexec > hush: use bb_execvp to execute commands and applets in execvp_or_die Shells are fragile beasts. This should go in after the previous "applets: use bb_execXX" patch is reviewed and applied. Absolutely do run the "run_all" scripts in shell/ash_test and shell/hush_test before submitting this change (run them with various combinations of CONFIGs, note in your submission what config(s) you tested). > libbb: implement re_exec using bb_execv >By using bb_execv, an applet can be executed with NOEXEC >instead of actually re-executing the binary You seem to misunderstand the purpose of re_exec(). It's used exclusively on NOMMU to re-execute the same applet after vfork() in the applet, in order to unblock the parent and have two instances of the applet code to run in parallel. Examine httpd.c to see how and why it's done. This is a work-around for an inability to use fork() on NOMMU machines. Making re_exec() "NOEXEC-capable" defeats the purpose why it exists. From wouter.franken_ext at softathome.com Tue Jan 20 09:28:27 2026 From: wouter.franken_ext at softathome.com (wouter.franken_ext at softathome.com) Date: Tue, 20 Jan 2026 10:28:27 +0100 Subject: [PATCH] libbb/loop: fix existence check for LOOP_CONFIGURE ioctl Message-ID: <20260120092850.141782-1-wouter.franken_ext@softathome.com> The LOOP_CONFIGURE ioctl is supported in 5.8 kernels and up. To have backwards compatibility there is a config option CONFIG_TRY_LOOP_CONFIGURE that will check if the ioctl exists and if not fall back to old way of configuring loop devices. Normally errno will be set to EINVAL when this ioctl does not exist. However, when kernel config CONFIG_COMPAT is enabled, then compat_ioctl is called. In that case -ENOIOCTLCMD is returned by loop device driver and generic ioctl wrapper will set errno to ENOTTY. Because busybox does not expect this it will fail to mount loop devices in this case. This patch fixes the check for the existence of the ioctl LOOP_CONFIGURE by checking if errno is one of both: EINVAL or ENOTTY. Signed-off-by: Wouter Franken Signed-off-by: Wouter Franken --- libbb/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/loop.c b/libbb/loop.c index a0c5d02..b603d0d 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -158,7 +158,7 @@ static int set_loopdev_params(int lfd, if (rc == 0) return rc; /* SUCCESS! */ # if ENABLE_TRY_LOOP_CONFIGURE - if (errno != EINVAL) + if (errno != EINVAL && errno != ENOTTY) return rc; /* error other than old kernel */ /* Old kernel, fall through into old way to do it: */ # endif -- 2.34.1 From renchunhui2025 at outlook.com Thu Jan 22 13:43:37 2026 From: renchunhui2025 at outlook.com (chunhui ren) Date: Thu, 22 Jan 2026 13:43:37 +0000 Subject: [RFC PATCH] sed/grep noexec support for performance optimization Message-ID: Hi BusyBox maintainers, I?m working on a performance optimization and would like to explore adding noexec support for sed and grep. The motivation is to reduce fork/exec overhead in constrained environments by executing sed/grep in-process when they are invoked via BusyBox applet dispatch (similar in spirit to existing noexec-related optimizations). I have an initial implementation attached below, where: ? sed and grep are marked as noexec-capable applets ? the change is intended purely as a performance optimization Before refining or splitting this further, I?d like to confirm whether this direction is acceptable, and whether there are known concerns in sed/grep internals that would make noexec unsuitable. Thanks for your time and feedback. Signed-off-by: Ren Chunhui > editors/sed.c | 2 +- findutils/grep.c | 2 +- include/libbb.h | 2 ++ libbb/appletlib.c | 29 +++++++++++++++++++++++++++++ shell/ash.c | 2 +- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/editors/sed.c b/editors/sed.c index 6179c5e..10fb3d9 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -60,7 +60,7 @@ //config:??sed is used to perform text transformations on a file //config:??or input from a pipeline. -//applet:IF_SED(APPLET(sed, BB_DIR_BIN, BB_SUID_DROP)) +//applet:IF_SED(APPLET_NOEXEC(sed, sed, BB_DIR_BIN, BB_SUID_DROP, sed)) //kbuild:lib-$(CONFIG_SED) += sed.o diff --git a/findutils/grep.c b/findutils/grep.c index f6d0a73..7cb89da 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -44,7 +44,7 @@ //config:??context surrounding our matching lines. //config:??Print the specified number of context lines (-C). -//applet:IF_GREP(APPLET(grep, BB_DIR_BIN, BB_SUID_DROP)) +//applet:IF_GREP(APPLET_NOEXEC(grep, grep, BB_DIR_BIN, BB_SUID_DROP, grep)) // APPLET_ODDNAME:name main location suid_type help //applet:IF_EGREP(APPLET_ODDNAME(egrep, grep, BB_DIR_BIN, BB_SUID_DROP, egrep)) //applet:IF_FGREP(APPLET_ODDNAME(fgrep, grep, BB_DIR_BIN, BB_SUID_DROP, fgrep)) diff --git a/include/libbb.h b/include/libbb.h index 01cdb1b..6704213 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2658,6 +2658,8 @@ void bbunit_settestfailed(void); ???????????} \ ?????} while (0) +extern bool is_applet_forbidden_noexec(int applet_no); +extern bool is_applet_force_noexec(int applet_no); POP_SAVED_FUNCTION_VISIBILITY diff --git a/libbb/appletlib.c b/libbb/appletlib.c index d9cc484..915049d 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -1129,3 +1129,32 @@ int main(int argc UNUSED_PARAM, char **argv) #endif } + +static bool is_forbidden_noexec[NUM_APPLETS] = { +?????[66] = true, // APPLET_NO_gzip +?????[140] = true, // APPLET_NO_ps +?????[85] = true, // APPLET_NO_ip +?????[183] = true, // APPLET_NO_top +?????[106] = true, // APPLET_NO_lsattr +?????[177] = true, // APPLET_NO_taskset +}; + +bool is_applet_forbidden_noexec(int applet_no) +{ +?????if (applet_no < 0 || applet_no >= NUM_APPLETS) +???????????return false; +?????return is_forbidden_noexec[applet_no]; +} + +static bool is_force_noexec[NUM_APPLETS] = { +?????[6] = true, // APPLET_NO_awk +?????//[63] = true, // APPLET_NO_grep +?????[157] = true, // APPLET_NO_sed +}; + +bool is_applet_force_noexec(int applet_no) +{ +?????if (applet_no < 0 || applet_no >= NUM_APPLETS) +???????????return false; +?????return is_force_noexec[applet_no]; +} diff --git a/shell/ash.c b/shell/ash.c index bbd7307..8e83dab 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8336,7 +8336,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) ?????envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL); ?????if (strchr(prog, '/') != NULL #if ENABLE_FEATURE_SH_STANDALONE -????? || (applet_no = find_applet_by_name(prog)) >= 0 +????? || (((applet_no = find_applet_by_name(prog)) >= 0) +????? && !is_applet_forbidden_noexec(applet_no) +????? && is_applet_force_noexec(applet_no)) #endif ?????) { ???????????tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); -- 2.37.7 -------------- next part -------------- An HTML attachment was scrubbed... URL: