This is an automated email from the ASF dual-hosted git repository.

luwei16 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new ad7e343bf20 [fix](cloud) Prevent FDB CloudUT ASAN getentropy crash 
(#67316)
ad7e343bf20 is described below

commit ad7e343bf20a2b3a8c95ad4da3f0fdea57d35ed9
Author: Gavin Chou <[email protected]>
AuthorDate: Mon Aug 31 20:27:18 2026 +0800

    [fix](cloud) Prevent FDB CloudUT ASAN getentropy crash (#67316)
    
    ### What problem does this PR solve?
    
    Issue Number: None
    
    Related PR: #65749
    
    Problem Summary:
    
    Several FDB-related CloudUT ASAN binaries can terminate with a zero-page
    SEGV in `libfdb_c.so`. The existing runner fallback from #65749 prevents
    the overall job from failing when the log contains both ASAN output and
    `libfdb_c.so`, but it does not fix the binary or guarantee that its
    GoogleTest cases actually ran. This PR fixes the underlying
    symbol-resolution failure.
    
    ### Root cause
    
    1. CloudUT ASAN executables are compiled against glibc 2.27, where
    `getentropy` exists, and run on workers with glibc 2.17, where it does
    not.
    2. Compiler-rt links a `getentropy` ASAN interceptor into each
    executable. `libfdb_c` checks `getentropy` as an optional weak symbol
    during FDB network initialization, so the interceptor makes the
    availability check succeed.
    3. The interceptor tries to forward the call to libc, but
    `dlsym(RTLD_NEXT, "getentropy")` resolves to null on glibc 2.17.
    4. The call therefore jumps to address zero, producing
    `AddressSanitizer:DEADLYSIGNAL`, `pc=0`, and a non-zero test-binary
    result.
    
    An A/B diagnostic CloudUT run ([build
    
52882](http://47.243.177.214:8111/buildConfiguration/SelectdbCore_Cloudut/52882))
    observed the full chain:
    
    - compile-time glibc 2.27 and runtime glibc 2.17;
    - native `getentropy` resolved to `__interceptor_trampoline_getentropy`;
    - `RTLD_NEXT getentropy` resolved to null;
    - the native probe reproduced the zero-page SEGV;
    - a probe exporting a strong syscall-backed `getentropy` was called
    during FDB network startup and completed successfully.
    
    Changing `fdb_external_client_directory` and aligning FDB client/server
    versions were also tested independently; neither changed the failure.
    This ruled out FDB client selection and protocol-version compatibility.
    
    ### Why this fix works
    
    - A strong `getentropy` implementation is linked directly into Linux
    ASAN CloudUT executables that link or initialize FDB.
    - `ENABLE_EXPORTS` puts the executable symbol in the dynamic symbol
    table, so `libfdb_c.so` resolves `getentropy` to this implementation
    instead of the unusable ASAN trampoline.
    - The implementation calls `SYS_getrandom` directly, avoiding both libc
    `getentropy` and libc `getrandom` interceptor paths.
    - It preserves the `getentropy(3)` 256-byte limit, retries interrupted
    operations, and falls back to `/dev/urandom` when the running kernel
    reports `ENOSYS`.
    - The compatibility object is limited to Linux ASAN unit tests.
    Production binaries, non-ASAN builds, FDB versions, and FDB
    configuration are unchanged.
    
    The BE glibc-compatibility objects cannot be reused directly here
    because Cloud is a separate CMake project and does not link them. That
    implementation also delegates to `getrandom`, while this workaround
    deliberately uses a direct syscall to avoid another interceptor
    dependency.
    
    ### What is changed?
    
    - Add a Linux ASAN test-only, syscall-backed `getentropy`
    implementation.
    - Export it from the FDB-linked/FDB-initializing CloudUT executables.
    - Keep the existing FDB client version, external-client configuration,
    and test runner unchanged.
    
    ### Testing
    
    - A/B CloudUT build 52882: native probe reproduced the zero-page crash;
    the strong-symbol probe passed and recorded the FDB network call.
    - CloudUT [build
    
53003](http://47.243.177.214:8111/buildConfiguration/SelectdbCore_Cloudut/53003):
    all four previously crashing binaries returned raw `ret=0`; their 1 + 19
    + 22 + 24 FDB tests (66 total) passed without invoking ASAN-result
    masking.
    - Apache Doris master CloudUT on this PR: [build
    
1034381](http://43.132.222.7:8111/viewLog.html?buildId=1034381&buildTypeId=Doris_DorisCloudUt_CloudUt),
    running.
    - Local checks:
        - clang-format 16 dry-run;
    - C11 `-Wall -Wextra -Werror` syntax checks for both the fallback and
    `SYS_getrandom` paths;
        - CMake target-existence check;
        - `git diff --check`.
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test
        - [ ] Regression test
        - [x] Unit Test
        - [ ] Manual test (add detailed scripts or steps below)
        - [ ] No need to test or manual test. Explain why:
    - [ ] This is a refactor/code format and no logic has been changed.
            - [ ] Previous test can cover this change.
            - [ ] No code files have been changed.
            - [ ] Other reason
    
    - Behavior changed:
        - [x] No. Production binaries and FDB configuration are unchanged.
        - [ ] Yes.
    
    - Does this need documentation?
        - [x] No.
        - [ ] Yes.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 cloud/test/CMakeLists.txt          |  37 ++++++++++++
 cloud/test/fdb_getentropy_compat.c | 113 +++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+)

diff --git a/cloud/test/CMakeLists.txt b/cloud/test/CMakeLists.txt
index e8fefae321f..6620b0184fe 100644
--- a/cloud/test/CMakeLists.txt
+++ b/cloud/test/CMakeLists.txt
@@ -86,6 +86,16 @@ add_executable(http_encode_key_test http_encode_key_test.cpp)
 
 add_executable(fdb_injection_test fdb_injection_test.cpp)
 
+# This object supplies a process-local getentropy implementation for an ASAN
+# build/runtime glibc mismatch in CloudUT. Keep it test-only and 
Linux-ASAN-only
+# so production binaries and non-affected test configurations are unchanged.
+# Cloud is a separate CMake project and does not link the BE 
glibc-compatibility
+# objects, so the implementation must be attached explicitly here.
+if (OS_LINUX AND CMAKE_BUILD_TYPE STREQUAL "ASAN")
+    add_library(fdb_getentropy_compat OBJECT fdb_getentropy_compat.c)
+    target_compile_options(fdb_getentropy_compat PRIVATE -fPIC)
+endif()
+
 add_executable(s3_accessor_test s3_accessor_test.cpp)
 
 add_executable(s3_accessor_client_test s3_accessor_client_test.cpp)
@@ -240,6 +250,33 @@ target_link_libraries(bvars_test
     ${FDB_LINKER_FLAGS}
     ${TEST_LINK_LIBS})
 
+# libfdb_c probes getentropy as a weak symbol while initializing its network.
+# In the affected environment, compiler-rt's interceptor makes that probe pass
+# but cannot forward the call to the older runtime libc. Add the compatibility
+# object only to executables that may initialize FDB; ENABLE_EXPORTS puts the
+# strong executable symbol in the dynamic symbol table so libfdb_c resolves to
+# it instead of the unusable interceptor.
+set(FDB_NETWORK_TEST_TARGETS
+    bvars_test
+    document_message_test
+    doris_txn_test
+    fdb_injection_test
+    mem_txn_kv_test
+    meta_service_test
+    recycler_test
+    rpc_kv_bvar_test
+    txn_kv_test
+    txn_lazy_commit_test
+    versioned_value_test)
+
+if (TARGET fdb_getentropy_compat)
+    foreach(FDB_NETWORK_TEST_TARGET ${FDB_NETWORK_TEST_TARGETS})
+        target_sources(${FDB_NETWORK_TEST_TARGET}
+            PRIVATE $<TARGET_OBJECTS:fdb_getentropy_compat>)
+        set_target_properties(${FDB_NETWORK_TEST_TARGET} PROPERTIES 
ENABLE_EXPORTS ON)
+    endforeach()
+endif()
+
 install(FILES
     ${BASE_DIR}/script/run_all_tests.sh
     ${BASE_DIR}/conf/fdb.cluster
diff --git a/cloud/test/fdb_getentropy_compat.c 
b/cloud/test/fdb_getentropy_compat.c
new file mode 100644
index 00000000000..458e904bae6
--- /dev/null
+++ b/cloud/test/fdb_getentropy_compat.c
@@ -0,0 +1,113 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#if !defined(SYS_getrandom) && defined(__NR_getrandom)
+#define SYS_getrandom __NR_getrandom
+#endif
+
+// Why this compatibility symbol is needed:
+//
+// CloudUT ASAN executables are built against glibc 2.27 and run against glibc
+// 2.17. The ASAN runtime exports a getentropy interceptor, so libfdb_c's weak
+// symbol check concludes that getentropy is available. At runtime, however,
+// the interceptor cannot resolve a next libc implementation (RTLD_NEXT is
+// null on glibc 2.17) and calling it jumps to address zero.
+//
+// This file is linked only into Linux ASAN test executables that initialize
+// the FDB network. Its strong, exported symbol gives libfdb_c a valid target
+// in those processes. Calling the kernel directly is important: forwarding to
+// a libc entropy function could enter the same interceptor path again.
+
+// Build headers may define SYS_getrandom even when an older worker kernel does
+// not implement it. Fall back to /dev/urandom only when the syscall reports
+// ENOSYS.
+static int fill_from_urandom(unsigned char* output, size_t length) {
+    int fd;
+    do {
+        fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+    } while (fd < 0 && errno == EINTR);
+    if (fd < 0) {
+        return -1;
+    }
+
+    while (length > 0) {
+        const ssize_t bytes_read = read(fd, output, length);
+        if (bytes_read > 0) {
+            output += bytes_read;
+            length -= (size_t)bytes_read;
+            continue;
+        }
+        if (bytes_read < 0 && errno == EINTR) {
+            continue;
+        }
+
+        const int saved_errno = bytes_read == 0 ? EIO : errno;
+        close(fd);
+        errno = saved_errno;
+        return -1;
+    }
+
+    return close(fd);
+}
+
+int getentropy(void* buffer, size_t length) {
+    // Match the getentropy(3) contract. FDB requests small buffers, but 
keeping
+    // the standard 256-byte limit makes this a safe process-wide replacement.
+    if (length > 256) {
+        errno = EIO;
+        return -1;
+    }
+
+    unsigned char* output = (unsigned char*)buffer;
+
+#if defined(SYS_getrandom)
+    // Use syscall rather than libc getrandom/getentropy so this implementation
+    // cannot recurse through an ASAN interceptor.
+    while (length > 0) {
+        const long bytes_read = syscall(SYS_getrandom, output, length, 0);
+        if (bytes_read > 0) {
+            output += bytes_read;
+            length -= (size_t)bytes_read;
+            continue;
+        }
+        if (bytes_read < 0 && errno == EINTR) {
+            continue;
+        }
+        if (bytes_read < 0 && errno == ENOSYS) {
+            break;
+        }
+        if (bytes_read == 0) {
+            errno = EIO;
+        }
+        return -1;
+    }
+
+    if (length == 0) {
+        return 0;
+    }
+#endif
+
+    return fill_from_urandom(output, length);
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to