From: Krzysztof Jackiewicz Date: Mon, 14 Apr 2025 17:12:37 +0000 (+0200) Subject: Add errno abort helper X-Git-Tag: accepted/tizen/9.0/unified/20250428.133422~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Ftizen_9.0_dev;p=platform%2Fcore%2Fsecurity%2Fsecurity-manager.git Add errno abort helper When allocations and logging are disallowed there's no way to get the errno value. Add a helper that puts the errno value in the stack using template functions. Also move the end of no-allocation area after the last barrier bump. Change-Id: I864c2104e2fa617feb8764e64e8e73673dd1e2d5 --- diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index bb07b594..bc966a56 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -70,6 +70,71 @@ #include "filesystem.h" #include "mount-namespace.h" +namespace { + +class ErrnoAbort { + template + [[noreturn]] static void errnoHandler() noexcept + { + abort(); + } + + using AbortMap = std::unordered_map; + + template + void addHandler() + { + ([&] { + [[maybe_unused]] bool inserted = map.try_emplace(Errno, &errnoHandler).second; + assert(inserted); + }(), ...); + } + + AbortMap map; + +public: + ErrnoAbort() + { + addHandler(); + } + + [[noreturn]] void call() const noexcept + { + int err = errno; + auto it = map.find(err); + if (it == map.end()) + abort(); + + it->second(); + abort(); + } +}; + +const ErrnoAbort errnoAbort; + +} // namespace + static const char *EMPTY = ""; static const std::string SMACK_SYSTEM = "System"; static std::string SMACK_SYSTEM_PRIVILEGED = "System::Privileged"; @@ -596,17 +661,25 @@ inline static int sigaction(int signum, const struct sigaction *act, struct siga } // namespace Syscall -inline static int label_for_self_internal(int tid) +inline static int label_for_self_internal(int tid, void(*error_handler)() = nullptr) { char threadSelf[sizeof "/proc//attr/current" + 1 + std::numeric_limits::digits10]; sprintf(threadSelf, "/proc/%u/attr/current", unsigned(tid)); int fd = open(threadSelf, O_WRONLY); - if (fd < 0) + if (fd < 0) { + if (error_handler) + error_handler(); return -1; + } int ret = write(fd, g_p_app_label->c_str(), g_p_app_label->length()); close(fd); + if (ret < 0) { + if (error_handler) + error_handler(); + return -1; + } - return ret < 0 ? -1 : 0; + return 0; } // Checks if caller has CAP_MAC_ADMIN configured properly. @@ -655,12 +728,12 @@ static bool alive_threads_have_state(int status) noexcept static int get_alive_threads(int own_tid, bool abort_on_error) noexcept { - auto handle_error = [&]{ - if (abort_on_error) - abort(); + auto handle_error = [&]{ + if (abort_on_error) + errnoAbort.call(); - return errno; - }; + return errno; + }; // reset alive status memset(&g_thread_alive, 0, sizeof(g_thread_alive)); @@ -672,11 +745,12 @@ static int get_alive_threads(int own_tid, bool abort_on_error) noexcept char buf[1024]; struct dirent64 *d; int bpos = 0; - for(;;) { + int ret = 0; + for(;ret == 0;) { ssize_t nread = getdents64(dir_fd, buf, sizeof(buf)); if (nread == -1) { - close(dir_fd); - return handle_error(); + ret = handle_error(); + break; } if (nread == 0) @@ -698,8 +772,8 @@ static int get_alive_threads(int own_tid, bool abort_on_error) noexcept errno = 0; long tid = strtol(d->d_name, &endptr, 10); if (errno != 0) { - close(dir_fd); - return handle_error(); + ret = handle_error(); + break; } if (tid == own_tid) @@ -721,7 +795,7 @@ static int get_alive_threads(int own_tid, bool abort_on_error) noexcept } close(dir_fd); - return 0; + return ret; } static void check_threads(int own_tid) noexcept @@ -778,14 +852,14 @@ static void signal_and_wait_for_handlers(pid_t own_pid, int own_tid) noexcept g_thread_alive[i] = false; continue; } else { - abort(); + errnoAbort.call(); } } } else if (ESRCH == err) { // thread already gone - noop g_thread_alive[i] = false; continue; } else { - abort(); + errnoAbort.call(); } } } @@ -921,20 +995,19 @@ static inline int security_manager_sync_threads_internal(const std::string &app_ /* * Change attributes of one last thread, the main thread. */ - if (g_p_app_label && label_for_self_internal(own_tid) != 0) - abort(); + if (g_p_app_label) + label_for_self_internal(own_tid, []{ errnoAbort.call(); }); if (cap_set_proc(g_cap)) - abort(); + errnoAbort.call(); + + g_th_barrier++; // this starts signal handlers to proceed once they wake up - logic in app starts in env where all have changed labels // No allocations allowed before this point if (enabled) SecurityManager::Log::LogSystemSingleton::Instance().Enable(true); - g_th_barrier++; // this starts signal handlers to proceed once they wake up - logic in app starts in env where all have changed labels - - if (Syscall::sigaction(SIGSETXID, &old, nullptr) < 0) { LogError("Error in sigaction()"); abort();