Add check for CAP_MAC_ADMIN inside prepare_app2 call 00/319400/5
authorTomasz Swierczek <t.swierczek@samsung.com>
Tue, 22 Oct 2024 14:52:08 +0000 (16:52 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 23 Oct 2024 19:25:32 +0000 (19:25 +0000)
Apparently in some weird scenarios, the wrt-loader or other launcher
that attempts at running apps, doesn't have the caps required.

Added check just prints proper error logs.

TODO: libsmack lacks function to get relabel-self list of labels
which probably should also be checked in the future (this is why
the check for CAP_MAC_ADMIN doesn't exit when there's no capability).

Change-Id: I5eeacb5ecb84883f6a4b2097887b82708297e98f

src/client/client-security-manager.cpp

index 7197f7232c20b045d14ed6ff6295df8b4ff16ac6..ab2ed3af476407de9b109ab3d9ce2ae72966de76 100644 (file)
@@ -613,6 +613,38 @@ inline static int label_for_self_internal(int tid)
     return ret < 0 ? -1 : 0;
 }
 
+// Checks if caller has CAP_MAC_ADMIN configured properly.
+// In cases where the capability is missing, this function
+// will write proper error logs for faster debugging.
+//
+// TODO the function would also probably need to check
+// list of "relabel-self" labels set in the process, but
+// libsmack doesn't have such function available (as of Oct 2024).
+//
+// Thats why its a void function & it doesn't abort too
+// (if capability is missing, we CAN have relabel-self configured).
+static inline void security_manager_pre_check()
+{
+    cap_t my_caps = cap_get_proc();
+    if (!my_caps) {
+        LogError("Unable to allocate capability object");
+        return;
+    }
+    cap_flag_value_t cap_flags_value;
+    if (cap_get_flag(my_caps, CAP_MAC_ADMIN, CAP_EFFECTIVE, &cap_flags_value) != 0) {
+        LogError("Can't check if process has CAP_MAC_ADMIN!!!");
+        cap_free(my_caps);
+        return;
+    }
+    if(cap_flags_value != CAP_SET) {
+        LogWarning("Process ****doesn't**** have effective CAP_MAC_ADMIN!"
+                   " It can still have dyntransition/relabel-self configured");
+        cap_free(my_caps);
+        return;
+    }
+    cap_free(my_caps);
+}
+
 static inline int security_manager_sync_threads_internal(const std::string &app_label)
 {
     static_assert(ATOMIC_INT_LOCK_FREE == 2, "std::atomic<int> is not always lock free");
@@ -1069,6 +1101,7 @@ int security_manager_prepare_app2(const char *app_name, const char *subsession_i
             (subsession_id ?: "(default)") + ")", Credentials::getCredentialsFromSelf());
 
     return try_catch([&] {
+        security_manager_pre_check();
 
         std::string appLabel, pkgName;
         PrepareAppFlags prepareAppFlags;