]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
musl: update to 1.2.6 22547/head
authorHannu Nyman <hannu.nyman@iki.fi>
Thu, 21 May 2026 13:07:31 +0000 (16:07 +0300)
committerHauke Mehrtens <hauke@hauke-m.de>
Mon, 25 May 2026 21:37:21 +0000 (23:37 +0200)
Update musl C library to 1.2.6. Fixes CVE-2025-26519

* Patches refreshed. Unnecessary upstream patch removed.

* Add a post-release patch for timezone handling in datetime string
  matching (affecting at least uhttpd):
  bug report: https://www.openwall.com/lists/musl/2026/03/22/3
  fix: https://www.openwall.com/lists/musl/2026/03/30/6

1.2.6 release notes
https://git.musl-libc.org/cgit/musl/tree/WHATSNEW?id=9fa28ece75d8a2191de7c5bb53bed224c5947417

new features:
- posix_getdents interface (new in POSIX-2024)
- renameat2 interface (linux extension)
- iconv support for CP858
- vdso clock_gettime for riscv{32,64}, powerpc{,64}, and s390x
- loongarch64 TLSDESC support
- exposed __getauxval for compiler runtime use detecting cpu features

compatibility:
- initgroups no longer artificially limits number of supplementary groups
- getusershell now skips blank lines and comments
- exit is now explicitly thread-safe (possible future requirement)
- atexit now fails rather than deadlocking if called from late dtor
- strerror now has error strings for EUCLEAN and ENAVAIL
- isatty no longer collapses errors to ENOTTY
- sched.h namespace pollution with _GNU_SOURCE is reduced
- hasmntopt now matches only whole options, not arbitrary substrings
- shadow.h no longer declares an unimplemented sgetspent interface
- vdso with missing sysv hash table (only gnu hash) is now supported

conformance:
- pwrite now handles O_APPEND correctly, reports error if it can't
- mbnrtowcs now conforms to new POSIX-2024 requirement for partial character
- iconv GBK now properly includes euro symbol
- strptime now accepts conversion specifiers added in POSIX-2024
- inet_ntop IPv6 "zero compression" now conforms to RFC 5952

bugs fixed:
- iconv euc-kr decoder could do oob writes on invalid inputs (CVE-2025-26519)
- iconv shift_jis decoder could produce wrong outputs for some invalid inputs
- printf did not honor hex float precision correctly in some cases
- lost or delayed wakes in sem_post under race condition
- termios input speed handling was wrong
- strcasestr failed to match zero-length needle
- fma handled corner case with negative zero wrongly
- syslog LOG_MAKEPRI macro was incorrect
- timer_create is no longer affected by known pthread_barrier bugs
- sysconf(_SC_MINSIGSTKSZ) computed min size incorrectly
- statx emulation left some fields uninitialized
- mntent wrongly included final newline in parsed field output
- SIGEV_THREAD timers could abort process if SIGTIMER became unblocked
- bind_textdomain_codeset returned wrong value

arch-specific bugs fixed:
- early dynamic linker handled page size wrong on dynamic pagesize archs
- arm and aarch64 crti/n files had wrong alignment
- m68k POLLWRNORM and POLLWRBAND values were incorrect
- x32 mq ABI was mismatched

Signed-off-by: Hannu Nyman <hannu.nyman@iki.fi>
Link: https://github.com/openwrt/openwrt/pull/22547
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
toolchain/musl/common.mk
toolchain/musl/patches/001-fix-1.2.6-incorrect-access-to-tzname-by-strptime-Z-convers.patch [new file with mode: 0644]
toolchain/musl/patches/003-fix-pathological-slowness-incorrect-mappings-in-icon.patch
toolchain/musl/patches/110-read_timezone_from_fs.patch
toolchain/musl/patches/610-add-renameat2-linux-syscall-wrapper.patch [deleted file]
toolchain/musl/patches/900-iconv_size_hack.patch

index 35bdfd184be852fea35391ad2ad6bee3831fceb8..10bd51768e48697dba156ee9cc034462600cc94b 100644 (file)
@@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk
 include $(INCLUDE_DIR)/target.mk
 
 PKG_NAME:=musl
-PKG_VERSION:=1.2.5
+PKG_VERSION:=1.2.6
 PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=https://musl.libc.org/releases/
-PKG_HASH:=a9a118bbe84d8764da0ea0d28b3ab3fae8477fc7e4085d90102b8596fc7c75e4
+PKG_HASH:=d585fd3b613c66151fc3249e8ed44f77020cb5e6c1e635a616d3f9f82460512a
 PKG_CPE_ID:=cpe:/a:musl-libc:musl
 
 LIBC_SO_VERSION:=$(PKG_VERSION)
