prepare_app: simplify thread syncing 07/222507/6
authorKonrad Lipinski <k.lipinski2@samsung.com>
Wed, 15 Jan 2020 15:44:43 +0000 (16:44 +0100)
committerTomasz Swierczek <t.swierczek@samsung.com>
Thu, 23 Jan 2020 06:55:30 +0000 (06:55 +0000)
Change-Id: If78f4688d71213f06c525462cedb9d259f8d406b

src/client/client-security-manager.cpp

index de93c37589b0aa5a31125dd320be987a98a2c84f..143c3d79f9017c21344407804274346843e988b1 100644 (file)
@@ -89,10 +89,8 @@ static std::map<enum lib_retcode, std::string> lib_retcode_string_map = {
 };
 
 // variables & definitions for thread security attributes
-static std::string g_app_label;
+static const std::string *g_p_app_label;
 static std::atomic<int> g_threads_count;
-static std::map<uid_t, std::string> g_tid_attr_current_map;
-static bool g_smack_present;
 static cap_t g_cap;
 
 #define MAX_SIG_WAIT_TIME   1000
@@ -590,36 +588,24 @@ inline static int sigaction(int signum, const struct sigaction *act, struct siga
 
 inline static int label_for_self_internal()
 {
-    int fd;
-    int ret;
-    fd = open(g_tid_attr_current_map[Syscall::gettid()].c_str(), O_WRONLY);
-    if (fd < 0) {
+    const auto tid = Syscall::gettid();
+    char threadSelf[sizeof "/proc//attr/current" + 1 + std::numeric_limits<unsigned>::digits10];
+    sprintf(threadSelf, "/proc/%u/attr/current", unsigned(tid));
+    int fd = open(threadSelf, O_WRONLY);
+    if (fd < 0)
         return -1;
-    }
-    ret = write(fd, g_app_label.c_str(), g_app_label.length());
+    int ret = write(fd, g_p_app_label->c_str(), g_p_app_label->length());
     close(fd);
 
-    if (ret < 0) {
-        return -1;
-    }
-    return 0;
+    return ret < 0 ? -1 : 0;
 }
 
 static inline int security_manager_sync_threads_internal(const std::string &app_label)
 {
-    if (ATOMIC_INT_LOCK_FREE != 2) {
-        LogError("std::atomic<int> is not always lock free");
-        return SECURITY_MANAGER_ERROR_UNKNOWN;
-    }
+    static_assert(ATOMIC_INT_LOCK_FREE == 2, "std::atomic<int> is not always lock free");
 
-    FS::FileNameVector files = FS::getSubDirectoriesFromDirectory("/proc/self/task");
-    uid_t cur_tid = Syscall::gettid();
-    pid_t cur_pid = getpid();
+    FS::FileNameVector files = FS::getSubDirectoriesFromDirectory("/proc/self/task", true);
 
-    g_app_label = app_label;
-    g_threads_count = 0;
-    g_tid_attr_current_map.clear();
-    g_smack_present = smack_check();
     g_cap = cap_init();
 
     if (!g_cap) {
@@ -627,92 +613,83 @@ static inline int security_manager_sync_threads_internal(const std::string &app_
         return SECURITY_MANAGER_ERROR_MEMORY;
     }
 
-    if (cap_clear(g_cap)) {
-        LogError("Unable to initialize capability object");
-        cap_free(g_cap);
-        return SECURITY_MANAGER_ERROR_UNKNOWN;
-    }
+    if (smack_check())
+        g_p_app_label = &app_label;
 
-    struct sigaction act;
-    struct sigaction old;
-    memset(&act, '\0', sizeof(act));
-    memset(&old, '\0', sizeof(old));
+    if (files.size() > 1) {
+        const pid_t cur_pid = getpid();
+        const pid_t cur_tid = Syscall::gettid();
+        g_threads_count = files.size() - 1;
 
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = SA_RESTART;
-    act.sa_handler = [](int signo) {
-        (void)signo;
+        struct sigaction act;
+        struct sigaction old;
+        memset(&act, '\0', sizeof(act));
 
-        std::atomic_thread_fence(std::memory_order_acquire);
+        sigemptyset(&act.sa_mask);
+        act.sa_flags = SA_RESTART;
+        act.sa_handler = [](int signo) {
+            (void)signo;
 
-        if (g_smack_present)
-            if (label_for_self_internal() != 0)
-                return;
-
-        if (cap_set_proc(g_cap))
-            return;
+            std::atomic_thread_fence(std::memory_order_acquire);
 
-        g_threads_count++;
-    };
+            if (g_p_app_label)
+                if (label_for_self_internal() != 0)
+                    return;
 
-    if (Syscall::sigaction(SIGSETXID, &act, &old) < 0) {
-        LogError("Error in sigaction()");
-        cap_free(g_cap);
-        return SECURITY_MANAGER_ERROR_UNKNOWN;
-    }
-
-    int sent_signals_count = 0;
+            if (cap_set_proc(g_cap))
+                return;
 
-    for (auto const &e : files) {
-        if (e.compare(".") == 0 || e.compare("..") == 0)
-            continue;
+            g_threads_count--;
+        };
 
-        int tid = atoi(e.c_str());
-        if (tid == static_cast<int>(cur_tid))
-            continue;
+        if (Syscall::sigaction(SIGSETXID, &act, &old) < 0) {
+            LogError("Error in sigaction()");
+            goto err;
+        }
 
-        g_tid_attr_current_map[tid] = "/proc/self/task/" + std::to_string(tid) + "/attr/current";
-    }
+        std::atomic_thread_fence(std::memory_order_release);
 
-    std::atomic_thread_fence(std::memory_order_release);
+        for (auto const &e : files) {
+            const int tid = atoi(e.c_str());
+            if (tid == static_cast<int>(cur_tid))
+                continue;
 
-    for (auto const& t_pair : g_tid_attr_current_map) {
-        if (Syscall::tgkill(cur_pid, t_pair.first, SIGSETXID) < 0) {
-            LogWarning("Error in tgkill()");
-            continue;
+            if (Syscall::tgkill(cur_pid, tid, SIGSETXID) < 0) {
+                LogWarning("Error in tgkill()");
+                continue;
+            }
         }
 
-        sent_signals_count++;
-    }
+        LogDebug("sent_signals_count: " << files.size() - 1);
 
-    LogDebug("sent_signals_count: " << sent_signals_count);
+        for (int i = MAX_SIG_WAIT_TIME; g_threads_count && i; i--)
+            usleep(1000);   // 1 ms
 
-    for (int i = 0; g_threads_count != sent_signals_count && i < MAX_SIG_WAIT_TIME; ++i)
-        usleep(1000);   // 1 ms
+        Syscall::sigaction(SIGSETXID, &old, nullptr);
 
-    Syscall::sigaction(SIGSETXID, &old, nullptr);
-
-    if (g_threads_count != sent_signals_count) {
-        LogError("Not all threads synchronized: threads done: " << g_threads_count);
-        cap_free(g_cap);
-        return SECURITY_MANAGER_ERROR_UNKNOWN;
+        if (g_threads_count) {
+            LogError("Not all threads synchronized: threads left: " << g_threads_count);
+            goto err;
+        }
     }
 
-    if (g_smack_present && smack_set_label_for_self(g_app_label.c_str()) != 0) {
+    if (g_p_app_label && smack_set_label_for_self(app_label.c_str()) != 0) {
         LogError("smack_set_label_for_self failed");
-        cap_free(g_cap);
-        return SECURITY_MANAGER_ERROR_UNKNOWN;
+        goto err;
     }
 
     if (cap_set_proc(g_cap)) {
         LogError("Can't drop main thread capabilities");
-        cap_free(g_cap);
-        return SECURITY_MANAGER_ERROR_UNKNOWN;
+        goto err;
     }
 
     cap_free(g_cap);
 
     return SECURITY_MANAGER_SUCCESS;
+
+err:
+    cap_free(g_cap);
+    return SECURITY_MANAGER_ERROR_UNKNOWN;
 }
 
 static int security_manager_set_process_groups_internal(const std::string &app_label)