Rewrite shared RO directory support in security-manager 01/84601/14
authorMateusz Forc <m.forc@samsung.com>
Fri, 19 Aug 2016 10:52:01 +0000 (12:52 +0200)
committerTomasz Swierczek <t.swierczek@samsung.com>
Mon, 29 Aug 2016 06:21:19 +0000 (08:21 +0200)
Extend support to all apps instead of only 2.x apps.
Migrate database to version 7:
Add shared_ro INTEGER column in pkg table

Conflicts:
src/common/include/privilege_db.h
src/common/privilege_db.cpp

Change-Id: Id925342c37651ee0d87cf14de4d806ef63c678fb

db/db.sql
db/updates/update-db-to-v7.sql [new file with mode: 0644]
src/common/include/privilege_db.h
src/common/include/service_impl.h
src/common/include/smack-rules.h
src/common/privilege_db.cpp
src/common/service_impl.cpp
src/common/smack-rules.cpp
src/include/security-manager-types.h

index 805baa0b7244096689968ddd270c0d15c684e7bd..c85fc35ab4fecf3b838f0643bd420ed79ad5391b 100644 (file)
--- a/db/db.sql
+++ b/db/db.sql
@@ -4,12 +4,13 @@ PRAGMA auto_vacuum = NONE;
 
 BEGIN EXCLUSIVE TRANSACTION;
 
-PRAGMA user_version = 6;
+PRAGMA user_version = 7;
 
 CREATE TABLE IF NOT EXISTS pkg (
 pkg_id INTEGER PRIMARY KEY,
 name VARCHAR NOT NULL,
 author_id INTEGER,
+shared_ro INTEGER NOT NULL DEFAULT 0,
 UNIQUE (name)
 FOREIGN KEY (author_id) REFERENCES author (author_id)
 );
diff --git a/db/updates/update-db-to-v7.sql b/db/updates/update-db-to-v7.sql
new file mode 100644 (file)
index 0000000..4f93ef7
--- /dev/null
@@ -0,0 +1,11 @@
+BEGIN EXCLUSIVE TRANSACTION;
+
+PRAGMA user_version = 7;
+
+ALTER TABLE pkg ADD shared_ro INTEGER NOT NULL DEFAULT 0;
+
+UPDATE pkg
+SET shared_ro = 1
+WHERE pkg_id IN (SELECT pkg_id FROM app WHERE version < 3);
+
+COMMIT TRANSACTION;
index 5bc1519d30f9c1e11cd3c36cc70cf826eae3ffc0..1068699c50c44b45ab50d202d7f6d3c69e509ee8 100644 (file)
@@ -66,12 +66,15 @@ enum class StmtType {
     EClearPrivatePaths,
     EGetPrivilegeGroups,
     EGetUserApps,
-    EGetTizen2XPackages,
+    EGetAllPackages,
     EGetAppsInPkg,
     EGetGroups,
     EGetPkgAuthorId,
     EAuthorIdExists,
     EGetAuthorIdByName,
+    EGetSharedROPackages,
+    ESetPackageSharedRO,
+    EIsPackageSharedRO,
 };
 
 class PrivilegeDb {
@@ -120,12 +123,15 @@ private:
         { StmtType::EClearPrivatePaths, "DELETE FROM shared_path;"},
         { StmtType::EGetPrivilegeGroups, " SELECT group_name FROM privilege_group WHERE privilege_name = ?" },
         { StmtType::EGetUserApps, "SELECT app_name FROM user_app_pkg_view WHERE uid=?" },
-        { StmtType::EGetTizen2XPackages,  "SELECT DISTINCT pkg_name FROM user_app_pkg_view WHERE version LIKE '2.%%'" },
+        { StmtType::EGetAllPackages,  "SELECT DISTINCT pkg_name FROM user_app_pkg_view" },
         { StmtType::EGetAppsInPkg, " SELECT app_name FROM user_app_pkg_view WHERE pkg_name = ?" },
         { StmtType::EGetGroups, "SELECT DISTINCT group_name, privilege_name FROM privilege_group" },
         { StmtType::EGetPkgAuthorId, "SELECT author_id FROM pkg WHERE name = ? AND author_id IS NOT NULL"},
         { StmtType::EAuthorIdExists, "SELECT count(*) FROM author where author_id=?"},
         { StmtType::EGetAuthorIdByName, "SELECT author_id FROM author WHERE name=?"},
+        { StmtType::EGetSharedROPackages, "SELECT DISTINCT name FROM pkg WHERE shared_ro = 1;"},
+        { StmtType::ESetPackageSharedRO, "UPDATE pkg SET shared_ro=1 WHERE name=?"},
+        { StmtType::EIsPackageSharedRO, "SELECT shared_ro FROM pkg WHERE name=?"},
     };
 
     /**
@@ -416,15 +422,15 @@ public:
     void GetPkgApps(const std::string &pkgName, std::vector<std::string> &appNames);
 
     /**
-     * Retrieve list of all Tizen 2.X packages
+     * Retrieve list of all packages
      *
-     * @param[out] packages - vector of package identifiers describing installed 2.x packages,
-     *                    this parameter do not need to be empty, but
-     *                    it is being overwritten during function call.
+     * @param[out] packages - vector of package identifiers describing installed packages,
+     *                        this parameter do not need to be empty, but
+     *                        it is being overwritten during function call.
      * @exception DB::SqlConnection::Exception::InternalError on internal error
      * @exception DB::SqlConnection::Exception::ConstraintError on constraint violation
      */
