Skip to contentSkip to conversation

package/libcurl: fix build on LoongArch with musl

PATCH New Yegor Yefremov 3 participants 3 messages Nov 9 – Nov 11

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 package/libcurl: fix build on LoongArch with musl

Since libcurl 8.21.0, building the curl tool for loongarch64 with a musl toolchain fails with:

ld: read-only segment has dynamic relocations
collect2: error: ld returned 1 exit status

On musl, none of the secure memory zeroing functions curl knows about are detected, so curlx_memzero_low() falls back to calling memset() through a 'const volatile' function pointer. In non-PIC code, GCC places this pointer in .rodata, and on LoongArch the linker emits a dynamic R_LARCH_64 relocation against memset() there, i.e. a text relocation. musl's dynamic loader does not support DT_TEXTREL, so the Buildroot toolchain wrapper links with -z text, which turns it into an error. Other architectures resolve the address to a PLT entry at link time and are not affected.

Add a patch, submitted upstream, that drops the 'const' qualifier, so that the pointer is placed in .data.

This issue has been present since commit be2789d08432 ("package/libcurl:
security bump to version 8.21.0"), which brought in the upstream code using the 'const volatile' pointer. It therefore affects 2026.08 and later, and 2026.05.x since 2026.05.1.

Fixes:
https://autobuild.buildroot.org/results/558c08d552920e45628254bdc029518120a35ae1

Fixes be2789d08432da951c0ebfb23b034072601bc8fe ("package/libcurl: security bump to version 8.21.0")
Assisted-by Claude:claude-opus-5-5
---
 ...-relocation-in-curlx_memzero_low-fal.patch | 41 +++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 package/libcurl/0001-curlx-avoid-text-relocation-in-curlx_memzero_low-fal.patch
package/libcurl/0001-curlx-avoid-text-relocation-in-curlx_memzero_low-fal.patch new file +41 -0
new file mode 100644
index 0000000000..4bb1ad83c8
@@ -0,0 +1,41 @@
+From 8c05728ff2dfd5481379280ee7215518a2817725 Mon Sep 17 00:00:00 2001
+From: Yegor Yefremov <[email protected]>
+Date: Mon, 9 Nov 2026 13:42:51 +0100
+Subject: [PATCH] curlx: avoid text relocation in curlx_memzero_low() fallback
+
+The const volatile function pointer is placed in .rodata in non-PIC
+code. On LoongArch this needs a dynamic relocation for memset(), so
+linking the curl tool against musl with -z text fails:
+
+  ld: read-only segment has dynamic relocations
+
+Drop the const. volatile is enough to keep the call.
+
+Follow-up to 066478f6346a2d987a9ecc3bd3bf45764d69c1c4 #21598
+
+Upstream: https://github.com/curl/curl/pull/23844
+Assisted-by: Claude:claude-opus-5-5
+Signed-off-by: Yegor Yefremov <[email protected]>
+---
+ lib/curlx/strdup.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/lib/curlx/strdup.c b/lib/curlx/strdup.c
+index ebc58c236..6f6d7c673 100644
+--- a/lib/curlx/strdup.c
++++ b/lib/curlx/strdup.c
+@@ -96,8 +96,9 @@ void *curlx_memdup0(const char *src, size_t length)
+ }
+ 
+ #ifdef USE_CURLX_MEMZERO
+-static void *(* const volatile p_curlx_memset)(void *buf, int val,
+-                                               size_t size) = memset;
++/* not const, to keep it out of .rodata and avoid a text relocation */
++static void *(* volatile p_curlx_memset)(void *buf, int val,
++                                         size_t size) = memset;
+ 
+ /* Local fallback in case there is no system function to securely zero a memory
+    buffer. */
+-- 
+2.34.1
+
Signature · 6 lines
2.34.1

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#1 lore raw

PATCH v2 1/1 package/libcurl: fix build on LoongArch with musl

Since libcurl 8.21.0, building the curl tool for loongarch64 with a musl toolchain fails with:

