Fix buckets: aggregation of global and local instance privileges of an app 92/118092/3
authorDariusz Michaluk <d.michaluk@samsung.com>
Wed, 1 Mar 2017 15:02:16 +0000 (16:02 +0100)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 15 Mar 2017 12:13:51 +0000 (13:13 +0100)
Current Cynara bucket design has an issue of aggregation of privileges
of global and local instances of an applications,
meaning when app is installed both globally and locally it will gain a sum of it's privileges.

MANIFESTS bucket could be split into two:
MANIFESTS_GLOBAL - holding only rules for global applications (label * privilege ALLOW)
                   and redirections to second additional bucket
                   when applications is installed locally (label uid * bucket MANIFESTS_LOCAL)
MANIFESTS_LOCAL - have only local rules for local applications (label uid privilege ALLOW)
Both of them will have DENY by default.

Change-Id: Iba3da506fca570ca3e2147998d9012aa9e485b44

policy/security-manager-policy-reload.in
policy/updates/update-policy-to-v6.sh [new file with mode: 0755]
src/common/cynara.cpp
src/common/include/cynara.h
src/common/service_impl.cpp

index 2490ca326f0709e1e381c564acfeefde53cc9015..366303e7d98b94b04fe826983c3c40fc60e847c6 100755 (executable)
@@ -17,7 +17,8 @@ PRIVACY_MANAGER DENY
 ADMIN NONE
 APPDEFINED NONE
 MAIN DENY
-MANIFESTS DENY
+MANIFESTS_GLOBAL DENY
+MANIFESTS_LOCAL DENY
 END
 
 # Link buckets together
@@ -28,7 +29,7 @@ do
     cyad --set-policy --client="*" --user="*" --privilege="*" --type=BUCKET \
         --bucket="$bucket_src" --metadata="$bucket_dst"
 done <<END
-MAIN MANIFESTS
+MAIN MANIFESTS_GLOBAL
 PRIVACY_MANAGER MAIN
 ADMIN APPDEFINED
 END
@@ -60,17 +61,17 @@ done
 # Non-application programs get access to all privileges
 for client in User System System::Privileged
 do
-    cyad --set-policy --bucket=MANIFESTS --client="$client" --user="*" --privilege="*" --type=ALLOW
+    cyad --set-policy --bucket=MANIFESTS_GLOBAL --client="$client" --user="*" --privilege="*" --type=ALLOW
 done
 
 # Root shell get access to all privileges
-cyad --set-policy --bucket=MANIFESTS --client="User::Shell" --user="0" --privilege="*" --type=ALLOW
+cyad --set-policy --bucket=MANIFESTS_GLOBAL --client="User::Shell" --user="0" --privilege="*" --type=ALLOW
 
 # Shell process get access to packagemanager.admin privilege to install applications
-cyad --set-policy --bucket=MANIFESTS --client="User::Shell" --user="*" --privilege="http://tizen.org/privilege/packagemanager.admin" --type=ALLOW
+cyad --set-policy --bucket=MANIFESTS_GLOBAL --client="User::Shell" --user="*" --privilege="http://tizen.org/privilege/packagemanager.admin" --type=ALLOW
 
 # Shell process get access to packagemanager.info privilege to debug applications