-    void GetTizen2XPackages(std::vector<std::string> &packages);
+    void GetAllPackages(std::vector<std::string> &packages);
 
     /* Retrive an id of an author from database
      *
@@ -464,6 +470,32 @@ public:
      */
     void GetGroupsRelatedPrivileges(std::vector<std::pair<std::string, std::string>> &privileges);
 
+    /**
+     * Retrieve list of packages with shared RO set to 1
+     *
+     * @param[out] packages - vector of package identifiers describing installed packages,
+     *                        this parameter do not need to be empty, but
+     *                        it is being overwritten during function call.
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     * @exception DB::SqlConnection::Exception::ConstraintError on constraint violation
+     */
+    void GetSharedROPackages(std::vector<std::string> &packages);
+
+    /**
+     * Set shared_ro field to 1 in package given by name
+     *
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     * @exception DB::SqlConnection::Exception::ConstraintError on constraint violation
+     */
+    void SetSharedROPackage(const std::string& pkgName);
+
+    /**
+     * Check whether package has shared_ro field set to 1 in db
+     *
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     * @exception DB::SqlConnection::Exception::ConstraintError on constraint violation
+     */
+    bool IsPackageSharedRO(const std::string& pkgName);
 };
 
 } //namespace SecurityManager
index 82774ffcc48052b426c4bb808d39445301629dc9..658c60b122d8a7bd451e2047b07eb4c9d032a3ac 100644 (file)
@@ -66,11 +66,15 @@ private:
                            const std::vector<std::string> &allowedDirs);
 
     static int labelPaths(const pkg_paths &paths,
-                             const std::string &pkgName,
-                             app_install_type installationType,
-                             const uid_t &uid);
+                          const std::string &pkgName,
+                          app_install_type installationType,
+                          const uid_t &uid);
 
-    static void getTizen2XApps(SmackRules::PkgsApps &pkgsApps);
+    static void getAllApps(SmackRules::PkgsApps &pkgsApps);
+
+    static void getSharedROApps(SmackRules::PkgsApps &sharedROPkgsApps);
+
+    static bool isSharedRO(const pkg_paths& paths);
 
     static bool isPrivilegePrivacy(const std::string &privilege);
 
