Removal of xattr "security.TIZEN_EXEC_LABEL"
[platform/core/security/security-manager.git] / src / client / client-security-manager.cpp
index c40097a..51130b6 100644 (file)
 
 #include <unistd.h>
 #include <grp.h>
+#include <dirent.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/xattr.h>
 #include <sys/smack.h>
+#include <sys/capability.h>
 
 #include <dpl/log/log.h>
 #include <dpl/exception.h>
@@ -239,32 +243,65 @@ int security_manager_get_app_pkgid(char **pkg_id, const char *app_id)
     });
 }
 
-SECURITY_MANAGER_API
-int security_manager_set_process_label_from_binary(const char *path)
+static bool setup_smack(const char *label)
 {
-    char *smack_label;
-    int ret;
-
-    LogDebug("security_manager_set_process_label_from_binary() called");
+    int labelSize = strlen(label);
 
-    if (smack_smackfs_path() == NULL)
-        return SECURITY_MANAGER_SUCCESS;
+    // Set Smack label for open socket file descriptors
 
-    if (path == NULL) {
-        LogError("security_manager_set_process_label_from_binary: path is NULL");
-        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    std::unique_ptr<DIR, std::function<int(DIR*)>> dir(
+        opendir("/proc/self/fd"), closedir);
+    if (!dir.get()) {
+        LogError("Unable to read list of open file descriptors: " <<
+            strerror(errno));
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
     }
 
-    ret = SecurityManager::getSmackLabelFromBinary(&smack_label, path);
-    if (ret == SECURITY_MANAGER_SUCCESS && smack_label != NULL) {
-        if (smack_set_label_for_self(smack_label) != 0) {
-            ret = SECURITY_MANAGER_ERROR_UNKNOWN;
-            LogError("Failed to set smack label " << smack_label << " for current process");
+    do {
+        errno = 0;
+        struct dirent *dirEntry = readdir(dir.get());
+        if (dirEntry == nullptr) {
+            if (errno == 0) // NULL return value also signals end of directory
+                break;
+
+            LogError("Unable to read list of open file descriptors: " <<
+                strerror(errno));
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
         }
-        free(smack_label);
-    }
 
-    return ret;
+        // Entries with numerical names specify file descriptors, ignore the rest
+        if (!isdigit(dirEntry->d_name[0]))
+            continue;
+
+        struct stat statBuf;
+        int fd = atoi(dirEntry->d_name);
+        int ret = fstat(fd, &statBuf);
+        if (ret != 0) {
+            LogWarning("fstat failed on file descriptor " << fd << ": " <<
+                strerror(errno));
+            continue;
+        }
+        if (S_ISSOCK(statBuf.st_mode)) {
+            ret = fsetxattr(fd, XATTR_NAME_SMACKIPIN, label, labelSize, 0);
+            if (ret != 0) {
+                LogError("Setting Smack label failed on file descriptor " <<
+                    fd << ": " << strerror(errno));
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+            }
+
+            ret = fsetxattr(fd, XATTR_NAME_SMACKIPOUT, label, labelSize, 0);
+            if (ret != 0) {
+                LogError("Setting Smack label failed on file descriptor " <<
+                    fd << ": " << strerror(errno));
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+            }
+        }
+    } while (true);
+
+    // Set Smack label of current process
+    smack_set_label_for_self(label);
+
+    return SECURITY_MANAGER_SUCCESS;
 }
 
 SECURITY_MANAGER_API
@@ -285,9 +322,9 @@ int security_manager_set_process_label_from_appid(const char *app_id)
     }
 
     if (SecurityManager::generateAppLabel(std::string(pkg_id), appLabel)) {
-        if (smack_set_label_for_self(appLabel.c_str()) != 0) {
+        ret = setup_smack(appLabel.c_str());
+        if (ret != SECURITY_MANAGER_SUCCESS) {
             LogError("Failed to set smack label " << appLabel << " for current process");
-            ret = SECURITY_MANAGER_ERROR_UNKNOWN;
         }
     }
     else {
@@ -379,3 +416,51 @@ int security_manager_set_process_groups_from_appid(const char *app_id)
         return SECURITY_MANAGER_SUCCESS;
     });
 }
+
+SECURITY_MANAGER_API
+int security_manager_drop_process_privileges(void)
+{
+    LogDebug("security_manager_drop_process_privileges() called");
+
+    int ret;
+    cap_t cap = cap_init();
+    if (!cap) {
+        LogError("Unable to allocate capability object");
+        return SECURITY_MANAGER_ERROR_MEMORY;
+    }
+
+    ret = cap_clear(cap);
+    if (ret) {
+        LogError("Unable to initialize capability object");
+        cap_free(cap);
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
+    }
+
+    ret = cap_set_proc(cap);
+    if (ret) {
+        LogError("Unable to drop process capabilities");
+        cap_free(cap);
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
+    }
+
+    cap_free(cap);
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_prepare_app(const char *app_id)
+{
+    LogDebug("security_manager_prepare_app() called");
+    int ret;
+
+    ret = security_manager_set_process_label_from_appid(app_id);
+    if (ret != SECURITY_MANAGER_SUCCESS)
+        return ret;
+
+    ret = security_manager_set_process_groups_from_appid(app_id);
+    if (ret != SECURITY_MANAGER_SUCCESS)
+        return ret;
+
+    ret = security_manager_drop_process_privileges();
+    return ret;
+}