Make policy changes affect always entire package 48/207948/5
authorTomasz Swierczek <t.swierczek@samsung.com>
Fri, 14 Jun 2019 06:39:24 +0000 (08:39 +0200)
committerTomasz Swierczek <t.swierczek@samsung.com>
Wed, 19 Jun 2019 10:14:47 +0000 (12:14 +0200)
hybrid apps in a package don't share Smack label, so changes in policy
were done individually per each app. This has to be changed to be consistent
with entire platform's operation where each package, from end-user perspective,
is treated as one entity.

Change-Id: I456fe210f788f1fab39c619747bf57544193bae8

src/common/policy/PkgInfo.cpp
src/common/policy/PkgInfo.h
src/common/policy/Policy.cpp
src/common/policy/Policy.h
src/notification-daemon/Logic.cpp
src/notification-daemon/Logic.h
src/notification-daemon/PolicyUpdater.cpp
src/notification-daemon/PolicyUpdater.h

index 5773623..0827f98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2018 Samsung Electronics Co.
+ *  Copyright (c) 2018-2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -46,6 +46,38 @@ void AulPkgInfo::fetch(const std::string &pkgId, uid_t uid) {
     m_uid = uid;
 }
 
+int app_func(pkgmgrinfo_appinfo_h handle, void *user_data)
+{
+    char *appid = NULL;
+    int ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
+    if (ret != PMINFO_R_OK) {
+        ALOGE("pkgmgrinfo_appinfo_get_appid failed with " << ret);
+        return -1;
+    }
+    std::vector<std::string> *output = static_cast<std::vector<std::string>*>(user_data);
+    output->push_back(std::string(appid));
+    return 0;
+}
+
+std::vector<std::string> PkgMgrPkgInfo::listOfAppIds(const std::string &pkgId, uid_t uid)
+{
+    pkgmgrinfo_pkginfo_h handle = nullptr;
+    int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle);
+    std::vector<std::string> output;
+    if (ret != PMINFO_R_OK) {
+        ALOGE("pkgmgrinfo_pkginfo_get_usr_pkginfo failed for " << pkgId  << " with " << ret);
+        return output;
+    }
+    ret = pkgmgrinfo_appinfo_get_list(handle, PMINFO_ALL_APP, app_func, &output);
+    if (ret != PMINFO_R_OK) {
+        ALOGE("pkgmgrinfo_appinfo_get_list failed for " << pkgId  << " with " << ret);
+        pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+        return std::vector<std::string>();
+    }
+    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+    return output;
+}
+
 void PkgMgrPkgInfo::fetch(const std::string &pkgId, uid_t uid) {
     pkgmgrinfo_pkginfo_h handle = nullptr;
     int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle);
index c838ec9..af225cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017-2018 Samsung Electronics Co.
+ *  Copyright (c) 2017-2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 
 #include <string>
 #include <sys/types.h>
+#include <vector>
 
 namespace AskUser {
 
@@ -71,6 +72,8 @@ protected:
 };
 
 class PkgMgrPkgInfo : public PkgInfo {
+public:
+    static std::vector<std::string> listOfAppIds(const std::string &pkgId, uid_t uid);
 protected:
     virtual void fetch(const std::string &pkgId, uid_t uid);
 };
index 94f3bf9..67a8728 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2016-2018 Samsung Electronics Co.
+ *  Copyright (c) 2016-2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -128,7 +128,7 @@ std::vector<PolicyEntryCopy> getAppPolicy(const std::string &appId) {
     return fetch.fetchPolicy();
 }
 