index 4e8962bfdd1b92bfaf0d77fffe03783c5e9635b0..9b96ba273d39aed0e6ed91b0858ec2e4bcb82c37 100644 (file)
@@ -76,20 +76,22 @@ public:
     void generatePackageCrossDeps(const std::vector<std::string> &pkgContents);
 
     /**
-     * Generate SharedRO rules for Tizen 2.x applications
-     * Each 2.X application gets read-only access to files shared by all other 2.X packages.
+     * Generate RO rules for all applications to SharedRO apps during appInstall/Uninstall
+     * Each application gets read-only access to files shared by SharedRO packages.
      *
-     * @param[in] pkgsApps    vector of Tizen 2.X applications - each element contains
-     *                        a pair with package name and contents
+     * @param[in] pkgsApps           vector of all applications - each element contains
+     *                               a pair with package name and contents
+     * @param[in] sharedROPkgsApps   vector of applications having sharedRO directory in their package -
+     *                               each element contains a pair with package name and contents
      */
-    static void generateSharedRORules(PkgsApps &pkgsApps);
+    static void generateSharedRORules(PkgsApps &pkgsApps, PkgsApps &sharedROPkgsApps);
 
     /**
-     * Revoke SharedRO rules for Tizen 2.x applications when a package is being removed
+     * Revoke SharedRO rules for applications when a package is being removed
      * Rules from all applications in \ref pkgsApps to SharedRO label of the package
      * under removal will be revoked from kernel.
      *
-     * @param[in] pkgsApps    vector of Tizen 2.X applications - each element contains
+     * @param[in] pkgsApps    vector of applications - each element contains
      *                        a pair with package name and contents
      * @param[in] revokePkg   package name being removed
      */
index 3b70cac4c545b6c45bf9d920cde481a86452068a..895da45cc59ee645232f0252e79c3d471a962c48 100644 (file)
@@ -407,15 +407,28 @@ void PrivilegeDb::GetUserApps(uid_t uid, std::vector<std::string> &apps)
     });
 }
 
-void PrivilegeDb::GetTizen2XPackages(std::vector<std::string> &packages)
+void PrivilegeDb::GetAllPackages(std::vector<std::string> &packages)
 {
     try_catch<void>([&] {
-        auto command = getStatement(StmtType::EGetTizen2XPackages);
+        auto command = getStatement(StmtType::EGetAllPackages);
         packages.clear();
         while (command->Step()) {
-            const std::string & tizen2XPkg = command->GetColumnString(0);
-            LogDebug("Found " << tizen2XPkg << " Tizen 2.X packages installed");
-            packages.push_back(tizen2XPkg);
+            const std::string &pkg = command->GetColumnString(0);
+            LogDebug("Found " << pkg << " package installed");
+            packages.push_back(pkg);
+        };
+     });
+}
+
+void PrivilegeDb::GetSharedROPackages(std::vector<std::string> &packages)
+{
+    try_catch<void>([&] {
+        auto command = getStatement(StmtType::EGetSharedROPackages);
+        packages.clear();
+        while (command->Step()) {
+            const std::string &pkg = command->GetColumnString(0);
+            LogDebug("Found " << pkg << " package installed");
+            packages.push_back(pkg);
         };
      });
 }
@@ -512,4 +525,31 @@ void PrivilegeDb::GetGroupsRelatedPrivileges(std::vector<std::pair<std::string,
     });
 }
 
+void PrivilegeDb::SetSharedROPackage(const std::string &pkgName)
+{
+   try_catch<void>([&] {
+        auto command = getStatement(StmtType::ESetPackageSharedRO);
+        command->BindString(1, pkgName);
+
+        if (command->Step())
+            LogDebug("shared_ro has been set to 1 for pkg: " << pkgName);
+    });
+}
+
+bool PrivilegeDb::IsPackageSharedRO(const std::string &pkgName)
+{
+   return try_catch<bool>([&]() -> bool {
+        auto command = getStatement(StmtType::EIsPackageSharedRO);
+        command->BindString(1, pkgName);
+        int shared_ro = 0;
+
+        if (command->Step())
+            shared_ro = command->GetColumnInteger(0);
+
+        LogDebug("Package " << pkgName << "has shared_ro set to " << shared_ro);
+
+        return (shared_ro > 0);
+    });
+}
+
 } //namespace SecurityManager
