Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package busybox for openSUSE:Factory checked in at 2026-10-02 23:02:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/busybox (Old) and /work/SRC/openSUSE:Factory/.busybox.new.1631729 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "busybox" Fri Oct 2 23:02:21 2026 rev:100 rq:1381941 version:1.38.0 Changes: -------- --- /work/SRC/openSUSE:Factory/busybox/busybox.changes 2026-08-26 19:51:23.058785158 +0200 +++ /work/SRC/openSUSE:Factory/.busybox.new.1631729/busybox.changes 2026-10-02 23:02:57.836338968 +0200 @@ -1,0 +2,30 @@ +Thu Oct 1 00:00:00 UTC 2026 - Radoslav Kolev <[email protected]> + +- Fix pre-authentication heap buffer overflow in TLS caused by unit + confusion in the Montgomery reduction buffer allocation + (CVE-2026-88830, bsc#1282575) + * 0001-tls-fix-undersized-buffer-calculation.patch +- Fix httpd silently failing open when IP deny rules contain an + invalid CIDR prefix length (CVE-2026-88831, bsc#1282550) + * 0001-httpd-fix-handling-of-D-1.2.3-999.patch +- Fix heap buffer overflow when parsing the volume ID of crafted + romfs filesystem images (CVE-2026-88832, bsc#1282576) + * 0001-volume_id-romfs-limit-the-maximum-size-of-label-to-V.patch +- Fix out-of-bounds read in dpkg read_package_field() stepping past + the NUL terminator on malformed .deb packages + (CVE-2026-88835, bsc#1282551) + * 0001-dpkg-free-results-of-read_package_field-preliminary-.patch + * 0002-dpkg-reformat-code-in-read_package_field-exposing-wh.patch + * 0003-dpkg-fix-cases-where-read_package_field-returns-offs.patch +- Fix out-of-bounds read and silent corruption of the dpkg status + file caused by write_status_file() not resetting the field_start + cursor between package stanzas (CVE-2026-88841, bsc#1282653) + * 0004-dpkg-fix-field-handling-in-write_status_file.patch +- Fix httpd misidentifying yescrypt password hashes as plaintext + (CVE-2026-88837, bsc#1282552) + * 0001-httpd-allow-yescrypt-passwords-y.patch +- Fix out-of-bounds write of heap pointers in the passwd/group parser + due to a stale tokenize() endpoint (CVE-2026-88839, bsc#1282568) + * 0001-libpwdgrp-tokenizer-fix-for-trailing-whitespace-remo.patch + +------------------------------------------------------------------- New: ---- 0001-dpkg-free-results-of-read_package_field-preliminary-.patch 0001-httpd-allow-yescrypt-passwords-y.patch 0001-httpd-fix-handling-of-D-1.2.3-999.patch 0001-libpwdgrp-tokenizer-fix-for-trailing-whitespace-remo.patch 0001-tls-fix-undersized-buffer-calculation.patch 0001-volume_id-romfs-limit-the-maximum-size-of-label-to-V.patch 0002-dpkg-reformat-code-in-read_package_field-exposing-wh.patch 0003-dpkg-fix-cases-where-read_package_field-returns-offs.patch 0004-dpkg-fix-field-handling-in-write_status_file.patch ----------(New B)---------- New: (CVE-2026-88835, bsc#1282551) * 0001-dpkg-free-results-of-read_package_field-preliminary-.patch * 0002-dpkg-reformat-code-in-read_package_field-exposing-wh.patch New: (CVE-2026-88837, bsc#1282552) * 0001-httpd-allow-yescrypt-passwords-y.patch - Fix out-of-bounds write of heap pointers in the passwd/group parser New: invalid CIDR prefix length (CVE-2026-88831, bsc#1282550) * 0001-httpd-fix-handling-of-D-1.2.3-999.patch - Fix heap buffer overflow when parsing the volume ID of crafted New: due to a stale tokenize() endpoint (CVE-2026-88839, bsc#1282568) * 0001-libpwdgrp-tokenizer-fix-for-trailing-whitespace-remo.patch New: (CVE-2026-88830, bsc#1282575) * 0001-tls-fix-undersized-buffer-calculation.patch - Fix httpd silently failing open when IP deny rules contain an New: romfs filesystem images (CVE-2026-88832, bsc#1282576) * 0001-volume_id-romfs-limit-the-maximum-size-of-label-to-V.patch - Fix out-of-bounds read in dpkg read_package_field() stepping past New: * 0001-dpkg-free-results-of-read_package_field-preliminary-.patch * 0002-dpkg-reformat-code-in-read_package_field-exposing-wh.patch * 0003-dpkg-fix-cases-where-read_package_field-returns-offs.patch New: * 0002-dpkg-reformat-code-in-read_package_field-exposing-wh.patch * 0003-dpkg-fix-cases-where-read_package_field-returns-offs.patch - Fix out-of-bounds read and silent corruption of the dpkg status New: cursor between package stanzas (CVE-2026-88841, bsc#1282653) * 0004-dpkg-fix-field-handling-in-write_status_file.patch - Fix httpd misidentifying yescrypt password hashes as plaintext ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ busybox.spec ++++++ --- /var/tmp/diff_new_pack.OkofVy/_old 2026-10-02 23:02:59.254398320 +0200 +++ /var/tmp/diff_new_pack.OkofVy/_new 2026-10-02 23:02:59.257398445 +0200 @@ -60,6 +60,25 @@ Patch11: 0001-ash-fix-out-of-bounds-read-in-ifsbreakup.patch # PATCH-FIX-UPSTREAM - Fix bsc#1271548 (CVE-2026-38755), stack exhaustion on deep ash function recursion Patch12: ash-fix-evalfun.patch +# PATCH-FIX-UPSTREAM - Fix bsc#1282575 (CVE-2026-88830), undersized buffer in TLS Montgomery reduction (upstream commit 89ac82774) +Patch13: 0001-tls-fix-undersized-buffer-calculation.patch +# PATCH-FIX-UPSTREAM - Fix bsc#1282550 (CVE-2026-88831), httpd fails open on invalid CIDR prefix in deny rules (upstream commit 339e3c62f) +Patch14: 0001-httpd-fix-handling-of-D-1.2.3-999.patch +# PATCH-FIX-UPSTREAM - Fix bsc#1282576 (CVE-2026-88832), heap buffer overflow in romfs volume ID parsing (upstream commit 9073c1d15) +Patch15: 0001-volume_id-romfs-limit-the-maximum-size-of-label-to-V.patch +# We don't really need the 4 dpkg patches below, as building dpkg is disabled in the config, but since they are upstream add them just in case +# PATCH-FIX-UPSTREAM - Prerequisite for the dpkg fixes below (upstream commit e2c5cc042) +Patch16: 0001-dpkg-free-results-of-read_package_field-preliminary-.patch +# PATCH-FIX-UPSTREAM - Prerequisite for the dpkg fixes below (upstream commit 43a9d7d31) +Patch17: 0002-dpkg-reformat-code-in-read_package_field-exposing-wh.patch +# PATCH-FIX-UPSTREAM - Fix bsc#1282551 (CVE-2026-88835), dpkg read_package_field() OOB read past NUL (upstream commit f5a4a02a1) +Patch18: 0003-dpkg-fix-cases-where-read_package_field-returns-offs.patch +# PATCH-FIX-UPSTREAM - Fix bsc#1282653 (CVE-2026-88841), dpkg write_status_file() OOB read/status file corruption (upstream commit d5cc94063) +Patch19: 0004-dpkg-fix-field-handling-in-write_status_file.patch +# PATCH-FIX-UPSTREAM - Fix bsc#1282552 (CVE-2026-88837), httpd misidentifies yescrypt hashes as plaintext (upstream commit 9f5cbdcaa) +Patch20: 0001-httpd-allow-yescrypt-passwords-y.patch +# PATCH-FIX-UPSTREAM - Fix bsc#1282568 (CVE-2026-88839), passwd/group parser OOB write on stale tokenize() endpoint (upstream commit c2dec52d3) +Patch21: 0001-libpwdgrp-tokenizer-fix-for-trailing-whitespace-remo.patch # other patches Patch100: busybox.install.patch ++++++ 0001-dpkg-free-results-of-read_package_field-preliminary-.patch ++++++ >From e2c5cc04206008acc82d28dac4fcb1963e8f0acf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Mon, 21 Sep 2026 16:16:47 +0200 Subject: [PATCH] dpkg: free results of read_package_field(), preliminary cleanups in read_package_field() function old new delta dpkg_main 3910 3943 +33 write_buffer_no_status 92 114 +22 read_package_field 204 184 -20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 55/-20) Total: 35 bytes Signed-off-by: Denys Vlasenko <[email protected]> --- archival/dpkg.c | 80 +++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/archival/dpkg.c b/archival/dpkg.c index eda5ec7eb..4ca1daf9b 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -531,26 +531,31 @@ static void free_package(common_node_t *node) } /* - * Gets the next package field from package_buffer, separated into the field name - * and field value, it returns the int offset to the first character of the next field + * Gets the next package field from package_buffer: + * "Name:<whitespace>VALUE{\n|NUL}" + * "Name:<whitespace>\n + * " VALUE{\n|NUL}" + * separated into "NAME" and "VALUE", both strdup()ed. + * Returns the int offset to the first character of the next field. + * The package_buffer parameter is NUL-terminated. */ static int read_package_field(const char *package_buffer, char **field_name, char **field_value) { int offset_name_start = 0; int offset_name_end = 0; int offset_value_start = 0; - int offset_value_end = 0; int offset = 0; int next_offset; int name_length; int value_length; int exit_flag = FALSE; + *field_name = NULL; + *field_value = NULL; if (package_buffer == NULL) { - *field_name = NULL; - *field_value = NULL; return -1; } + while (1) { next_offset = offset + 1; switch (package_buffer[offset]) { @@ -566,14 +571,14 @@ static int read_package_field(const char *package_buffer, char **field_name, cha * immediately after name */ break; case '\n': - /* TODO: The char next_offset may be out of bounds */ if (package_buffer[next_offset] != ' ') { exit_flag = TRUE; break; } + /* fall through */ case '\t': case ' ': - /* increment the value start point if its a just filler */ + /* increment start points if it is just a filler */ if (offset_name_start == offset) { offset_name_start++; } @@ -584,9 +589,8 @@ static int read_package_field(const char *package_buffer, char **field_name, cha } if (exit_flag) { /* Check that the names are valid */ - offset_value_end = offset; name_length = offset_name_end - offset_name_start; - value_length = offset_value_end - offset_value_start; + value_length = offset - offset_value_start; if (name_length == 0) { break; } @@ -594,27 +598,26 @@ static int read_package_field(const char *package_buffer, char **field_name, cha break; } - /* If not valid, start fresh with next field */ + /* Not valid: start fresh with next field */ exit_flag = FALSE; offset_name_start = offset + 1; offset_name_end = 0; offset_value_start = offset + 1; - offset_value_end = offset + 1; offset++; } offset++; - } - *field_name = NULL; - if (name_length) { + } /* while (1) */ + + if (name_length > 0) { *field_name = xstrndup(&package_buffer[offset_name_start], name_length); } - *field_value = NULL; if (value_length > 0) { *field_value = xstrndup(&package_buffer[offset_value_start], value_length); } return next_offset; } +/* The parameter is NUL-terminated */ static unsigned fill_package_struct(char *control_buffer) { static const char field_names[] ALIGN1 = @@ -623,14 +626,14 @@ static unsigned fill_package_struct(char *control_buffer) "Conflicts\0""Suggests\0""Recommends\0""Enhances\0"; common_node_t *new_node = xzalloc(sizeof(common_node_t)); - char *field_name; - char *field_value; int field_start = 0; - int num = -1; int buffer_length = strlen(control_buffer); + int num; new_node->version = search_name_hashtable("unknown"); while (field_start < buffer_length) { + char *field_name; + char *field_value; unsigned field_num; field_start += read_package_field(&control_buffer[field_start], @@ -799,7 +802,7 @@ static void write_buffer_no_status(FILE *new_status_file, const char *control_bu char *name; char *value; int start = 0; - while (1) { + while (control_buffer[start]) { start += read_package_field(&control_buffer[start], &name, &value); if (name == NULL) { break; @@ -807,6 +810,8 @@ static void write_buffer_no_status(FILE *new_status_file, const char *control_bu if (strcmp(name, "Status") != 0) { fprintf(new_status_file, "%s: %s\n", name, value); } + free(name); + free(value); } } @@ -815,34 +820,35 @@ static void write_status_file(deb_file_t **deb_file) { FILE *old_status_file = xfopen_for_read("/var/lib/dpkg/status"); FILE *new_status_file = xfopen_for_write("/var/lib/dpkg/status.udeb"); - char *package_name; - char *status_from_file; - char *control_buffer = NULL; - char *tmp_string; - int status_num; + char *control_buffer; int field_start = 0; - int write_flag; - int i = 0; + int status_num; + int i; /* Update previously known packages */ while ((control_buffer = xmalloc_fgetline_str(old_status_file, "\n\n")) != NULL) { + char *package_name; + char *status_from_file; + char *tmp_string; + int write_flag; +//FIXME: "int field_start = 0;" should be _here_, right? + tmp_string = strstr(control_buffer, "Package:"); if (tmp_string == NULL) { + free(control_buffer); continue; } - tmp_string += 8; tmp_string += strspn(tmp_string, " \n\t"); package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n")); + write_flag = FALSE; + status_from_file = NULL; tmp_string = strstr(control_buffer, "Status:"); if (tmp_string != NULL) { - /* Separate the status value from the control buffer */ tmp_string += 7; tmp_string += strspn(tmp_string, " \n\t"); status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n")); - } else { - status_from_file = NULL; } /* Find this package in the status hashtable */ @@ -870,7 +876,7 @@ static void write_status_file(deb_file_t **deb_file) } i++; } - /* This is temperary, debugging only */ + /* This is temporary, debugging only */ if (deb_file[i] == NULL) { bb_error_msg_and_die("ALERT: cannot find a control file, " "your status file may be broken, status may be " @@ -882,7 +888,7 @@ static void write_status_file(deb_file_t **deb_file) fprintf(new_status_file, "Package: %s\n", package_name); fprintf(new_status_file, "Status: %s\n", status_from_hashtable); - while (1) { + while (control_buffer[field_start]) { char *field_name; char *field_value; field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value); @@ -894,13 +900,15 @@ static void write_status_file(deb_file_t **deb_file) ) { fprintf(new_status_file, "%s: %s\n", field_name, field_value); } + free(field_name); + free(field_value); } write_flag = TRUE; fputs("\n", new_status_file); } else if (strcmp("config-files", name_hashtable[state_status]) == 0) { /* only change the status line */ - while (1) { + while (control_buffer[field_start]) { char *field_name; char *field_value; field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value); @@ -913,13 +921,15 @@ static void write_status_file(deb_file_t **deb_file) } else { fprintf(new_status_file, "%s: %s\n", field_name, field_value); } + free(field_name); + free(field_value); } write_flag = TRUE; fputs("\n", new_status_file); } } } - /* If the package from the status file wasn't handle above, do it now*/ + /* If the package from the status file wasn't handled above, do it now */ if (!write_flag) { fprintf(new_status_file, "%s\n\n", control_buffer); } @@ -927,7 +937,7 @@ static void write_status_file(deb_file_t **deb_file) free(status_from_file); free(package_name); free(control_buffer); - } + } /* while (control_buffer) */ /* Write any new packages */ for (i = 0; deb_file[i] != NULL; i++) { ++++++ 0001-httpd-allow-yescrypt-passwords-y.patch ++++++ >From 9f5cbdcaa5972d58503c59cd0da13da1e5bb272b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Tue, 22 Sep 2026 01:14:47 +0200 Subject: [PATCH] httpd: allow yescrypt passwords ("$y$....") function old new delta check_user_passwd 439 444 +5 Signed-off-by: Denys Vlasenko <[email protected]> --- loginutils/Config.src | 2 +- networking/httpd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loginutils/Config.src b/loginutils/Config.src index a7812bd32..5559992da 100644 --- a/loginutils/Config.src +++ b/loginutils/Config.src @@ -96,7 +96,7 @@ config USE_BB_CRYPT_YES default y depends on USE_BB_CRYPT help - Enable this if you have passwords starting with "$y$" or + Enable this if you have passwords starting with "$y$" in your /etc/passwd or /etc/shadow files. These passwords are hashed using yescrypt algorithms. With this option off, login will fail password check for any diff --git a/networking/httpd.c b/networking/httpd.c index a5dfb38af..842574e0e 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -2247,7 +2247,7 @@ static int check_user_passwd(const char *path, char *user_and_passwd) } /* Else: passwd is from httpd.conf, it is either plaintext or encrypted */ - if (passwd[0] == '$' && isdigit(passwd[1])) { + if (passwd[0] == '$' && (isdigit(passwd[1]) || passwd[1] == 'y')) { char *encrypted; # if !ENABLE_PAM check_encrypted: ++++++ 0001-httpd-fix-handling-of-D-1.2.3-999.patch ++++++ >From 339e3c62f5bcf252839c8abca5325f48a22f21aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Mon, 21 Sep 2026 04:40:37 +0200 Subject: [PATCH] httpd: fix handling of "D:1.2.3/999" An error in allow/deny rule should be interpreted as D:0/0 ("deny all") but was interpreted as D:IP/0. Fix this. function old new delta parse_conf 1323 1330 +7 Signed-off-by: Denys Vlasenko <[email protected]> --- networking/httpd.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/networking/httpd.c b/networking/httpd.c index ad59493d7..bc446a838 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -41,7 +41,7 @@ * H:/serverroot # define the server root. It will override -h * A:172.20. # Allow address from 172.20.0.0/16 * A:10.0.0.0/25 # Allow any address from 10.0.0.0-10.0.0.127 - * A:10.0.0.0/255.255.255.128 # Allow any address that previous set + * A:10.0.0.0/255.255.255.128 # Same as the previous * A:127.0.0.1 # Allow local loopback connections * D:* # Deny from other IP connections * E404:/path/e404.html # /path/e404.html is the 404 (not found) error page @@ -63,7 +63,7 @@ * Deny/Allow IP logic: * - Default is to allow all (Allow all (A:*) is a no-op). * - Deny rules take precedence over allow rules. - * - "Deny all" rule (D:*) is applied last. + * - However, "Deny all" rule (D:*) is applied last. * * Example: * 1. Allow only specified addresses @@ -381,8 +381,8 @@ typedef struct Htaccess { /* Must have "next" as a first member */ typedef struct Htaccess_IP { struct Htaccess_IP *next; - unsigned ip; - unsigned mask; + uint32_t ip; /* host-endian */ + uint32_t mask; /* host-endian */ int allow_deny; } Htaccess_IP; #endif @@ -653,11 +653,11 @@ static ALWAYS_INLINE void free_Htaccess_IP_list(Htaccess_IP **pptr) #if ENABLE_FEATURE_HTTPD_ACL_IP /* Returns presumed mask width in bits or < 0 on error. * Updates strp, stores IP at provided pointer */ -static int scan_ip(const char **strp, unsigned *ipp, unsigned char endc) +static int scan_ip(const char **strp, uint32_t *ipp, unsigned char endc) { const char *p = *strp; int auto_mask = 8; - unsigned ip = 0; + uint32_t ip = 0; int j; if (*p == '/') @@ -695,10 +695,10 @@ static int scan_ip(const char **strp, unsigned *ipp, unsigned char endc) } /* Returns 0 on success. Stores IP and mask at provided pointers */ -static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp) +static int scan_ip_mask(const char *str, uint32_t *ipp, uint32_t *maskp) { int i; - unsigned mask; + uint32_t mask; char *p; i = scan_ip(&str, ipp, '/'); @@ -713,15 +713,16 @@ static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp) /* (return 0 (success) only if it has N.N.N.N form) */ return scan_ip(&str, maskp, '\0') - 32; } - if (*p) + if (*p) /* 'xxx' had something apart from just digits */ return -1; } + //else: i = "automask" (the count of explicit IP components: "10.0[.]" = 16) if (i > 32) return -1; - if (sizeof(unsigned) == 4 && i == 32) { - /* mask >>= 32 below may not work */ + if (i == 32) { + /* mask >>= 32 below may not work (according to C standard) */ mask = 0; } else { mask = 0xffffffff; @@ -890,15 +891,18 @@ static int parse_conf(const char *path, int flag) if (scan_ip_mask(after_colon, &pip->ip, &pip->mask)) { /* IP{/mask} syntax error detected, protect all */ ch = 'D'; + //bb_error_msg("ERR"); + pip->ip = 0; /* could be set before error is detected - zero it (again) */ pip->mask = 0; } + //bb_error_msg_and_die("ip:0x%08x mask:0x%08x", pip->ip, pip->mask); pip->allow_deny = ch; if (ch == 'D') { /* Deny:from_IP - prepend */ pip->next = G.ip_a_d; G.ip_a_d = pip; } else { - /* A:from_IP - append (thus all D's precedes A's) */ + /* A:from_IP - append (thus all D's precede A's) */ Htaccess_IP *prev_IP = G.ip_a_d; if (prev_IP == NULL) { G.ip_a_d = pip; @@ -2045,7 +2049,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what) } #if ENABLE_FEATURE_HTTPD_ACL_IP -static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip) +static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(uint32_t remote_ip) { Htaccess_IP *cur; @@ -2337,7 +2341,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) char *urlp; char *tptr; #if ENABLE_FEATURE_HTTPD_ACL_IP - unsigned remote_ip; + uint32_t remote_ip; #endif #if ENABLE_FEATURE_HTTPD_CGI unsigned total_headers_len; ++++++ 0001-libpwdgrp-tokenizer-fix-for-trailing-whitespace-remo.patch ++++++ >From c2dec52d37380d27d89827cf01a770f6b3b04e3a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Tue, 22 Sep 2026 02:19:06 +0200 Subject: [PATCH] libpwdgrp: tokenizer fix for trailing whitespace removeal. The tokenize() function trims trailing whitespace via overlapping_strcpy() but continues to reference the stale *end pointer. Fixing this. function old new delta tokenize 120 119 -1 Signed-off-by: Denys Vlasenko <[email protected]> --- libpwdgrp/pwd_grp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 10debbcdb..48a49fc24 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -171,7 +171,7 @@ static int tokenize(char *buffer, int ch) if (p != end) overlapping_strcpy(p, end); num_fields++; - if (*end == '\0') { + if (*p == '\0') { S.tokenize_end = p + 1; return num_fields; } ++++++ 0001-tls-fix-undersized-buffer-calculation.patch ++++++ >From 89ac82774f90e270d04ed5299e5cf05dfbc314c1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Mon, 21 Sep 2026 03:19:28 +0200 Subject: [PATCH] tls: fix undersized buffer calculation All callers of pstm_montgomery_reduce() are currently in pstm_exptmod() and they all pass a preallocated temporary buffer, so the incorrect code is unreachable. But fix it anyway. function old new delta pstm_montgomery_reduce 431 430 -1 Signed-off-by: Denys Vlasenko <[email protected]> --- networking/tls_pstm_montgomery_reduce.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c index e63e590db..36882425a 100644 --- a/networking/tls_pstm_montgomery_reduce.c +++ b/networking/tls_pstm_montgomery_reduce.c @@ -370,6 +370,7 @@ int32 FAST_FUNC pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, pstm_digit *c, *_c, *tmpm, mu; int32 oldused, x, y; int pa; //bbox: was int16 + uint32 cSize; pa = m->used; if (pa > a->alloc) { @@ -377,11 +378,13 @@ int32 FAST_FUNC pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, return PS_LIMIT_FAIL; } - if (paD && paDlen >= (uint32)2*pa+1) { + cSize = (2 * pa + 1) * sizeof(pstm_digit); + if (paD && paDlen >= cSize) { c = paD; memset(c, 0x0, paDlen); } else { - c = xzalloc(2*pa+1);//bbox + //bbox: dead code, all callers always pass paD: + c = xzalloc(cSize); //bbox } /* copy the input */ oldused = a->used; @@ -441,7 +444,8 @@ int32 FAST_FUNC pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, x = PS_MEM_FAIL; } } - if (paDlen < (uint32)2*pa+1) { + //bbox: dead code, all callers always pass paD: + if (c != paD) { psFree(c, pool); } return x; ++++++ 0001-volume_id-romfs-limit-the-maximum-size-of-label-to-V.patch ++++++ >From 9073c1d15c9953c6f1e39145815fc5dccfa6081c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Mon, 21 Sep 2026 05:34:19 +0200 Subject: [PATCH] volume_id/romfs: limit the maximum size of label to VOLUME_ID_LABEL_SIZE function old new delta volume_id_set_label_string 71 81 +10 volume_id_probe_romfs 94 97 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 13/0) Total: 13 bytes Signed-off-by: Denys Vlasenko <[email protected]> --- util-linux/volume_id/romfs.c | 4 ++-- util-linux/volume_id/util.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/util-linux/volume_id/romfs.c b/util-linux/volume_id/romfs.c index bd74fda8d..475144c43 100644 --- a/util-linux/volume_id/romfs.c +++ b/util-linux/volume_id/romfs.c @@ -44,8 +44,8 @@ int FAST_FUNC volume_id_probe_romfs(struct volume_id *id /*,uint64_t off*/) if (rfs == NULL) return -1; - if (memcmp(rfs->magic, "-rom1fs-", 4) == 0) { - size_t len = strlen((char *)rfs->name); + if (memcmp(rfs->magic, "-rom1fs-", 8) == 0) { + size_t len = strnlen((char *)rfs->name, VOLUME_ID_LABEL_SIZE); if (len) { // volume_id_set_label_raw(id, rfs->name, len); diff --git a/util-linux/volume_id/util.c b/util-linux/volume_id/util.c index b59aa99b2..a2bee28ab 100644 --- a/util-linux/volume_id/util.c +++ b/util-linux/volume_id/util.c @@ -116,6 +116,10 @@ void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t { unsigned i; + /* Do not overflow label[VOLUME_ID_LABEL_SIZE+1] */ + if (count > VOLUME_ID_LABEL_SIZE) + count = VOLUME_ID_LABEL_SIZE; + memcpy(id->label, buf, count); /* remove trailing whitespace */ ++++++ 0002-dpkg-reformat-code-in-read_package_field-exposing-wh.patch ++++++ >From 43a9d7d31560ad4e9d6a341207b1aa191cb9b0db Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Mon, 21 Sep 2026 16:32:43 +0200 Subject: [PATCH] dpkg: reformat code in read_package_field(), exposing why it's buggy function old new delta read_package_field 184 169 -15 Signed-off-by: Denys Vlasenko <[email protected]> --- archival/dpkg.c | 56 +++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/archival/dpkg.c b/archival/dpkg.c index 4ca1daf9b..860256f0e 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -548,20 +548,13 @@ static int read_package_field(const char *package_buffer, char **field_name, cha int next_offset; int name_length; int value_length; - int exit_flag = FALSE; *field_name = NULL; *field_value = NULL; - if (package_buffer == NULL) { - return -1; - } while (1) { next_offset = offset + 1; switch (package_buffer[offset]) { - case '\0': - exit_flag = TRUE; - break; case ':': if (offset_name_end == 0) { offset_name_end = offset; @@ -572,8 +565,7 @@ static int read_package_field(const char *package_buffer, char **field_name, cha break; case '\n': if (package_buffer[next_offset] != ' ') { - exit_flag = TRUE; - break; + goto end_of_value; } /* fall through */ case '\t': @@ -586,35 +578,31 @@ static int read_package_field(const char *package_buffer, char **field_name, cha offset_value_start++; } break; - } - if (exit_flag) { - /* Check that the names are valid */ - name_length = offset_name_end - offset_name_start; - value_length = offset - offset_value_start; - if (name_length == 0) { - break; - } - if ((name_length > 0) && (value_length > 0)) { + case '\0': + end_of_value: + /* Check that the names are valid */ + name_length = offset_name_end - offset_name_start; + value_length = offset - offset_value_start; + if ((name_length > 0) && (value_length > 0)) { + if (name_length > 0) { + *field_name = xstrndup(&package_buffer[offset_name_start], name_length); + } + if (value_length > 0) { + *field_value = xstrndup(&package_buffer[offset_value_start], value_length); + } + return next_offset; + } + if (!package_buffer[offset]) + return next_offset; //BUG! past NUL + /* Not valid: start fresh with next field */ + offset_name_start = offset + 1; + offset_name_end = 0; + offset_value_start = offset + 1; + offset++; //BUG? break; - } - - /* Not valid: start fresh with next field */ - exit_flag = FALSE; - offset_name_start = offset + 1; - offset_name_end = 0; - offset_value_start = offset + 1; - offset++; } offset++; } /* while (1) */ - - if (name_length > 0) { - *field_name = xstrndup(&package_buffer[offset_name_start], name_length); - } - if (value_length > 0) { - *field_value = xstrndup(&package_buffer[offset_value_start], value_length); - } - return next_offset; } /* The parameter is NUL-terminated */ ++++++ 0003-dpkg-fix-cases-where-read_package_field-returns-offs.patch ++++++ >From f5a4a02a157e250d28976e2ba4ea61a2fa7eb51f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Mon, 21 Sep 2026 16:59:56 +0200 Subject: [PATCH] dpkg: fix cases where read_package_field() returns offset past NUL function old new delta read_package_field 169 211 +42 Signed-off-by: Denys Vlasenko <[email protected]> --- archival/dpkg.c | 63 +++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/archival/dpkg.c b/archival/dpkg.c index 860256f0e..b8d8eb648 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -532,8 +532,8 @@ static void free_package(common_node_t *node) /* * Gets the next package field from package_buffer: - * "Name:<whitespace>VALUE{\n|NUL}" - * "Name:<whitespace>\n + * "<whitespace>Name:<whitespace>VALUE{\n|NUL}" + * "<whitespace>Name:<whitespace>\n * " VALUE{\n|NUL}" * separated into "NAME" and "VALUE", both strdup()ed. * Returns the int offset to the first character of the next field. @@ -541,64 +541,61 @@ static void free_package(common_node_t *node) */ static int read_package_field(const char *package_buffer, char **field_name, char **field_value) { - int offset_name_start = 0; - int offset_name_end = 0; - int offset_value_start = 0; - int offset = 0; - int next_offset; - int name_length; - int value_length; + int offset_name_start; + int offset_name_end; + int offset_value_start = offset_value_start; + int offset; *field_name = NULL; *field_value = NULL; + offset = 0; + offset_name_start = 0; + offset_name_end = 0; /* "we did not see ':' yet" */ while (1) { - next_offset = offset + 1; - switch (package_buffer[offset]) { + char ch = package_buffer[offset]; + switch (ch) { case ':': if (offset_name_end == 0) { - offset_name_end = offset; - offset_value_start = next_offset; + offset_name_end = offset + 1; /* points AFTER ':' - think of empty NAME case */ + offset_value_start = offset + 1; } - /* TODO: Name might still have trailing spaces if ':' isn't + /* TODO: NAME might still have trailing spaces if ':' isn't * immediately after name */ break; case '\n': - if (package_buffer[next_offset] != ' ') { + if (package_buffer[offset + 1] != ' ') goto end_of_value; - } /* fall through */ case '\t': case ' ': /* increment start points if it is just a filler */ - if (offset_name_start == offset) { + if (offset_name_start == offset) offset_name_start++; - } - if (offset_value_start == offset) { + if (offset_value_start == offset) offset_value_start++; - } break; case '\0': end_of_value: - /* Check that the names are valid */ - name_length = offset_name_end - offset_name_start; - value_length = offset - offset_value_start; - if ((name_length > 0) && (value_length > 0)) { - if (name_length > 0) { + /* Did we see the ':'? */ + if (offset_name_end != 0) { + /* Yes. Check that NAME and VALUE exist and not empty */ + int name_length = (offset_name_end - 1) - offset_name_start; + int value_length = offset - offset_value_start; + if ((name_length > 0) && (value_length > 0)) { *field_name = xstrndup(&package_buffer[offset_name_start], name_length); - } - if (value_length > 0) { *field_value = xstrndup(&package_buffer[offset_value_start], value_length); + if (ch) + offset++; /* skip '\n' */ + return offset; } - return next_offset; } - if (!package_buffer[offset]) - return next_offset; //BUG! past NUL + if (!ch) + return offset; /* stop at NUL */ + /* Not valid: start fresh with next field */ offset_name_start = offset + 1; - offset_name_end = 0; - offset_value_start = offset + 1; - offset++; //BUG? + offset_name_end = 0; /* "we did not see ':' yet" */ break; } offset++; ++++++ 0004-dpkg-fix-field-handling-in-write_status_file.patch ++++++ >From d5cc94063b2bb5b54fe1021e54600cbcbce6a350 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <[email protected]> Date: Tue, 22 Sep 2026 01:04:32 +0200 Subject: [PATCH] dpkg: fix field handling in write_status_file() function old new delta dpkg_main 3943 3934 -9 Signed-off-by: Denys Vlasenko <[email protected]> --- [Backport note: dropped the upstream comment-only hunk that renames "Name" to "NAME" in the read_package_field() description, as it depends on the unrelated variable-renaming commit 7c611860d.] --- archival/dpkg.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/archival/dpkg.c b/archival/dpkg.c index 3abc810c8..6a65f16a4 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -809,7 +809,6 @@ static void write_status_file(deb_file_t **deb_file) FILE *old_status_file = xfopen_for_read("/var/lib/dpkg/status"); FILE *new_status_file = xfopen_for_write("/var/lib/dpkg/status.udeb"); char *control_buffer; - int field_start = 0; int status_num; int i; @@ -819,23 +818,20 @@ static void write_status_file(deb_file_t **deb_file) char *status_from_file; char *tmp_string; int write_flag; -//FIXME: "int field_start = 0;" should be _here_, right? tmp_string = strstr(control_buffer, "Package:"); if (tmp_string == NULL) { free(control_buffer); continue; } - tmp_string += 8; - tmp_string += strspn(tmp_string, " \n\t"); + tmp_string = skip_whitespace(tmp_string + 8); package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n")); write_flag = FALSE; status_from_file = NULL; tmp_string = strstr(control_buffer, "Status:"); if (tmp_string != NULL) { - tmp_string += 7; - tmp_string += strspn(tmp_string, " \n\t"); + tmp_string = skip_whitespace(tmp_string + 7); status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n")); } @@ -872,6 +868,8 @@ static void write_status_file(deb_file_t **deb_file) } } else if (strcmp("not-installed", name_hashtable[state_status]) == 0) { + int field_start = 0; + /* Only write the Package, Status, Priority and Section lines */ fprintf(new_status_file, "Package: %s\n", package_name); fprintf(new_status_file, "Status: %s\n", status_from_hashtable); @@ -880,6 +878,8 @@ static void write_status_file(deb_file_t **deb_file) char *field_name; char *field_value; field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value); +//FIXME: the questionable ": VALUE" lines (empty NAME) +//probably should not stop parsing of the entire file? if (field_name == NULL) { break; } @@ -895,6 +895,8 @@ static void write_status_file(deb_file_t **deb_file) fputs("\n", new_status_file); } else if (strcmp("config-files", name_hashtable[state_status]) == 0) { + int field_start = 0; + /* only change the status line */ while (control_buffer[field_start]) { char *field_name;
