From 9a467b0a3cc3a0ee09cc923acb656e76050875bf Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Thu, 26 Mar 2026 18:36:37 +0100 Subject: [PATCH] fix: skip /tmp extraction when profiling libraries are installed The loader constructor used to extract both libdd_profiling-embedded.so and the ddprof executable to /tmp on every load. This triggers security scanners (e.g. Falcon) that flag new executables in /tmp. When ddprof is installed as a package, the .so already sits in a standard library search path and the binary is already in PATH. The extraction is unnecessary. The loader now tries dlopen with a bare library name first. Per dlopen(3), a filename without a slash is resolved through the standard search order (DT_RPATH, LD_LIBRARY_PATH, DT_RUNPATH, ldconfig cache, /lib, /usr/lib). If that succeeds, no files are written to /tmp at all. exec_ddprof gains a similar fallback: try execvp (PATH search) before resorting to memfd_create + fexecve from embedded data. When the libraries are NOT installed (self-contained / ad-hoc usage), both paths fall through to the existing /tmp extraction, so nothing changes for that use case. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/lib/dd_profiling.cc | 10 ++++++- src/lib/loader.c | 58 +++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/lib/dd_profiling.cc b/src/lib/dd_profiling.cc index 43a9a235..b6327e83 100644 --- a/src/lib/dd_profiling.cc +++ b/src/lib/dd_profiling.cc @@ -289,8 +289,16 @@ int exec_ddprof(pid_t target_pid, pid_t parent_pid, if (const char *ddprof_exe = g_state.getenv(k_profiler_ddprof_exe_env_variable); ddprof_exe) { + // Explicit path set (e.g. by loader after /tmp extraction). execve(ddprof_exe, argv, environ); - } else { + } + + // Try to find ddprof in PATH (covers the installed-package case without + // needing /tmp extraction or an explicit env var). + execvp(ddprof_str, argv); + + // PATH lookup failed: fall back to executing the embedded binary via memfd. + { auto exe_data = profiler_exe_data(); if (exe_data.size == 0) { return -1; diff --git a/src/lib/loader.c b/src/lib/loader.c index 3368b0aa..0b8be432 100644 --- a/src/lib/loader.c +++ b/src/lib/loader.c @@ -279,39 +279,53 @@ __typeof(ddprof_stop_profiling) *s_stop_profiling_func = NULL; static void __attribute__((constructor)) loader() { char *lib_profiling_path = getenv(k_profiler_lib_env_variable); + + ensure_libdl_is_loaded(); + ensure_libm_is_loaded(); + ensure_libpthread_is_loaded(); + ensure_librt_is_loaded(); + ensure_loader_symbols_promoted(); + if (!lib_profiling_path) { - EmbeddedData lib_data = profiling_lib_data(); - EmbeddedData exe_data = profiler_exe_data(); - if (lib_data.size == 0 || exe_data.size == 0) { - // nothing to do - return; - } - lib_profiling_path = get_or_create_temp_file( - k_libdd_profiling_embedded_name, lib_data, 0644); - char *profiler_exe_path = - get_or_create_temp_file(k_profiler_exe_name, exe_data, 0755); - if (!lib_profiling_path || !profiler_exe_path) { - free(lib_profiling_path); + // Try the bare library name first. If the .so is installed in a standard + // search path (or anywhere in LD_LIBRARY_PATH / DT_RPATH / ldconfig + // cache), dlopen finds it without extracting anything to /tmp. + s_profiling_lib_handle = + my_dlopen(k_libdd_profiling_embedded_name, RTLD_LOCAL | RTLD_NOW); + + if (!s_profiling_lib_handle) { + // Bare name not found: fall back to extracting embedded data to /tmp. + EmbeddedData lib_data = profiling_lib_data(); + EmbeddedData exe_data = profiler_exe_data(); + if (lib_data.size == 0 || exe_data.size == 0) { + // nothing to do + return; + } + lib_profiling_path = get_or_create_temp_file( + k_libdd_profiling_embedded_name, lib_data, 0644); + char *profiler_exe_path = + get_or_create_temp_file(k_profiler_exe_name, exe_data, 0755); + if (!lib_profiling_path || !profiler_exe_path) { + free(lib_profiling_path); + free(profiler_exe_path); + return; + } + setenv(k_profiler_ddprof_exe_env_variable, profiler_exe_path, 1); free(profiler_exe_path); - return; + s_profiling_lib_handle = + my_dlopen(lib_profiling_path, RTLD_LOCAL | RTLD_NOW); } - setenv(k_profiler_ddprof_exe_env_variable, profiler_exe_path, 1); - free(profiler_exe_path); } else { lib_profiling_path = strdup(lib_profiling_path); if (!lib_profiling_path) { return; } + s_profiling_lib_handle = + my_dlopen(lib_profiling_path, RTLD_LOCAL | RTLD_NOW); } - ensure_libdl_is_loaded(); - ensure_libm_is_loaded(); - ensure_libpthread_is_loaded(); - ensure_librt_is_loaded(); - ensure_loader_symbols_promoted(); - - s_profiling_lib_handle = my_dlopen(lib_profiling_path, RTLD_LOCAL | RTLD_NOW); free(lib_profiling_path); + if (s_profiling_lib_handle) { s_start_profiling_func = (__typeof(s_start_profiling_func))my_dlsym( s_profiling_lib_handle, "ddprof_start_profiling");