diff --git a/toolchain/musl/patches/001-fix-1.2.6-incorrect-access-to-tzname-by-strptime-Z-convers.patch b/toolchain/musl/patches/001-fix-1.2.6-incorrect-access-to-tzname-by-strptime-Z-convers.patch
new file mode 100644 (file)
index 0000000..6ed5b02
--- /dev/null
@@ -0,0 +1,99 @@
+From 0572555dab1d1e10b5f7351a005ec588cab41e25 Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Sun, 22 Mar 2026 21:32:35 -0400
+Subject: [PATCH] fix incorrect access to tzname[] by strptime %Z conversion
+ specifier
+
+there are three issues here:
+
+1. if tzset has not been called (explicitly or implicitly), the
+tzname[] array will contain null pointers, and the dereference to
+compare against them has undefined behavior (and will fault).
+
+2. access to tzname[] was performed without the timezone lock held.
+this resulted in a data race if the timezone is concurrently changed
+from another thread.
+
+3. due to unintended signedness of the types, the open-coded isalpha
+in the non-matching case was wrong and would continue past null
+termination.
+
+to fix the first two issues, the body of the %Z conversion is moved to
+__tz.c where it has access to locking, and null checks are added.
+
+there is probably an argument to be made that the equivalent of tzset
+should happen here, but POSIX does not specify that to happen, so in
+the absence of an interpretation adding such an allowance or
+requirement, it is not done.
+
+the third issue is fixed just by using the existing isalpha macro.
+---
+ src/time/__tz.c      | 19 +++++++++++++++++++
+ src/time/strptime.c  | 13 +++----------
+ src/time/time_impl.h |  1 +
+ 3 files changed, 23 insertions(+), 10 deletions(-)
+
+--- a/src/time/__tz.c
++++ b/src/time/__tz.c
+@@ -436,3 +436,22 @@ const char *__tm_to_tzname(const struct
+       UNLOCK(lock);
+       return p;
+ }
++
++int __tzname_to_isdst(const char *restrict *s)
++{
++      size_t len;
++      int isdst = -1;
++      LOCK(lock);
++      if (tzname[0] && !strncmp(*s, tzname[0], len = strlen(tzname[0]))) {
++              isdst = 0;
++              *s += len;
++      } else if (tzname[1] && !strncmp(*s, tzname[1], len=strlen(tzname[1]))) {
++              isdst = 1;
++              *s += len;
++      } else {
++              /* FIXME: is this supposed to be an error? */
++              while (isalpha(**s)) ++*s;
++      }
++      UNLOCK(lock);
++      return isdst;
++}
+--- a/src/time/strptime.c
++++ b/src/time/strptime.c
+@@ -5,6 +5,7 @@
+ #include <stddef.h>
+ #include <string.h>
+ #include <strings.h>
++#include "time_impl.h"
+ char *strptime(const char *restrict s, const char *restrict f, struct tm *restrict tm)
+ {
+@@ -207,16 +208,8 @@ char *strptime(const char *restrict s, c
+                       s += 5;
+                       break;
+               case 'Z':
+-                      if (!strncmp(s, tzname[0], len = strlen(tzname[0]))) {
+-                              tm->tm_isdst = 0;
+-                              s += len;
+-                      } else if (!strncmp(s, tzname[1], len=strlen(tzname[1]))) {
+-                              tm->tm_isdst = 1;
+-                              s += len;
+-                      } else {
+-                              /* FIXME: is this supposed to be an error? */
+-                              while ((*s|32)-'a' <= 'z'-'a') s++;
+-                      }
++                      i = __tzname_to_isdst(&s);
++                      if (i>=0) tm->tm_isdst = i;
+                       break;
+               case '%':
+                       if (*s++ != '%') return 0;
+--- a/src/time/time_impl.h
++++ b/src/time/time_impl.h
+@@ -5,6 +5,7 @@ hidden int __month_to_secs(int, int);
+ hidden long long __year_to_secs(long long, int *);
+ hidden long long __tm_to_secs(const struct tm *);
+ hidden const char *__tm_to_tzname(const struct tm *);
++hidden int __tzname_to_isdst(const char *restrict *);
+ hidden int __secs_to_tm(long long, struct tm *);
+ hidden void __secs_to_zone(long long, int, int *, long *, long *, const char **);
+ hidden const char *__strftime_fmt_1(char (*)[100], size_t *, int, const struct tm *, locale_t, int);
index 11dc0464d58b5b51250ea1f330931a0cab39aae3..a14765cef9e95569d9422bcf4df5fec2def5a31f 100644 (file)
@@ -276,7 +276,7 @@ postprocessing step that will be added later.
  size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restrict out, size_t *restrict outb)
  {
        size_t x=0;
-@@ -423,15 +429,24 @@ size_t iconv(iconv_t cd, char **restrict
+@@ -430,15 +436,24 @@ size_t iconv(iconv_t cd, char **restrict
                                d = *((unsigned char *)*in + 3);
                                if (d-'0'>9) goto ilseq;
                                c += d-'0';
index e1d0f3ac7a40a8b135a48bf33dcf1188b50b7b52..a1f54db5519908f04bc22b648373b3687901cc9a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/src/time/__tz.c
 +++ b/src/time/__tz.c
-@@ -32,6 +32,9 @@ static int r0[5], r1[5];
+@@ -31,6 +31,9 @@ static int r0[5], r1[5];
  static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end;
  static size_t map_size;
  
@@ -10,7 +10,7 @@
  static char old_tz_buf[32];
  static char *old_tz = old_tz_buf;
  static size_t old_tz_size = sizeof old_tz_buf;
-@@ -133,6 +136,15 @@ static void do_tzset()
+@@ -132,6 +135,15 @@ static void do_tzset()
                "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0";
  
        s = getenv("TZ");
diff --git a/toolchain/musl/patches/610-add-renameat2-linux-syscall-wrapper.patch b/toolchain/musl/patches/610-add-renameat2-linux-syscall-wrapper.patch
deleted file mode 100644 (file)
index 1677693..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-From dc651fe2e6b16087c519c0bd0bf943cb7c53c807 Mon Sep 17 00:00:00 2001
-In-Reply-To: <20240423234355.2414567-1-Tony.Ambardar@gmail.com>
-References: <20240423234355.2414567-1-Tony.Ambardar@gmail.com>
-From: Tony Ambardar <Tony.Ambardar@gmail.com>
-Date: Sat, 20 Apr 2024 21:30:13 -0700
-Subject: [PATCH v3] add renameat2 linux syscall wrapper
-To: musl@lists.openwall.com
-Cc: Rich Felker <dalias@libc.org>
-
-This syscall is available since Linux 3.15 and also implemented in glibc
-from version 2.28. It is commonly used in filesystem or security contexts.
-
-Constants RENAME_NOREPLACE, RENAME_EXCHANGE, RENAME_WHITEOUT are guarded by
-_GNU_SOURCE as with glibc.
-
-Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
----
-v2 -> v3:
- * call SYS_renameat first if applicable
- * drop unneeded error code handling
-
-v1 -> v2:
- * align related constants
- * drop 'int' from 'unsigned int'
- * add fallback to SYS_renameat where applicable
----
- include/stdio.h       |  7 +++++++
- src/linux/renameat2.c | 11 +++++++++++
- 2 files changed, 18 insertions(+)
- create mode 100644 src/linux/renameat2.c
-
---- a/include/stdio.h
-+++ b/include/stdio.h
-@@ -158,6 +158,13 @@ char *ctermid(char *);
- #define L_ctermid 20
- #endif
-+#if defined(_GNU_SOURCE)
-+#define RENAME_NOREPLACE (1 << 0)
-+#define RENAME_EXCHANGE  (1 << 1)
-+#define RENAME_WHITEOUT  (1 << 2)
-+
-+int renameat2(int, const char *, int, const char *, unsigned);
-+#endif
- #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
-  || defined(_BSD_SOURCE)
---- /dev/null
-+++ b/src/linux/renameat2.c
-@@ -0,0 +1,11 @@
-+#define _GNU_SOURCE
-+#include <stdio.h>
-+#include "syscall.h"
-+
-+int renameat2(int oldfd, const char *old, int newfd, const char *new, unsigned flags)
-+{
-+#ifdef SYS_renameat
-+      if (!flags) return syscall(SYS_renameat, oldfd, old, newfd, new);
-+#endif
-+      return syscall(SYS_renameat2, oldfd, old, newfd, new, flags);
-+}
index 8dc0471386c6f1d84839c7151041abf5e72ad8c8..b3085d45392804f38a24a674c4ece1fed8c27ada 100644 (file)
@@ -56,7 +56,7 @@
                case SHIFT_JIS:
                        if (c < 128) break;
                        if (c-0xa1 <= 0xdf-0xa1) {
-@@ -533,6 +540,7 @@ size_t iconv(iconv_t cd, char **restrict
+@@ -540,6 +547,7 @@ size_t iconv(iconv_t cd, char **restrict
                        c = ksc[c][d];
                        if (!c) goto ilseq;
                        break;
@@ -64,7 +64,7 @@
                default:
                        if (!c) break;
                        c = legacy_map(map, c);
-@@ -574,6 +582,7 @@ size_t iconv(iconv_t cd, char **restrict
+@@ -585,6 +593,7 @@ size_t iconv(iconv_t cd, char **restrict
                                }
                        }
                        goto subst;
@@ -72,7 +72,7 @@
                case SHIFT_JIS:
                        if (c < 128) goto revout;
                        if (c == 0xa5) {
-@@ -647,6 +656,7 @@ size_t iconv(iconv_t cd, char **restrict
+@@ -658,6 +667,7 @@ size_t iconv(iconv_t cd, char **restrict
                        *(*out)++ = 'B';
                        *outb -= 8;
                        break;