index 25852bfc61599a1236ee3c65bfb467e2a719a96e..96be37f84827635d047d548a5de330d9fea2b909 100644 (file)
@@ -137,16 +137,6 @@ static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr,
     return SECURITY_MANAGER_SUCCESS;
 }
 
-bool isTizen2XVersion(const std::string &version)
-{
-    std::size_t notWhitePos = version.find_first_not_of(" \t");
-    if (notWhitePos == std::string::npos)
-        return false;
-    if (version.at(notWhitePos) == '2')
-        return true;
-    return false;
-}
-
 bool sharingExists(const std::string &targetAppName, const std::string &path)
 {
     int targetPathCount;
@@ -450,10 +440,22 @@ int ServiceImpl::labelPaths(const pkg_paths &paths,
     }
 }
 
-void ServiceImpl::getTizen2XApps(SmackRules::PkgsApps &pkgsApps)
+void ServiceImpl::getAllApps(SmackRules::PkgsApps &pkgsApps)
+{
+    std::vector<std::string> pkgs;
+    PrivilegeDb::getInstance().GetAllPackages(pkgs);
+
+    pkgsApps.resize(pkgs.size());
+    for (size_t i = 0; i < pkgs.size(); ++i) {
+        pkgsApps[i].first = std::move(pkgs[i]);
+        PrivilegeDb::getInstance().GetPkgApps(pkgsApps[i].first, pkgsApps[i].second);
+    }
+}
+
+void ServiceImpl::getSharedROApps(SmackRules::PkgsApps &pkgsApps)
 {
     std::vector<std::string> pkgs;
-    PrivilegeDb::getInstance().GetTizen2XPackages(pkgs);
+    PrivilegeDb::getInstance().GetSharedROPackages(pkgs);
 
     pkgsApps.resize(pkgs.size());
     for (size_t i = 0; i < pkgs.size(); ++i) {
@@ -477,6 +479,17 @@ bool ServiceImpl::isPrivilegePrivacy(const std::string &privilege)
     return false;
 }
 
+bool ServiceImpl::isSharedRO(const pkg_paths& paths)
+{
+    for (const auto& pkgPath : paths) {
+        auto pathType = static_cast<app_install_path_type>(pkgPath.second);
+        if (pathType == SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO)
+            return true;
+    }
+
+    return false;
+}
+
 int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
 {
     std::vector<std::string> addedPermissions;
@@ -486,8 +499,10 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
     std::string pkgBasePath;
     std::string appLabel;
     std::string pkgLabel;
-    SmackRules::PkgsApps tizen2XpkgsApps;
+    SmackRules::PkgsApps sharedROPkgsApps;
+    SmackRules::PkgsApps allApps;
     int authorId;
+    bool hasSharedRO = isSharedRO(req.pkgPaths);
 
     try {
         installRequestMangle(req, cynaraUserStr);
@@ -514,9 +529,9 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
         PrivilegeDb::getInstance().GetPkgApps(req.pkgName, pkgContents);
         PrivilegeDb::getInstance().GetPkgAuthorId(req.pkgName, authorId);
         CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, cynaraUserStr, req.privileges, isPrivilegePrivacy);
-        // if app is targetted to Tizen 2.X, give other 2.X apps RO rules to it's shared dir
-        if (isTizen2XVersion(req.tizenVersion))
-            getTizen2XApps(tizen2XpkgsApps);
+
+        if (hasSharedRO)
+            PrivilegeDb::getInstance().SetSharedROPackage(req.pkgName);
 
         // WTF? Why this commit is here? Shouldn't it be at the end of this function?
         PrivilegeDb::getInstance().CommitTransaction();
@@ -562,8 +577,10 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
                 << req.pkgName << ". Applications in package: " << pkgContents.size());
         SmackRules::installApplicationRules(req.appName, req.pkgName, authorId, pkgContents);
 
-        if (isTizen2XVersion(req.tizenVersion))
-            SmackRules::generateSharedRORules(tizen2XpkgsApps);
+        getSharedROApps(sharedROPkgsApps);
+        getAllApps(allApps);
+
+        SmackRules::generateSharedRORules(allApps, sharedROPkgsApps);
 
         SmackRules::mergeRules();
     } catch (const SmackException::InvalidParam &e) {
@@ -591,7 +608,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req)
     bool removePkg = false;
     bool removeAuthor = false;
     std::string cynaraUserStr;