-cyad --set-policy --bucket=MANIFESTS --client="User::Shell" --user="*" --privilege="http://tizen.org/privilege/packagemanager.info" --type=ALLOW
+cyad --set-policy --bucket=MANIFESTS_GLOBAL --client="User::Shell" --user="*" --privilege="http://tizen.org/privilege/packagemanager.info" --type=ALLOW
 
 # Load privilege-group mappings
 (
diff --git a/policy/updates/update-policy-to-v6.sh b/policy/updates/update-policy-to-v6.sh
new file mode 100755 (executable)
index 0000000..bd1fedc
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh -e
+
+export PATH=/sbin:/usr/sbin:/bin:/usr/bin
+
+. /etc/tizen-platform.conf
+
+systemctl stop security-manager.service security-manager.socket
+
+cyad --set-bucket=MANIFESTS_GLOBAL --type=DENY
+cyad --set-bucket=MANIFESTS_LOCAL --type=DENY
+cyad --set-policy --bucket=MAIN --client="*" --user="*" --privilege="*" --type=BUCKET \
+     --metadata=MANIFESTS_GLOBAL
+
+cyad --list-policies=MANIFESTS --user="*" --all |
+sed 's/MANIFESTS/MANIFESTS_GLOBAL/g' |
+cyad --set-policy --bucket=MANIFESTS_GLOBAL --bulk=-
+cyad --erase=MANIFESTS --recursive=no --client="#" --user="*" --privilege="#"
+
+cyad --list-policies=MANIFESTS --all |
+grep -v "User::Pkg::" |
+sed 's/MANIFESTS/MANIFESTS_GLOBAL/g' |
+cyad --set-policy --bucket=MANIFESTS_GLOBAL --bulk=-
+
+cyad --list-policies=MANIFESTS --all |
+grep "User::Pkg::" |
+sed 's/MANIFESTS/MANIFESTS_LOCAL/g' |
+cyad --set-policy --bucket=MANIFESTS_LOCAL --bulk=-
+
+cyad --list-policies=MANIFESTS_LOCAL --all |
+while IFS=";" read bucket client user privilege policy
+do
+    cyad --set-policy --bucket=MANIFESTS_GLOBAL --client="$client" --user="$user" --privilege="*" \
+         --type=BUCKET --metadata=MANIFESTS_LOCAL
+done
+
+cyad --delete-bucket=MANIFESTS
+
+systemctl start security-manager.service security-manager.socket
index 4fbf60d45a01b3dce8761b8735ebcf531591f989..447e0ec262f39896593eec1456e7faf62dc53085 100644 (file)
@@ -55,10 +55,12 @@ namespace SecurityManager {
  * - PRIVACY_MANAGER - first bucket during search (which is actually default bucket
  *   with empty string as id). If user specifies his preference then required rule
  *   is created here.
- * - MAIN            - holds rules denied by manufacturer, redirects to MANIFESTS
+ * - MAIN            - holds rules denied by manufacturer, redirects to MANIFESTS_GLOBAL
  *   bucket and holds entries for each user pointing to User Type
  *   specific buckets
- * - MANIFESTS       - stores rules needed by installed apps (from package
+ * - MANIFESTS_GLOBAL   - stores rules needed by globally installed apps (from package
+ *   manifest), redirects to MANIFESTS_LOCAL bucket when app is installed locally
+ * - MANIFESTS_LOCAL    - stores rules needed by locally installed apps (from package
  *   manifest)
  * - USER_TYPE_ADMIN
  * - USER_TYPE_SYSTEM
@@ -78,22 +80,28 @@ namespace SecurityManager {
  *  |      <<allow>>         |
  *  |   PRIVACY_MANAGER      |
  *  |                        |
- *  |  * * *      Bucket:MAIN|                         |------------------|
- *  |------------------------|                         |      <<deny>>    |
- *             |                                    |->|     MANIFESTS    |
- *             -----------------                    |  |                  |
- *                             |                    |  |------------------|
- *                             V                    |
- *                     |------------------------|   |
- *                     |       <<deny>>         |---|
- *                     |         MAIN           |
- * |---------------|   |                        |     |-------------------|
- * |    <<deny>>   |<--| * * *  Bucket:MANIFESTS|---->|      <<deny>>     |
- * | USER_TYPE_SYST|   |------------------------|     |  USER_TYPE_NORMAL |
- * |               |        |       |      |          |                   |
- * |---------------|        |       |      |          |-------------------|
- *        |                 |       |      |                    |
- *        |                 V       |      V                    |
+ *  |  * * *  Bucket:MAIN    |                         |-------------------------------|
+ *  |------------------------|                         |           <<deny>>            |
+ *             |                                    |->|       MANIFESTS_GLOBAL        |
+ *             -----------------                    |  |                               |
+ *                             |                    |  | c u *  Bucket:MANIFESTS_LOCAL |
+ *                             |                    |  |-------------------------------|
+ *                             V                    |                   |
+ *             |--------------------------------|   |                   V
+ *             |            <<deny>>            |---|           |------------------|
+ *             |              MAIN              |               |     <<deny>>     |
+ *             |                                |               |  MANIFESTS_LOCAL |
+ *             | * * *  Bucket:MANIFESTS_GLOBAL |               |                  |
+ *        |----|                                |----------|    |------------------|
+ *        |    |--------------------------------|          |
+ *        V               |         |      |               V
+ * |---------------|      |         |      |          |-------------------|
+ * |    <<deny>>   |      |         |      |          |      <<deny>>     |
+ * | USER_TYPE_SYST|      |         |      |          |  USER_TYPE_NORMAL |
+ * |               |      |         |      |          |                   |
+ * |---------------|      |         |      |          |-------------------|
+ *        |               |         |      |                    |
+ *        |               V         |      V                    |
  *        |      |---------------|  |   |---------------|       |
  *        |      |    <<deny>>   |  |   |    <<deny>>   |       |
  *        |      |USER_TYPE_GUEST|  |   |USER_TYPE_ADMIN|       |
@@ -134,7 +142,8 @@ CynaraAdmin::BucketsMap CynaraAdmin::Buckets =
     { Bucket::USER_TYPE_GUEST, std::string("USER_TYPE_GUEST") },
     { Bucket::USER_TYPE_SYSTEM, std::string("USER_TYPE_SYSTEM")},
     { Bucket::ADMIN, std::string("ADMIN")},
-    { Bucket::MANIFESTS, std::string("MANIFESTS")},
+    { Bucket::MANIFESTS_GLOBAL, std::string("MANIFESTS_GLOBAL")},
+    { Bucket::MANIFESTS_LOCAL, std::string("MANIFESTS_LOCAL")},
     { Bucket::APPDEFINED, std::string("APPDEFINED")},
 };
 
@@ -333,21 +342,42 @@ void CynaraAdmin::UpdateAppPolicy(
     uid_t uid,
     const std::vector<std::string> &privileges,
     const std::vector<std::pair<std::string, int>> &oldAppDefinedPrivileges,
-    const std::vector<std::pair<std::string, int>> &newAppDefinedPrivileges)
+    const std::vector<std::pair<std::string, int>> &newAppDefinedPrivileges,
+    bool policyRemove)
 {
     std::vector<CynaraAdminPolicy> oldPolicies;
     std::vector<CynaraAdminPolicy> policies;
 
-    std::string cynaraUser;
-    if (global)
+    // 1st, performing operation on MANIFESTS_GLOBAL/MANIFESTS_LOCAL bucket
+    std::string cynaraUser, bucket;
+    if (global) {
         cynaraUser = CYNARA_ADMIN_WILDCARD;
-    else
+        bucket = Buckets.at(Bucket::MANIFESTS_GLOBAL);
+    } else {
         cynaraUser = std::to_string(static_cast<unsigned int>(uid));
+        bucket = Buckets.at(Bucket::MANIFESTS_LOCAL);
+
+        // when app is installed locally add/remove redirection from MANIFESTS_GLOBAL to MANIFESTS_LOCAL
+        if (policyRemove) {
+            policies.push_back(CynaraAdminPolicy(
+                label,
+                cynaraUser,
+                "*",
+                static_cast<int>(CynaraAdminPolicy::Operation::Delete),
+                Buckets.at(Bucket::MANIFESTS_GLOBAL)));
+        } else {
+            policies.push_back(CynaraAdminPolicy(
+                label,
+                cynaraUser,
+                "*",
+                bucket,
+                Buckets.at(Bucket::MANIFESTS_GLOBAL)));
+        }
+    }
 
-    // 1st, performing operation on MANIFESTS bucket
-    ListPolicies(Buckets.at(Bucket::MANIFESTS), label, cynaraUser, CYNARA_ADMIN_ANY, oldPolicies);
-    CalculatePolicies(label, cynaraUser, privileges, Buckets.at(Bucket::MANIFESTS),
-        static_cast<int>(CynaraAdminPolicy::Operation::Allow), oldPolicies, policies);
+    ListPolicies(bucket, label, cynaraUser, CYNARA_ADMIN_ANY, oldPolicies);
+    CalculatePolicies(label, cynaraUser, privileges, bucket,
+                      static_cast<int>(CynaraAdminPolicy::Operation::Allow), oldPolicies, policies);
     oldPolicies.clear();
 
     bool askUserEnabled = false;
@@ -440,9 +470,11 @@ void CynaraAdmin::GetAppPolicy(const std::string &label, const std::string &user
         std::vector<std::string> &privileges)
 {
     std::vector<CynaraAdminPolicy> policies;
-    ListPolicies(
-        CynaraAdmin::Buckets.at(Bucket::MANIFESTS),
-        label, user, CYNARA_ADMIN_ANY, policies);
+    std::string bucket = (user == CYNARA_ADMIN_WILDCARD) ?
+        CynaraAdmin::Buckets.at(Bucket::MANIFESTS_GLOBAL) :
+        CynaraAdmin::Buckets.at(Bucket::MANIFESTS_LOCAL);
+
+    ListPolicies(bucket, label, user, CYNARA_ADMIN_ANY, policies);
 
     for (auto &policy : policies) {
         std::string privilege = policy.privilege;
@@ -486,7 +518,7 @@ void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType)
                                          Buckets.at(Bucket::MAIN)));
 
     std::vector<CynaraAdminPolicy> appPolicies;
-    ListPolicies(CynaraAdmin::Buckets.at(Bucket::MANIFESTS),
+    ListPolicies(CynaraAdmin::Buckets.at(Bucket::MANIFESTS_GLOBAL),
                  CYNARA_ADMIN_ANY, CYNARA_ADMIN_WILDCARD,
                  CYNARA_ADMIN_ANY, appPolicies);
 
index 394c1e186f1708e29a3958949304adaf4787e44d..b386f5be40b40b1476b7feca44de0198917a76a7 100644 (file)
@@ -50,7 +50,8 @@ enum class Bucket
     USER_TYPE_GUEST,
     USER_TYPE_SYSTEM,
     ADMIN,
-    MANIFESTS,
+    MANIFESTS_GLOBAL,
+    MANIFESTS_LOCAL,
     APPDEFINED
 };
 
@@ -135,11 +136,13 @@ public:
      * @param privileges currently enabled privileges
      * @param oldAppDefinedPrivileges old privileges defined by application
      * @param newAppDefinedPrivileges new privileges defined by application
+     * @param policyRemove true while application deinstallation
      */
     void UpdateAppPolicy(const std::string &label, bool global, uid_t uid,
         const std::vector<std::string> &privileges,
         const std::vector<std::pair<std::string, int>> &oldAppDefinedPrivileges,
-        const std::vector<std::pair<std::string, int>> &newAppDefinedPrivileges);
+        const std::vector<std::pair<std::string, int>> &newAppDefinedPrivileges,
+        bool policyRemove = false);
 
     /**
      * Fetch Cynara policies for the application and the user.
index e02c4451e3b0d87b4fa12638fefd6a2ca9323628..6982b0852a4ce29e1315f732b8a4d0b4b5aa0e4f 100644 (file)
@@ -705,7 +705,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req)
         bool global = req.installationType == SM_APP_INSTALL_GLOBAL ||
                       req.installationType == SM_APP_INSTALL_PRELOADED;
         m_cynaraAdmin.UpdateAppPolicy(processLabel, global, req.uid, std::vector<std::string>(),
-                                      oldAppDefinedPrivileges, std::vector<std::pair<std::string, int>>());
+                                      oldAppDefinedPrivileges, std::vector<std::pair<std::string, int>>(), true);
         trans.commit();
 
         LogDebug("Application uninstallation commited to database");