-void identifyApp(PkgInfo &pkgInfo, const std::string &client, std::string &appId, std::string &pkgId)
+void identifyApp(PkgInfo &pkgInfo, const std::string &client, std::string &appId, std::string &pkgId, bool &isHybrid)
 {
     char *pkgName = nullptr;
     char *appName = nullptr;
@@ -138,6 +138,9 @@ void identifyApp(PkgInfo &pkgInfo, const std::string &client, std::string &appId
     std::unique_ptr<char, decltype(free)*> app_name_p(appName, free);
     throwOnSMError("security_manager_identify_app_from_cynara_client", ret);
 
+    // if the appId was in Smack label of client, it means that the app comes from hybrid package
+    isHybrid = (appName == nullptr ? false : true);
+
     if (!pkgName) {
         ALOGE("Couldn't identify clients package id");
         return;
index 5bcfb86..3af17fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2016-2018 Samsung Electronics Co.
+ *  Copyright (c) 2016-2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ namespace AskUser {
 class PolicyEntryCopy;
 
 std::string getOwnAppId(PkgInfo &pkgInfo);
-void identifyApp(PkgInfo &pkgInfo, const std::string &client, std::string &appId, std::string &pkgId);
+void identifyApp(PkgInfo &pkgInfo, const std::string &client, std::string &appId, std::string &pkgId, bool &isHybrid);
 
 std::set<Privilege> getManifestPrivs(const std::string &appId);
 
index f7b305b..c2027ef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017-2018 Samsung Electronics Co.
+ *  Copyright (c) 2017-2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -109,12 +109,13 @@ void Logic::addChannelFd(Protocol::ConnectionFd fd, const Protocol::Credentials
 
         std::string appId, pkgId;
         PkgMgrPkgInfo pkgInfo;
-        identifyApp(pkgInfo, creds.label, appId, pkgId);
+        bool isHybrid;
+        identifyApp(pkgInfo, creds.label, appId, pkgId, isHybrid);
 
         ALOGD("Proper client connected");
         stopTimer();
 
-        ConnectionInfo connInfo{appId, pkgId, creds.uid};
+        ConnectionInfo connInfo{appId, pkgId, creds.uid, isHybrid};
         m_connToInfo.insert(it, std::make_pair(fd, connInfo));
     } catch (const std::exception &e) {
         ALOGE("Failed to add channel fd " << fd);
@@ -423,7 +424,7 @@ bool Logic::setPolicy(const ConnectionInfo &conn) {
         levels[i] = clientResponseToPolicy(currentEvent.privacyResponses[privacy]);
     }
 
-    if (!PolicyUpdater::update(conn.appId, currentEvent.uniquePrivacies, levels)) {
+    if (!PolicyUpdater::update(conn.pkgId, conn.appId, conn.isHybrid, currentEvent.uniquePrivacies, levels)) {
         ALOGE("Couldn't set policy for " << conn.appId);
         return false;
     }
index 5e4a10a..dd7243f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017-2018 Samsung Electronics Co.
+ *  Copyright (c) 2017-2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -73,6 +73,7 @@ private:
         std::string appId;
         std::string pkgId;
         std::string user;
+        bool isHybrid;
     };
 
     struct PrivilegeStruct {
index c99ec05..068c17f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
 #include "PolicyUpdater.h"
 #include <policy/Policy.h>
 #include <policy/PrivilegeInfo.h>
+#include <policy/PkgInfo.h>
 
 namespace AskUser {
 
 namespace Notification {
 
-bool PolicyUpdater::update(const std::string &appId, const std::vector<std::string> &privacies,
+bool PolicyUpdater::update(const std::string &pkgId, const std::string &appId, bool isHybrid,
+                           const std::vector<std::string> &privacies,
                            const std::vector<std::string> &levels)
 {
     try {
-        ALOGD("Generating policy update for: app: " << appId << ", user:" << geteuid()
+        uid_t myUid = geteuid();
+        ALOGD("Generating policy update for: app: " << appId << ", hybrid: " << isHybrid << ", user:" << myUid
               << ", privacies num: " << privacies.size());
 
         if (privacies.size() != levels.size() || levels.size() == 0) {
@@ -49,34 +52,46 @@ bool PolicyUpdater::update(const std::string &appId, const std::vector<std::stri
         static const std::string user = std::to_string(geteuid());
         PolicyRequest req;
 
-        for (size_t i = 0; i < privacies.size(); ++i) {
-            const auto &privacy = privacies[i];
-            const auto &level = levels[i];
+        std::vector<std::string> appIds = {appId};
 
-            ALOGD("Generating policy update for: app: " << appId << ", user:" << geteuid()
-                  << ", privacy " << privacy << ", level: " << level);
+        if (isHybrid) {
+            // apps in a hybrid package have distinct Smack labels;
+            // since entire platform manages privileges per package,
+            // here we need to get all apps in the pkg for the policy
+            // to be effective for entire pkg
+            appIds = PkgMgrPkgInfo::listOfAppIds(pkgId, myUid);
+        }
 
-            auto privacyPrivs = PrivilegeInfo::getPrivacyPrivileges(privacy);
-            if (privacyPrivs.empty()) {
-                ALOGE("Unable to get privacy privileges for privacy " << privacy);
-                throw Exception("Unable to get privacy privileges for privacy " + privacy);
-            }
+        for (auto &app : appIds) {
+            for (size_t i = 0; i < privacies.size(); ++i) {
+                const auto &privacy = privacies[i];
+                const auto &level = levels[i];
+
+                ALOGD("Generating policy update for: app: " << app << ", user:" << geteuid()
+                      << ", privacy " << privacy << ", level: " << level);
+
+                auto privacyPrivs = PrivilegeInfo::getPrivacyPrivileges(privacy);
+                if (privacyPrivs.empty()) {
+                    ALOGE("Unable to get privacy privileges for privacy " << privacy);
+                    throw Exception("Unable to get privacy privileges for privacy " + privacy);
+                }
 
-            for (auto &priv : privacyPrivs) {
-                std::string currentPolicy = getPrivilegePolicy(appId, priv);
-                if (currentPolicy.empty()) {
-                    ALOGD("Application didn't request privilege " << priv << ", skipping");
-                    continue;
+                for (auto &priv : privacyPrivs) {
+                    std::string currentPolicy = getPrivilegePolicy(app, priv);
+                    if (currentPolicy.empty()) {
+                        ALOGD("Application didn't request privilege " << priv << ", skipping");
+                        continue;
+                    }
+                    ALOGD("Adding policy entries for : app: " << app << ", priv: "
+                          << priv  << ", user:" << user << ", level: "
+                          << level);
+                    PolicyEntry entry;
+                    entry.setApp(app);
+                    entry.setUser(user);
+                    entry.setPrivilege(priv);
+                    entry.setLevel(level);
+                    req.addEntry(std::move(entry));
                 }
-                ALOGD("Adding policy entries for : app: " << appId << ", priv: "
-                      << priv  << ", user:" << user << ", level: "
-                      << level);
-                PolicyEntry entry;
-                entry.setApp(appId);
-                entry.setUser(user);
-                entry.setPrivilege(priv);
-                entry.setLevel(level);
-                req.addEntry(std::move(entry));
             }
         }
 
index 8cc72a9..15815fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -30,7 +30,8 @@ namespace AskUser {
 namespace Notification {
 
 namespace PolicyUpdater {
-    bool update(const std::string &appId, const std::vector<std::string> &privacies,
+    bool update(const std::string &pkgId, const std::string &appId, bool isHybrid,
+                const std::vector<std::string> &privacies,
                 const std::vector<std::string> &levels);
 };