musl: update to 1.2.6

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>
This commit is contained in:
Hannu Nyman
2026-05-21 16:07:31 +03:00
committed by Hauke Mehrtens
parent 6d9b4a4c41
commit ab06327b13
6 changed files with 107 additions and 69 deletions
+2 -2
View 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)
@@ -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);
@@ -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';
@@ -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");
@@ -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);
+}
@@ -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;