-    SmackRules::PkgsApps tizen2XpkgsApps;
+    SmackRules::PkgsApps pkgsApps, sharedROPkgsApps;
     std::map<std::string, std::vector<std::string>> asOwnerSharing;
     std::map<std::string, std::vector<std::string>> asTargetSharing;
     int authorId;
@@ -665,9 +682,8 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req)
 
         PrivilegeDb::getInstance().RemoveApplication(req.appName, req.uid, removeApp, removePkg, removeAuthor);
 
-        // if uninstalled app is targetted to Tizen 2.X, remove other 2.X apps RO rules it's shared dir
-        if (isTizen2XVersion(req.tizenVersion))
-            getTizen2XApps(tizen2XpkgsApps);
+        getAllApps(pkgsApps);
+        getSharedROApps(sharedROPkgsApps);
 
         CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector<std::string>(), isPrivilegePrivacy);
         PrivilegeDb::getInstance().CommitTransaction();
@@ -709,11 +725,9 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req)
                 SmackRules::updatePackageRules(req.pkgName, pkgContents);
             }
 
-            if (isTizen2XVersion(req.tizenVersion)) {
-                SmackRules::generateSharedRORules(tizen2XpkgsApps);
-                if (removePkg)
-                    SmackRules::revokeSharedRORules(tizen2XpkgsApps, req.pkgName);
-            }
+            SmackRules::generateSharedRORules(pkgsApps, sharedROPkgsApps);
+            if (removePkg)
+               SmackRules::revokeSharedRORules(pkgsApps, req.pkgName);
         }
 
         if (authorId != -1 && removeAuthor) {
@@ -1551,6 +1565,34 @@ int ServiceImpl::pathsRegister(const Credentials &creds, path_req req)
         return SECURITY_MANAGER_ERROR_MEMORY;
     }
 