ld: read-only segment has dynamic relocations
collect2: error: ld returned 1 exit status

On musl, none of the secure memory zeroing functions curl knows about are detected, so curlx_memzero_low() falls back to calling memset() through a 'const volatile' function pointer. In non-PIC code, GCC places this pointer in .rodata, and on LoongArch the linker emits a dynamic R_LARCH_64 relocation against memset() there, i.e. a text relocation. musl's dynamic loader does not support DT_TEXTREL, so the Buildroot toolchain wrapper links with -z text, which turns it into an error. Other architectures resolve the address to a PLT entry at link time and are not affected.

Backport the upstream fix, which detects explicit_bzero() at configure time. musl provides it since 1.1.20, so the memset() fallback is no longer used. As the patch touches configure.ac and m4/, autoreconf the package.

This issue has been present since commit be2789d08432 ("package/libcurl:
security bump to version 8.21.0"), which brought in the upstream code using the 'const volatile' pointer. It therefore affects 2026.08 and later, and 2026.05.x since 2026.05.1.

Fixes:
https://autobuild.buildroot.org/results/558c08d552920e45628254bdc029518120a35ae1

Fixes be2789d08432da951c0ebfb23b034072601bc8fe ("package/libcurl: security bump to version 8.21.0")
Assisted-by Claude:claude-opus-5-5

---
Changes v1 -> v2:
- replace the local patch with the upstream fix, which detects explicit_bzero() at configure time instead (suggested by Viktor Szakats in the upstream review)
- autoreconf the package, as the patch touches configure.ac and m4/

 ...o-detect-explicit_bzero-in-configure.patch | 235 ++++++++++++++++++
 package/libcurl/libcurl.mk                    |   2 +
 2 files changed, 237 insertions(+)
 create mode 100644 package/libcurl/0001-build-auto-detect-explicit_bzero-in-configure.patch
package/libcurl/0001-build-auto-detect-explicit_bzero-in-configure.patch new file +235 -0
new file mode 100644
index 0000000000..475c55b6e6
@@ -0,0 +1,235 @@
+From e55a7ff40ebe1974735205135dfb3bf9e3db269b Mon Sep 17 00:00:00 2001
+From: Viktor Szakats <[email protected]>
+Date: Mon, 9 Nov 2026 19:24:43 +0100
+Subject: [PATCH] build: auto-detect `explicit_bzero()` in configure
+
+Replacing compile-time auto-detection. Mainly due to MUSL, which offers
+no means to detect its presence or version via the preprocessor,
+requiring costly configure-time detection.
+
+After this patch `explicit_bzero()` is used with MUSL 1.1.20+
+(2018-09-04), and potentially more platforms which wasn't expliticly
+opted-in previously.
+
+This in turn avoids this link-time error, and suspect toolchain bug,
+when falling back to the local memzero, combined with LoongArch ld
+2.45.1 + gcc 16.2.0:
+```
+gcc/loongarch64-buildroot-linux-musl/16.2.0/.../loongarch64-buildroot-linux-musl/bin/ld: read-only segment has dynamic relocations
+```
+Ref: https://autobuild.buildroot.org/results/558c08d552920e45628254bdc029518120a35ae1
+
+Reported-by: Yegor Yefremov
+Fixes #23844
+Follow-up to 982e2e8c75f157940ef100f59dea94c4eb607058 #21989
+Follow-up to 066478f6346a2d987a9ecc3bd3bf45764d69c1c4 #21598
+
+Closes #23866
+
+Upstream: https://github.com/curl/curl/commit/e55a7ff40ebe1974735205135dfb3bf9e3db269b
+Signed-off-by: Yegor Yefremov <[email protected]>
+---
+ CMake/unix-cache.cmake     |  9 +++++
+ CMakeLists.txt             |  5 ++-
+ configure.ac               |  6 +++-
+ lib/cf-socket.c            |  4 +++
+ lib/curl_config-cmake.h.in |  3 ++
+ lib/curl_setup.h           | 15 +++------
+ m4/curl-functions.m4       | 67 ++++++++++++++++++++++++++++++++++++++
+ 7 files changed, 96 insertions(+), 13 deletions(-)
+
+diff --git a/CMake/unix-cache.cmake b/CMake/unix-cache.cmake
+index b6b544442046..468bd3e4dc01 100644
+--- a/CMake/unix-cache.cmake
++++ b/CMake/unix-cache.cmake
+@@ -69,6 +69,15 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
+        CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
+   set(HAVE_EVENTFD 1)
+ endif()
++if(CYGWIN OR
++   CMAKE_SYSTEM_NAME STREQUAL "Linux" OR  # glibc 2.25+, MUSL 1.1.20+
++   CMAKE_SYSTEM_NAME STREQUAL "DragonFlyBSD" OR  # 5.6+
++   CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR  # 11 r272673+
++   CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")  # 5.5+
++  set(HAVE_EXPLICIT_BZERO 1)
++elseif(APPLE)
++  set(HAVE_EXPLICIT_BZERO 0)
++endif()
+ if(ANDROID AND ANDROID_PLATFORM_LEVEL GREATER_EQUAL 34)
+   set(HAVE_MEMSET_EXPLICIT 1)
+ endif()
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index a9df7a21bc3c..23f21dd37d47 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -1739,7 +1739,10 @@ if(NOT WIN32)
+ 
+   check_symbol_exists("memset_s" "string.h" HAVE_MEMSET_S)
+   if(NOT HAVE_MEMSET_S)
+-    check_function_exists("memset_explicit" HAVE_MEMSET_EXPLICIT)
++    check_symbol_exists("explicit_bzero" "string.h" HAVE_EXPLICIT_BZERO)
++    if(NOT HAVE_EXPLICIT_BZERO)
++      check_function_exists("memset_explicit" HAVE_MEMSET_EXPLICIT)
++    endif()
+   endif()
+ endif()
+ 
+diff --git a/configure.ac b/configure.ac
+index d6a542311116..ebefb158a27f 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -4242,7 +4242,11 @@ if test "$curl_cv_native_windows" != "yes"; then
+ 
+   CURL_CHECK_FUNC_MEMSET_S
+   if test "$curl_cv_func_memset_s" = "no"; then
+-    AC_CHECK_FUNCS([memset_explicit])
++    dnl Use complex detection to avoid misdetection on old Linux.
++    CURL_CHECK_FUNC_EXPLICIT_BZERO
++    if test "$curl_cv_func_explicit_bzero" = "no"; then
++      AC_CHECK_FUNCS([memset_explicit])
++    fi
+   fi
+ fi
+ 
+diff --git a/lib/cf-socket.c b/lib/cf-socket.c
+index 97b5fa89d219..9073274ba0c2 100644
+--- a/lib/cf-socket.c
++++ b/lib/cf-socket.c
+@@ -59,6 +59,10 @@
+ #include <inet.h>
+ #endif
+ 
++#ifdef __DragonFly__
++#include <sys/param.h>  /* for __DragonFly_version */
++#endif
++
+ #include "urldata.h"
+ #include "curl_trc.h"
+ #include "if2ip.h"
+diff --git a/lib/curl_config-cmake.h.in b/lib/curl_config-cmake.h.in
+index 45c5de970dce..dbbbd04fdfb8 100644
+--- a/lib/curl_config-cmake.h.in
++++ b/lib/curl_config-cmake.h.in
+@@ -234,6 +234,9 @@
+ /* Define to 1 if you have the `opendir' function. */
+ #cmakedefine HAVE_OPENDIR 1
+ 
++/* Define to 1 if you have the explicit_bzero function. */
++#cmakedefine HAVE_EXPLICIT_BZERO 1
++
+ /* Define to 1 if you have the memset_explicit (C23) function. */
+ #cmakedefine HAVE_MEMSET_EXPLICIT 1
+ 
+diff --git a/lib/curl_setup.h b/lib/curl_setup.h
+index d4d0f25bfe24..504b21210352 100644
+--- a/lib/curl_setup.h
++++ b/lib/curl_setup.h
+@@ -1638,9 +1638,8 @@ typedef struct sockaddr_un {
+ #endif
+ 
+ /* For FreeBSD it is included from curl/curl.h */
+-#if defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__)
+-#include <sys/param.h>  /* for __DragonFly_version, OpenBSD,
+-                           __NetBSD_Version__ */
++#ifdef __NetBSD__
++#include <sys/param.h>  /* for __NetBSD_Version__ */
+ #endif
+ 
+ /* NetBSD before 6.1 did not set SS_NBIO for SOCK_NONBLOCK. */
+@@ -1660,16 +1659,10 @@ typedef struct sockaddr_un {
+ #endif
+ #elif defined(HAVE_MEMSET_S)
+ #define curlx_memzero_low(buf, size)  (void)memset_s(buf, size, 0, size)
++#elif defined(HAVE_EXPLICIT_BZERO)
++#define curlx_memzero_low(buf, size)  explicit_bzero(buf, size)
+ #elif defined(HAVE_MEMSET_EXPLICIT)
+ #define curlx_memzero_low(buf, size)  (void)memset_explicit(buf, 0, size)
+-#elif defined(__CYGWIN__) || \
+-  (defined(__NEWLIB__) && !defined(__CLIB2__)) || \
+-  (defined(__GLIBC__) && \
+-    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))) || \
+-  (defined(__DragonFly__) && __DragonFly_version >= 500600 /* 5.6+ */) || \
+-  (defined(__FreeBSD__) && __FreeBSD_version >= 1100037 /* 11.0+ */) || \
+-  (defined(__OpenBSD__) && OpenBSD >= 201405 /* 5.5+ */)
+-#define curlx_memzero_low(buf, size)  explicit_bzero(buf, size)
+ #elif defined(__NetBSD__) && __NetBSD_Version__ >= 702000000 /* 7.2+ */
+ #define curlx_memzero_low(buf, size)  (void)explicit_memset(buf, 0, size)
+ #endif
+diff --git a/m4/curl-functions.m4 b/m4/curl-functions.m4
+index 64046a834afb..2edbdf0fb5f4 100644
+--- a/m4/curl-functions.m4
++++ b/m4/curl-functions.m4
+@@ -3956,6 +3956,73 @@ AC_DEFUN([CURL_CHECK_FUNC_MEMSET_S], [
+   fi
+ ])
+ 
++dnl CURL_CHECK_FUNC_EXPLICIT_BZERO
++dnl -------------------------------------------------
++dnl Verify if explicit_bzero is available.
++
++AC_DEFUN([CURL_CHECK_FUNC_EXPLICIT_BZERO], [
++
++  tst_links_explicit_bzero="unknown"
++  tst_proto_explicit_bzero="unknown"
++  tst_compile_explicit_bzero="unknown"
++
++  AC_MSG_CHECKING([if explicit_bzero can be linked])
++  AC_LINK_IFELSE([
++    AC_LANG_FUNC_LINK_TRY([explicit_bzero])
++  ],[
++    AC_MSG_RESULT([yes])
++    tst_links_explicit_bzero="yes"
++  ],[
++    AC_MSG_RESULT([no])
++    tst_links_explicit_bzero="no"
++  ])
++
++  if test "$tst_links_explicit_bzero" = "yes"; then
++    AC_MSG_CHECKING([if explicit_bzero is prototyped])
++    AC_EGREP_CPP([explicit_bzero],[
++      $curl_includes_string
++    ],[
++      AC_MSG_RESULT([yes])
++      tst_proto_explicit_bzero="yes"
++    ],[
++      AC_MSG_RESULT([no])
++      tst_proto_explicit_bzero="no"
++    ])
++  fi
++
++  if test "$tst_proto_explicit_bzero" = "yes"; then
++    AC_MSG_CHECKING([if explicit_bzero is compilable])
++    AC_COMPILE_IFELSE([
++      AC_LANG_PROGRAM([[
++        $curl_includes_string
++      ]],[[
++        char buf[2];
++        explicit_bzero(buf, sizeof(buf));
++      ]])
++    ],[
++      AC_MSG_RESULT([yes])
++      tst_compile_explicit_bzero="yes"
++    ],[
++      AC_MSG_RESULT([no])
++      tst_compile_explicit_bzero="no"
++    ])
++  fi
++
++  AC_MSG_CHECKING([if explicit_bzero might be used])
++  if test "$tst_links_explicit_bzero" = "yes" &&
++     test "$tst_proto_explicit_bzero" = "yes" &&
++     test "$tst_compile_explicit_bzero" = "yes" &&
++     test "x$curl_disallow_explicit_bzero" != "xyes"; then
++    AC_MSG_RESULT([yes])
++    AC_DEFINE_UNQUOTED(HAVE_EXPLICIT_BZERO, 1,
++      [Define to 1 if you have the explicit_bzero function.])
++    curl_cv_func_explicit_bzero="yes"
++  else
++    AC_MSG_RESULT([no])
++    curl_cv_func_explicit_bzero="no"
++  fi
++])
++
+ dnl CURL_RUN_IFELSE
+ dnl -------------------------------------------------
+ dnl Wrapper macro to use instead of AC_RUN_IFELSE. It
package/libcurl/libcurl.mk +2 -0
index 00f718fbec..a8cbe65385 100644
@@ -14,6 +14,8 @@ LIBCURL_LICENSE = curl
 LIBCURL_LICENSE_FILES = COPYING
 LIBCURL_CPE_ID_VENDOR = haxx
 LIBCURL_INSTALL_STAGING = YES
+# 0001-build-auto-detect-explicit_bzero-in-configure.patch
+LIBCURL_AUTORECONF = YES
 
 # Likewise, there is no compiler on the target, so libcurl-option (to
 # generate C code) isn't very useful
Signature · 6 lines
2.34.1

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#2 lore raw
Quoted 34 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"Yegor" == Yegor Yefremov via buildroot <[email protected]> writes:

Since libcurl 8.21.0, building the curl tool for loongarch64 with a musl toolchain fails with:

ld: read-only segment has dynamic relocations
collect2: error: ld returned 1 exit status

On musl, none of the secure memory zeroing functions curl knows about are detected, so curlx_memzero_low() falls back to calling memset() through a 'const volatile' function pointer. In non-PIC code, GCC places this pointer in .rodata, and on LoongArch the linker emits a dynamic R_LARCH_64 relocation against memset() there, i.e. a text relocation. musl's dynamic loader does not support DT_TEXTREL, so the Buildroot toolchain wrapper links with -z text, which turns it into an error. Other architectures resolve the address to a PLT entry at link time and are not affected.

Backport the upstream fix, which detects explicit_bzero() at configure time. musl provides it since 1.1.20, so the memset() fallback is no longer used. As the patch touches configure.ac and m4/, autoreconf the package.

This issue has been present since commit be2789d08432 ("package/libcurl:
security bump to version 8.21.0"), which brought in the upstream code using the 'const volatile' pointer. It therefore affects 2026.08 and later, and 2026.05.x since 2026.05.1.

Fixes:
https://autobuild.buildroot.org/results/558c08d552920e45628254bdc029518120a35ae1

Fixes be2789d08432da951c0ebfb23b034072601bc8fe ("package/libcurl: security bump to version 8.21.0")
Assisted-by Claude:claude-opus-5-5
Quoted 6 lines

---
Changes v1 -> v2:
- replace the local patch with the upstream fix, which detects explicit_bzero() at configure time instead (suggested by Viktor Szakats in the upstream review)
- autoreconf the package, as the patch touches configure.ac and m4/

Committed, thanks.

Signature · 5 lines
Bye, Peter Korsgaard
_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot