From: Tomasz Swierczek Date: Thu, 16 Jan 2025 12:30:17 +0000 (+0100) Subject: Fix possible issue with lazy-symbol binding X-Git-Tag: accepted/tizen/unified/20250117.011625~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f97fa87b06198319209cf73b720c2664a995101f;p=platform%2Fcore%2Fsecurity%2Fsecurity-manager.git Fix possible issue with lazy-symbol binding It seems possible that lazy binding of the SO symbols loaded by linker can cause problems when the SIGSETXID arrives in some thread at the precise moment that a symbol in a thread is being lazy-initialized. By doing calls below we're ensuring that symbols used inside our handler are already loaded - lazy symbols (or any not-loaded) should not be called inside a handler. Also, changed the handler to be a regular function for easier debugging in kernel team. Change-Id: I6a293374c38f47b18af86166d8b150af55469739 --- diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index bb1b80fe..d65d6626 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -811,6 +811,24 @@ static void signal_and_wait_for_handlers(pid_t own_pid, int own_tid) noexcept } while (true); } +static void sig_handler(int signo) +{ + (void)signo; + std::atomic_thread_fence(std::memory_order_acquire); + int tid = Syscall::gettid(); + set_tid_state(tid, 1); + while(g_th_barrier == 0) + usleep(SLEEP_CONST); + if (g_p_app_label) + if (label_for_self_internal(tid) != 0) + return; + if (cap_set_proc(g_cap)) + return; + set_tid_state(tid, 2); + while(g_th_barrier == 1) + usleep(SLEEP_CONST); +} + static inline int security_manager_sync_threads_internal(const std::string &app_label) { static_assert(ATOMIC_INT_LOCK_FREE == 2, "std::atomic is not always lock free"); @@ -838,22 +856,7 @@ static inline int security_manager_sync_threads_internal(const std::string &app_ sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; - act.sa_handler = [](int signo) { - (void)signo; - std::atomic_thread_fence(std::memory_order_acquire); - int tid = Syscall::gettid(); - set_tid_state(tid, 1); - while(g_th_barrier == 0) - usleep(SLEEP_CONST); - if (g_p_app_label) - if (label_for_self_internal(tid) != 0) - return; - if (cap_set_proc(g_cap)) - return; - set_tid_state(tid, 2); - while(g_th_barrier == 1) - usleep(SLEEP_CONST); - }; + act.sa_handler = sig_handler; if (Syscall::sigaction(SIGSETXID, &act, &old) < 0) { LogError("Error in sigaction()"); @@ -863,6 +866,27 @@ static inline int security_manager_sync_threads_internal(const std::string &app_ initialize_tid_states(); std::atomic_thread_fence(std::memory_order_release); + // It seems possible that lazy binding of the SO symbols loaded by linker can cause problems + // when the SIGSETXID arrives in some thread at the precise moment that a symbol in a thread + // is being lazy-initialized. By doing calls below we're ensuring that symbols used inside + // our handler are already loaded. + // not calling open/read/write/close/std::string anywyere as these are already used before, + // including openning connection to the daemon that uses sockets. + // + (void)syscall(-1); + usleep(SLEEP_CONST); + char buffer [10]; + int a = 1; + (void)sprintf(buffer, "%d", a); + cap_t tmp_cap = cap_get_proc(); + if (!tmp_cap) { + LogError("Unable to allocate capability object"); + return SECURITY_MANAGER_ERROR_MEMORY; + } + (void)cap_set_proc(tmp_cap); + (void)cap_free(tmp_cap); + // + g_th_barrier = 0; auto enabled = SecurityManager::Log::LogSystemSingleton::Instance().IsLoggingEnabled();