+    try {
+        if (isSharedRO(req.pkgPaths)) {
+            PrivilegeDb::getInstance().BeginTransaction();
+
+            if (!PrivilegeDb::getInstance().IsPackageSharedRO(req.pkgName)) {
+
+                PrivilegeDb::getInstance().SetSharedROPackage(req.pkgName);
+
+                SmackRules::PkgsApps pkgsApps;
+                SmackRules::PkgsApps allApps;
+
+                getSharedROApps(pkgsApps);
+                getAllApps(allApps);
+
+                SmackRules::generateSharedRORules(allApps, pkgsApps);
+                SmackRules::mergeRules();
+            }
+        PrivilegeDb::getInstance().CommitTransaction();
+        }
+    } catch (const PrivilegeDb::Exception::IOError &e) {
+        LogError("Cannot access application database: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    } catch (const PrivilegeDb::Exception::InternalError &e) {
+        PrivilegeDb::getInstance().RollbackTransaction();
+        LogError("Error while saving application info to database: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    }
+
     return labelPaths(req.pkgPaths,
                       req.pkgName,
                       static_cast<app_install_type>(req.installationType),
index b1a3a617ef2cc6888ee5a9f8eec9d6f000408671..54fcecd384d9aed241c1ce86198af26aa530303d 100644 (file)
@@ -55,7 +55,7 @@ const std::string AUTHOR_RULES_TEMPLATE_FILE_PATH = TizenPlatformConfig::makePat
 const std::string SMACK_RULES_PATH_MERGED      = LOCAL_STATE_DIR "/security-manager/rules-merged/rules.merged";
 const std::string SMACK_RULES_PATH_MERGED_T    = LOCAL_STATE_DIR "/security-manager/rules-merged/rules.merged.temp";
 const std::string SMACK_RULES_PATH             = LOCAL_STATE_DIR "/security-manager/rules";
-const std::string SMACK_RULES_SHARED_RO_PATH   = LOCAL_STATE_DIR "/security-manager/rules/2x_shared_ro";
+const std::string SMACK_RULES_SHARED_RO_PATH   = LOCAL_STATE_DIR "/security-manager/rules/shared_ro";
 const std::string SMACK_APP_IN_PACKAGE_PERMS   = "rwxat";
 const std::string SMACK_APP_CROSS_PKG_PERMS    = "rx";
 const std::string SMACK_APP_PATH_OWNER_PERMS = "rwxat";
@@ -257,7 +257,7 @@ void SmackRules::generatePackageCrossDeps(const std::vector<std::string> &pkgCon
     }
 }
 
-void SmackRules::generateSharedRORules(PkgsApps &pkgsApps)
+void SmackRules::generateSharedRORules(PkgsApps &pkgsApps, PkgsApps &sharedROPkgsApps)
 {
     LogDebug("Generating SharedRO rules");
 
@@ -265,12 +265,13 @@ void SmackRules::generateSharedRORules(PkgsApps &pkgsApps)
     for (size_t i = 0; i < pkgsApps.size(); ++i) {
         for (const std::string &appName : pkgsApps[i].second) {
             std::string appLabel = SmackLabels::generateAppLabel(appName);
-            for (size_t j = 0; j < pkgsApps.size(); ++j) {
-                if (j != i) { // Rules for SharedRO files from own pkg are generated elsewhere
-                    std::string &pkgName = pkgsApps[j].first;
+            for (size_t j = 0; j < sharedROPkgsApps.size(); ++j) {
+                // Rules for SharedRO files from own pkg are generated elsewhere
+                if (pkgsApps[i] != sharedROPkgsApps[j]) {
+                    const std::string &pkgName = sharedROPkgsApps[j].first;
                     rules.add(appLabel,
-                        SmackLabels::generatePkgLabelOwnerRWothersRO(pkgName),
-                        SMACK_APP_CROSS_PKG_PERMS);
+                              SmackLabels::generatePkgLabelOwnerRWothersRO(pkgName),
+                              SMACK_APP_CROSS_PKG_PERMS);
                 }
             }
         }
@@ -294,8 +295,8 @@ void SmackRules::revokeSharedRORules(PkgsApps &pkgsApps, const std::string &revo
         for (const std::string &appName : pkgsApps[i].second) {
             std::string appLabel = SmackLabels::generateAppLabel(appName);
             rules.add(appLabel,
-                SmackLabels::generatePkgLabelOwnerRWothersRO(revokePkg),
-                SMACK_APP_CROSS_PKG_PERMS);
+                      SmackLabels::generatePkgLabelOwnerRWothersRO(revokePkg),
+                      SMACK_APP_CROSS_PKG_PERMS);
         }
     }
 
index 0c2891ef17043af66f04fe38ae053b3f1159f703..7b8c8bb6e07b8303168870aca201c516bde94169 100644 (file)
@@ -63,8 +63,7 @@ enum app_install_path_type {
     SECURITY_MANAGER_PATH_RW,
     //! RO access for given application package
     SECURITY_MANAGER_PATH_RO,
-    //! RW access for the owner, RO for other 2.X applications
-    //! (other 3.0 apps will not have access to the shared folder)
+    //! RW access for the owner, RO for other applications
     SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO,
     //! RW access for application packages coming from the same author
     SECURITY_MANAGER_PATH_TRUSTED_RW,