From 4baed9bba0de8156d41d827ed100169d468691c8 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Wed, 20 May 2026 19:27:19 +0200 Subject: [PATCH 1/3] fix(docker): remove libtcnative-1 at runtime when FIPS mode is detected SSLEngine=off alone is insufficient to prevent the OpenSSL 3.x crash on FIPS-enabled hosts. libtcnative-1 still loads libcrypto.so.3 and calls OpenSSL for non-SSL operations (e.g. random number generation), which triggers EVP_MD_get0_provider+0x4 SIGSEGV when the FIPS provider (fips.so) is missing from Ubuntu 24.04. The fix removes libtcnative-1.so at container startup when FIPS mode is detected, before Tomcat starts. This prevents the native library from loading OpenSSL entirely. Tomcat falls back to pure Java NIO/JSSE. libtcnative-1 remains installed by default for non-FIPS environments. Fixes #34212 Related: #34067, PR #34213 --- .../original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh b/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh index 9056773f8d91..94268c9909b8 100755 --- a/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh +++ b/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh @@ -7,6 +7,10 @@ # # The Tomcat Native APR library (libtcnative-1) version 1.2.35 is incompatible # with OpenSSL 3.x when running in FIPS mode, causing segmentation faults. +# Setting SSLEngine=off alone is insufficient: libtcnative-1 still loads +# libcrypto.so.3 and calls OpenSSL for non-SSL operations (e.g. random number +# generation), which triggers the same FIPS provider crash. The library must +# be removed at runtime before Tomcat starts to fully prevent the crash. # # Configuration Options: # ---------------------- @@ -53,6 +57,8 @@ elif [[ "${FIPS_ENABLED}" == "true" ]]; then echo "[FIPS Detection] Automatically disabling APR SSL Engine due to FIPS mode" echo "[FIPS Detection] This prevents JVM crashes with OpenSSL 3.x in FIPS environments" echo "[FIPS Detection] Tomcat will use Java JSSE for SSL/TLS instead" + echo "[FIPS Detection] Removing libtcnative-1 to prevent OpenSSL initialization in FIPS mode" + rm -f /usr/lib/x86_64-linux-gnu/libtcnative-1.so.0* 2>/dev/null || true export CMS_SSL_ENGINE="off" else # Default: Keep APR SSL Engine enabled for performance benefits From dd371a9cc5fcfaa6691823bef1d632a19d9544a7 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Thu, 21 May 2026 17:05:30 +0200 Subject: [PATCH 2/3] fix(docker): remove AprLifecycleListener from server.xml in FIPS mode The previous approach (rm -f libtcnative-1.so) was silently a no-op: the container runs as UID 65001 (non-root) and cannot unlink root-owned files under /usr/lib. The || true masked the EACCES, making the fix invisible in logs while the JVM continued to crash. Instead, remove the AprLifecycleListener entry from server.xml at container startup when FIPS mode is detected. server.xml lives under /srv/dotserver/tomcat/conf/ which is owned by the dotcms user, so no root privileges are needed. Without the AprLifecycleListener, Tomcat never calls Library.initialize() and libtcnative-1 is never loaded, preventing libcrypto.so.3 from being touched entirely. Also adds a post-condition grep to fail loudly if the sed did not remove the listener, so failures are visible in container logs. Fixes #34212 Related: #34067, PR #34213 --- .../srv/15-detect-fips-and-set-ssl-engine.sh | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh b/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh index 94268c9909b8..77bea5f083f1 100755 --- a/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh +++ b/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh @@ -9,8 +9,12 @@ # with OpenSSL 3.x when running in FIPS mode, causing segmentation faults. # Setting SSLEngine=off alone is insufficient: libtcnative-1 still loads # libcrypto.so.3 and calls OpenSSL for non-SSL operations (e.g. random number -# generation), which triggers the same FIPS provider crash. The library must -# be removed at runtime before Tomcat starts to fully prevent the crash. +# generation), which triggers the same FIPS provider crash. +# +# When FIPS mode is detected, the AprLifecycleListener is removed from +# server.xml at runtime (before Tomcat starts) so that libtcnative-1 is never +# loaded by Tomcat at all. server.xml lives under /srv/dotserver/tomcat/conf/ +# which is owned by the dotcms user, so no root privileges are needed. # # Configuration Options: # ---------------------- @@ -57,8 +61,21 @@ elif [[ "${FIPS_ENABLED}" == "true" ]]; then echo "[FIPS Detection] Automatically disabling APR SSL Engine due to FIPS mode" echo "[FIPS Detection] This prevents JVM crashes with OpenSSL 3.x in FIPS environments" echo "[FIPS Detection] Tomcat will use Java JSSE for SSL/TLS instead" - echo "[FIPS Detection] Removing libtcnative-1 to prevent OpenSSL initialization in FIPS mode" - rm -f /usr/lib/x86_64-linux-gnu/libtcnative-1.so.0* 2>/dev/null || true + # SSLEngine=off alone does not prevent libtcnative-1 from loading libcrypto.so.3 + # and calling OpenSSL for non-SSL operations. Remove the AprLifecycleListener + # from server.xml so Tomcat never loads the native library at all. + # server.xml is under /srv (owned by dotcms user) so no root access is needed. + TOMCAT_SERVER_XML="${TOMCAT_HOME:-/srv/dotserver/tomcat}/conf/server.xml" + if [[ -f "${TOMCAT_SERVER_XML}" ]]; then + sed -i '/AprLifecycleListener/d' "${TOMCAT_SERVER_XML}" + if ! grep -q 'AprLifecycleListener' "${TOMCAT_SERVER_XML}"; then + echo "[FIPS Detection] AprLifecycleListener removed from server.xml — libtcnative-1 will not be loaded" + else + echo "[FIPS Detection] WARNING: Failed to remove AprLifecycleListener from ${TOMCAT_SERVER_XML} — JVM may still crash" + fi + else + echo "[FIPS Detection] WARNING: server.xml not found at ${TOMCAT_SERVER_XML} — libtcnative-1 may still load" + fi export CMS_SSL_ENGINE="off" else # Default: Keep APR SSL Engine enabled for performance benefits From 772fcb84d626af27a7a37965483518511e7c48fa Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Tue, 9 Jun 2026 15:09:34 +0200 Subject: [PATCH 3/3] fix(docker): relocate libtcnative-1 to /srv/native-libs for FIPS removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The server.xml AprLifecycleListener approach was insufficient because setenv.sh sets java.library.path=/usr/lib/-linux-gnu/ and Tomcat auto-detects and loads libtcnative-1 from there regardless of server.xml. Root cause: On a FIPS-enabled kernel, OpenSSL 3.x requires fips.so before allowing any crypto operation. Ubuntu 24.04 does not ship fips.so, so the first OpenSSL call (EVP_MD_get0_provider) segfaults at the native level. Fix: - Dockerfile: move libtcnative-1.so.0* to /srv/native-libs/ (dotcms-owned) and leave symlinks in /usr/lib/-linux-gnu/. This is done as root during the image build — no runtime root access required. - FIPS script: when FIPS detected, rm /srv/native-libs/libtcnative-1.so.0* (writable by dotcms user). The symlinks in /usr/lib become dangling so dlopen() cannot load the library regardless of java.library.path. Non-FIPS containers are unaffected: symlinks resolve normally, the library loads and provides its usual performance benefits. Fixes #34212 Related: #34067, PR #34213 --- dotCMS/src/main/docker/original/Dockerfile | 13 +++++ .../srv/15-detect-fips-and-set-ssl-engine.sh | 47 +++++++++---------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/dotCMS/src/main/docker/original/Dockerfile b/dotCMS/src/main/docker/original/Dockerfile index 764caa38c175..c3042474f590 100644 --- a/dotCMS/src/main/docker/original/Dockerfile +++ b/dotCMS/src/main/docker/original/Dockerfile @@ -92,6 +92,19 @@ COPY --from=container-base /java /java COPY --from=container-base /srv /srv COPY --from=container-base /data /data +# Move libtcnative-1 to /srv/native-libs (owned by dotcms user) and leave symlinks +# in /usr/lib. This lets the FIPS detection script remove the library at runtime +# without root access — making the symlinks dangling so dlopen() fails to load it. +RUN set -e; \ + ARCH=$(uname -m); \ + mkdir -p /srv/native-libs; \ + for f in /usr/lib/${ARCH}-linux-gnu/libtcnative-1.so.0*; do \ + [ -e "$f" ] || continue; \ + mv "$f" /srv/native-libs/; \ + ln -sf "/srv/native-libs/$(basename "$f")" "$f"; \ + done; \ + chown -R dotcms:dotcms /srv/native-libs + USER $USER_UID:$USER_GID ENV JAVA_HOME="/java" ENV PATH=$PATH:/java/bin diff --git a/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh b/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh index 77bea5f083f1..c11c145b9494 100755 --- a/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh +++ b/dotCMS/src/main/docker/original/ROOT/srv/15-detect-fips-and-set-ssl-engine.sh @@ -2,25 +2,27 @@ # FIPS Mode Detection and APR SSL Engine Configuration # ===================================================== -# This script automatically detects FIPS-enabled environments and disables the -# Tomcat Native APR SSL Engine to prevent JVM crashes with OpenSSL 3.x. +# This script automatically detects FIPS-enabled environments and prevents +# libtcnative-1 from loading to avoid JVM crashes with OpenSSL 3.x in FIPS mode. # -# The Tomcat Native APR library (libtcnative-1) version 1.2.35 is incompatible -# with OpenSSL 3.x when running in FIPS mode, causing segmentation faults. -# Setting SSLEngine=off alone is insufficient: libtcnative-1 still loads -# libcrypto.so.3 and calls OpenSSL for non-SSL operations (e.g. random number -# generation), which triggers the same FIPS provider crash. +# Root cause: libtcnative-1 links against libcrypto.so.3. On a FIPS-enabled kernel, +# OpenSSL 3.x requires the FIPS provider (fips.so) to be present before allowing +# any crypto operation. Ubuntu 24.04 does not ship fips.so, so the first OpenSSL +# crypto call (e.g. EVP_MD_get0_provider for random number generation) segfaults. +# This happens regardless of SSLEngine or AprLifecycleListener configuration because +# setenv.sh sets java.library.path to /usr/lib/-linux-gnu/ and Tomcat auto- +# detects and loads libtcnative-1 from there even without an AprLifecycleListener. # -# When FIPS mode is detected, the AprLifecycleListener is removed from -# server.xml at runtime (before Tomcat starts) so that libtcnative-1 is never -# loaded by Tomcat at all. server.xml lives under /srv/dotserver/tomcat/conf/ -# which is owned by the dotcms user, so no root privileges are needed. +# Fix: The Dockerfile moves libtcnative-1.so.0* to /srv/native-libs/ (owned by the +# dotcms user) and leaves symlinks in /usr/lib. When FIPS is detected, this script +# removes the files in /srv/native-libs/, making the symlinks dangling. dlopen() then +# fails to load the library regardless of java.library.path or server.xml config. # # Configuration Options: # ---------------------- # 1. Automatic FIPS Detection (default behavior): # - The script checks /proc/sys/crypto/fips_enabled -# - If FIPS is enabled, CMS_SSL_ENGINE is automatically set to 'off' +# - If FIPS is enabled, libtcnative-1 is removed and CMS_SSL_ENGINE is set to 'off' # # 2. Manual Override with CMS_DISABLE_APR_SSL: # - Set CMS_DISABLE_APR_SSL=true to disable APR SSL Engine @@ -61,20 +63,15 @@ elif [[ "${FIPS_ENABLED}" == "true" ]]; then echo "[FIPS Detection] Automatically disabling APR SSL Engine due to FIPS mode" echo "[FIPS Detection] This prevents JVM crashes with OpenSSL 3.x in FIPS environments" echo "[FIPS Detection] Tomcat will use Java JSSE for SSL/TLS instead" - # SSLEngine=off alone does not prevent libtcnative-1 from loading libcrypto.so.3 - # and calling OpenSSL for non-SSL operations. Remove the AprLifecycleListener - # from server.xml so Tomcat never loads the native library at all. - # server.xml is under /srv (owned by dotcms user) so no root access is needed. - TOMCAT_SERVER_XML="${TOMCAT_HOME:-/srv/dotserver/tomcat}/conf/server.xml" - if [[ -f "${TOMCAT_SERVER_XML}" ]]; then - sed -i '/AprLifecycleListener/d' "${TOMCAT_SERVER_XML}" - if ! grep -q 'AprLifecycleListener' "${TOMCAT_SERVER_XML}"; then - echo "[FIPS Detection] AprLifecycleListener removed from server.xml — libtcnative-1 will not be loaded" - else - echo "[FIPS Detection] WARNING: Failed to remove AprLifecycleListener from ${TOMCAT_SERVER_XML} — JVM may still crash" - fi + # Remove libtcnative-1 from /srv/native-libs (writable by dotcms user). + # The Dockerfile placed the library there and left symlinks in /usr/lib. + # Removing the target makes the symlinks dangling so dlopen() cannot load + # the library regardless of java.library.path or server.xml configuration. + if rm -f /srv/native-libs/libtcnative-1.so.0* && \ + ! ls /srv/native-libs/libtcnative-1.so.0* >/dev/null 2>&1; then + echo "[FIPS Detection] libtcnative-1 removed from /srv/native-libs — library cannot be loaded" else - echo "[FIPS Detection] WARNING: server.xml not found at ${TOMCAT_SERVER_XML} — libtcnative-1 may still load" + echo "[FIPS Detection] WARNING: Failed to remove libtcnative-1 from /srv/native-libs — JVM may still crash" fi export CMS_SSL_ENGINE="off" else