From 676689b890f3ba691c5b00495b5f15193ee9a466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Tue, 30 Jun 2026 23:05:46 +0100 Subject: [PATCH 1/2] make libunwind built against musl use _dl_find_object --- appsec/tests/integration/gradle/images.gradle | 1 + .../src/docker/nginx-fpm-musl/Dockerfile | 21 ++++-- .../nginx-fpm-musl/llvm-runtimes/APKBUILD | 64 +++++++++++++++++++ ...lvm-libunwind-dl-find-object-runtime.patch | 33 ++++++++++ 4 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 appsec/tests/integration/src/docker/nginx-fpm-musl/llvm-runtimes/APKBUILD create mode 100644 appsec/tests/integration/src/docker/nginx-fpm-musl/llvm-runtimes/llvm-libunwind-dl-find-object-runtime.patch diff --git a/appsec/tests/integration/gradle/images.gradle b/appsec/tests/integration/gradle/images.gradle index f285ea546c1..ef786a53f73 100644 --- a/appsec/tests/integration/gradle/images.gradle +++ b/appsec/tests/integration/gradle/images.gradle @@ -212,6 +212,7 @@ tasks.register('buildNginxFpm-8.5-release-musl', Exec) { description = "Build the musl-nginx image for Alpine testing" inputs.file file('src/docker/nginx-fpm-musl/Dockerfile') inputs.file file('src/docker/nginx-fpm-musl/nginx.conf') + inputs.dir 'src/docker/nginx-fpm-musl/llvm-runtimes' outputs.upToDateWhen imageUpToDate(inputs, image) commandLine(*dockerBuildCommand, *dockerMirrorArgs, diff --git a/appsec/tests/integration/src/docker/nginx-fpm-musl/Dockerfile b/appsec/tests/integration/src/docker/nginx-fpm-musl/Dockerfile index b82083c3196..b49bf9f26d7 100644 --- a/appsec/tests/integration/src/docker/nginx-fpm-musl/Dockerfile +++ b/appsec/tests/integration/src/docker/nginx-fpm-musl/Dockerfile @@ -3,10 +3,10 @@ FROM php:8.5-fpm-alpine # doubles as php/toolchain image for musl RUN apk add --no-cache \ - autoconf automake bash bison clang clang-dev cmake curl curl-dev \ - g++ gcc gdb git libc-dev linux-headers llvm-libunwind-static make \ - musl-dev nginx oniguruma-dev openssl-dev patchelf pkgconf re2c libtool \ - libxml2-dev libzip-dev xz-static zlib-dev \ + abuild autoconf automake bash bison clang clang-dev cmake curl curl-dev \ + build-base g++ gcc gdb git libc-dev linux-headers llvm22-dev llvm22-static make \ + musl-dev nginx oniguruma-dev openssl-dev patch patchelf pkgconf re2c libtool \ + libxml2-dev libzip-dev python3 samurai xz xz-static zlib-dev \ vim @@ -24,6 +24,19 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ rustup toolchain install nightly-$(uname -m)-unknown-linux-musl && \ rustup component add rust-src --toolchain nightly-$(uname -m)-unknown-linux-musl +COPY llvm-runtimes /tmp/llvm-runtimes +RUN RUST_TARGET="$(uname -m)-unknown-linux-musl" && \ + RUST_TOOLCHAIN="/usr/local/rustup/toolchains/nightly-${RUST_TARGET}" && \ + apk update && \ + cd /tmp/llvm-runtimes && \ + abuild-keygen -an && \ + cp /root/.abuild/*.rsa.pub /etc/apk/keys/ && \ + abuild -F -r && \ + package="$(find /root/packages -name 'llvm-libunwind-static-patched-*.apk' -print -quit)" && \ + apk add --allow-untrusted "$package" && \ + cp /usr/lib/libunwind.a "${RUST_TOOLCHAIN}/lib/rustlib/${RUST_TARGET}/lib/self-contained/libunwind.a" && \ + rm -rf /tmp/llvm-runtimes /root/packages /var/cache/distfiles/* + RUN mkdir -p /run/nginx && \ mkdir -p /var/www/public && \ chown -R linux_user:linux_user /var/www && \ diff --git a/appsec/tests/integration/src/docker/nginx-fpm-musl/llvm-runtimes/APKBUILD b/appsec/tests/integration/src/docker/nginx-fpm-musl/llvm-runtimes/APKBUILD new file mode 100644 index 00000000000..7e3bbc8f49c --- /dev/null +++ b/appsec/tests/integration/src/docker/nginx-fpm-musl/llvm-runtimes/APKBUILD @@ -0,0 +1,64 @@ +# Contributor: Eric Molitor +# Contributor: Jakub Jirutka +# Contributor: Rasmus Thomsen +# Maintainer: Natanael Copa +pkgname=llvm-libunwind-static-patched +pkgver=22.1.3 +_pkgver=${pkgver/_/-} +_llvmver=${pkgver%%.*} +pkgrel=0 +pkgdesc="LLVM libunwind static library with runtime _dl_find_object probing" +url="https://llvm.org/" +arch="x86_64 aarch64" +license="Apache-2.0" +makedepends=" + abuild>=3.15.0-r5 + clang + cmake + linux-headers + llvm$_llvmver-dev + llvm$_llvmver-static + python3 + samurai + " +source="https://github.com/llvm/llvm-project/releases/download/llvmorg-$_pkgver/llvm-project-$_pkgver.src.tar.xz + llvm-libunwind-dl-find-object-runtime.patch + " +builddir="$srcdir/llvm-project-$_pkgver.src" +options="!check" + +prepare() { + default_prepare +} + +build() { + CC=clang \ + CXX=clang++ \ + CFLAGS="$CFLAGS -DNDEBUG -DSANITIZER_CAN_USE_PREINIT_ARRAY=0" \ + CXXFLAGS="$CXXFLAGS -DNDEBUG -DSANITIZER_CAN_USE_PREINIT_ARRAY=0" \ + cmake -B build -G Ninja -Wno-dev -S runtimes \ + -DLLVM_ENABLE_RUNTIMES="libunwind" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DLIBCXX_HAS_MUSL_LIBC=ON \ + -DLIBUNWIND_HAS_NODEFAULTLIBS_FLAG=OFF \ + -DLIBUNWIND_ENABLE_SHARED=OFF \ + -DLIBUNWIND_ENABLE_STATIC=ON \ + -DLIBUNWIND_INSTALL_HEADERS=OFF \ + -DLIBUNWIND_INSTALL_SHARED_LIBRARY=OFF \ + -DLIBUNWIND_INSTALL_STATIC_LIBRARY=ON \ + -DCMAKE_VERBOSE_MAKEFILE=ON + cmake --build build --target unwind_static +} + +package() { + DESTDIR="$pkgdir" cmake --install build + + find "$pkgdir" -type f ! -path "$pkgdir/usr/lib/libunwind.a" -delete + find "$pkgdir" -type d -empty -delete +} + +sha512sums=" +3557a955d55471671ae2f7b9c809affd59a29a6fb1e70a2a5d040dc1c6376246deb0635be8ca36cae09112981760e9afb128c822e5554bd722589fb8dee3f0df llvm-project-22.1.3.src.tar.xz +82fac87a42efd9d4612b03653880ba7d29f6ba05b790d7916dff02cf14c6149c037d81fd0e3303958a9d8052a54e3f094b42fd8e45211d97d91a86aafae1ee7b llvm-libunwind-dl-find-object-runtime.patch +" diff --git a/appsec/tests/integration/src/docker/nginx-fpm-musl/llvm-runtimes/llvm-libunwind-dl-find-object-runtime.patch b/appsec/tests/integration/src/docker/nginx-fpm-musl/llvm-runtimes/llvm-libunwind-dl-find-object-runtime.patch new file mode 100644 index 00000000000..aef913ddd13 --- /dev/null +++ b/appsec/tests/integration/src/docker/nginx-fpm-musl/llvm-runtimes/llvm-libunwind-dl-find-object-runtime.patch @@ -0,0 +1,33 @@ +diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp +--- a/libunwind/src/AddressSpace.hpp ++++ b/libunwind/src/AddressSpace.hpp +@@ -99,6 +99,29 @@ + + #include + ++#if defined(__linux__) && defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) && \ ++ defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) && \ ++ !defined(DLFO_STRUCT_HAS_EH_DBASE) && \ ++ (defined(__x86_64__) || defined(__aarch64__)) ++// glibc 2.35 added _dl_find_object, and LLVM libunwind already probes for it ++// with dlsym at runtime. musl's does not declare the glibc-only ABI, ++// so provide the compatible public layout and keep the runtime fallback to ++// dl_iterate_phdr when _dl_find_object is absent. ++#define DLFO_STRUCT_HAS_EH_DBASE 0 ++#define DLFO_STRUCT_HAS_EH_COUNT 0 ++#define DLFO_EH_SEGMENT_TYPE PT_GNU_EH_FRAME ++struct dl_find_object { ++ unsigned long long int dlfo_flags; ++ void *dlfo_map_start; ++ void *dlfo_map_end; ++ struct link_map *dlfo_link_map; ++ void *dlfo_eh_frame; ++ unsigned long long int __dlfo_reserved[7]; ++}; ++ ++extern "C" int _dl_find_object(void *, struct dl_find_object *); ++#endif ++ + #endif + + namespace libunwind { From f8bc36fc17731e2a9ed09c6fd5560ef92bce5e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Wed, 1 Jul 2026 12:51:44 +0100 Subject: [PATCH 2/2] update pushed nginx-fpm-php-8.5-release-musl image --- .gitlab/generate-package.php | 22 ++++++++++++++++++- .../integration/gradle/tag_mappings.gradle | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.gitlab/generate-package.php b/.gitlab/generate-package.php index bc760c9e2b4..d7f43430416 100644 --- a/.gitlab/generate-package.php +++ b/.gitlab/generate-package.php @@ -72,6 +72,26 @@ ], ]; +$appsec_helper_rust_image_tag = "nginx-fpm-php-8.5-release-musl"; +$appsec_helper_rust_image = appsec_image_from_tag_mapping($appsec_helper_rust_image_tag); + +function appsec_image_from_tag_mapping(string $tag): string +{ + $tag_mappings_file = __DIR__ . "/../appsec/tests/integration/gradle/tag_mappings.gradle"; + $tag_mappings = file_get_contents($tag_mappings_file); + if ($tag_mappings === false) { + throw new RuntimeException("Failed to read $tag_mappings_file"); + } + + if (!preg_match("/['\"]" . preg_quote($tag, "/") . "['\"]\\s*:\\s*['\"]([^'\"]+)['\"]/", $tag_mappings, $matches)) { + throw new RuntimeException("Tag $tag not found in $tag_mappings_file"); + } + + $repo = "registry.ddbuild.io/images/mirror/datadog/dd-appsec-php-ci"; + $image_ref = $matches[1]; + return str_starts_with($image_ref, "sha256:") ? "$repo@$image_ref" : "$repo:$image_ref"; +} + ?> stages: @@ -303,7 +323,7 @@ "compile appsec helper rust": stage: appsec - image: "registry.ddbuild.io/images/mirror/datadog/dd-appsec-php-ci:nginx-fpm-php-8.5-release-musl" + image: "" tags: [ "arch:$ARCH" ] needs: [ "prepare code" ] parallel: diff --git a/appsec/tests/integration/gradle/tag_mappings.gradle b/appsec/tests/integration/gradle/tag_mappings.gradle index ca2bdd442c4..6f36365ed2e 100644 --- a/appsec/tests/integration/gradle/tag_mappings.gradle +++ b/appsec/tests/integration/gradle/tag_mappings.gradle @@ -37,7 +37,7 @@ ext.tag_mappings = [ 'php-7.1-release': 'sha256:d52f126a9101785afe08aeb8af45ebc9393f6007fa9ad20f847fceb4dfe00ef6', 'php-8.4-release': 'sha256:8dd60fd881701c66853820ca7bbbfa5554a91a6007c372444d3203f30d7eae4f', 'apache2-mod-php-8.4-release-zts': 'sha256:d0974677d0f1e12dc59a217a07045afd9649bdc42e680df7d6f7c718ad07c9ed', - 'nginx-fpm-php-8.5-release-musl': 'sha256:0ab409dfc415b0c035414b89efdb34218faa1850e99ad3fcf7b52bd5fc042e0c', + 'nginx-fpm-php-8.5-release-musl': 'sha256:e455d450af85e1b0723ae3cc7e48b0e32b01b6000b619751b2b60597648671e4', 'apache2-mod-php-8.3-release-zts': 'sha256:0ddb8cdc827b9a3dc271a35712346c66ab5a70aa34ae4f2fdf73e3632d0fd1f0', 'apache2-mod-php-8.5-release-zts': 'sha256:33aa76b5ee683d9eb3a1c199b01f3dc998671c0d27ea465ac67943ccda0ad017', 'php-7.2-debug': 'sha256:b809a751f79a4a5b8dedaa57b08c1e9ad407805732f67609a015370867691b79',