Adapt application file labeling to new requirements 41/46841/7
authorRafal Krypa <r.krypa@samsung.com>
Mon, 31 Aug 2015 18:07:21 +0000 (20:07 +0200)
committerRafal Krypa <r.krypa@samsung.com>
Wed, 2 Sep 2015 15:14:57 +0000 (17:14 +0200)
The following changes has been made:
- application base path must now be APPS_ROOT/$pkgID, not
  APPS_ROOT/$pkgID/$appID
- application base path is now enforced, no files outside base path allowed
- application base path will be labeled with User::Pkg::$pkgID, no transmute
- SECURITY_MANAGER_PATH_TYPE_RO will be labeled with User::Pkg::$pkgID::RO
- applications get a Smack rule for RO access to User::Pkg::$pkgID::RO
- SECURITY_MANAGER_PATH_PUBLIC_RO will be labeled with User::Home
- SECURITY_MANAGER_PATH_PRIVATE and SECURITY_MANAGER_PATH_PUBLIC path types

Change-Id: I2d0260effcbe8da0c0e9130b89b4b34e7e104d29
Signed-off-by: Rafal Krypa <r.krypa@samsung.com>
policy/app-rules-template.smack
src/common/include/service_impl.h
src/common/include/smack-labels.h
src/common/include/smack-rules.h
src/common/service_impl.cpp
src/common/smack-labels.cpp
src/common/smack-rules.cpp
src/include/security-manager.h

index d0b6fb2..5bb1639 100644 (file)
@@ -4,9 +4,11 @@ System ~APP~ rwx
 ~APP~ System::Run rwxat
 ~APP~ System::Log rwxa
 ~APP~ _ l
-User ~APP~ rwxa
+User ~APP~ rwx
 User ~PKG~ rwxat
+User ~PKG~::RO rwxat
 ~APP~ User wx
 ~APP~ User::Home rxl
 ~APP~ User::App::Shared rwxat
 ~APP~ ~PKG~ rwxat
+~APP~ ~PKG~::RO rxl
index 0b6e3c6..ccf5e78 100644 (file)
@@ -43,7 +43,7 @@ private:
 
     static bool getUserAppDir(const uid_t &uid, std::string &userAppDir);
 
-    static bool installRequestAuthCheck(const app_inst_req &req, uid_t uid, bool &isCorrectPath, std::string &appPath);
+    static bool installRequestAuthCheck(const app_inst_req &req, uid_t uid, std::string &appPath);
 
     static bool getZoneId(std::string &zoneId);
 
index b454eff..1a68f1e 100644 (file)
@@ -37,49 +37,22 @@ namespace SmackLabels {
 /**
  * Sets Smack labels on a directory and its contents, recursively.
  *
- * @param appId[in] application's identifier
- * @param path[in] path to a file or directory to setup
- * @param pathType[in] type of path to setup. See description of
- *         app_install_path_type in security-manager.h for details
- *
- */
-void setupPath(const std::string &appId, const std::string &path,
-    app_install_path_type pathType);
-
-/**
- * Sets Smack labels on a directory and its contents, recursively.
- *
- * @param appId[in] application's identifier
+ * @param pkgId[in] application's package identifier
  * @param path[in] path to a file or directory to setup
  * @param pathType[in] type of path to setup. See description of
  *         app_install_path_type in security-manager.h for details
  * @param zoneId[in] ID of zone for which label should be set
  */
-void setupPath(const std::string &appId, const std::string &path,
+void setupPath(const std::string &pkgId, const std::string &path,
     app_install_path_type pathType, const std::string &zoneId);
 
 /**
- * Sets Smack labels on a <ROOT_APP>/<pkg_id> and <ROOT_APP>/<pkg_id>/<app_id>
- * non-recursively
+ * Sets Smack labels on a <ROOT_APP>/<pkg_id> non-recursively
  *
  * @param pkgId[in] package identifier
- * @param appId[in] application's identifier
  * @param basePath[in] <ROOT_APP> path
  */
-void setupCorrectPath(const std::string &pkgId, const std::string &appId,
-        const std::string &basePath);
-
-/**
- * Sets Smack labels on a <ROOT_APP>/<pkg_id> and <ROOT_APP>/<pkg_id>/<app_id>
- * non-recursively
- *
- * @param pkgId[in] package identifier
- * @param appId[in] application's identifier
- * @param basePath[in] <ROOT_APP> path
- * @param zoneId[in] ID of zone for which label should be set
- */
-void setupCorrectPath(const std::string &pkgId, const std::string &appId,
-        const std::string &basePath, const std::string &zoneId);
+void setupAppBasePath(const std::string &pkgId, const std::string &basePath);
 
 /**
  * Generates application name for a label fetched from Cynara
@@ -105,6 +78,15 @@ std::string generateAppLabel(const std::string &appId);
  */
 std::string generatePkgLabel(const std::string &pkgId);
 
+/**
+ * Generates label for private application RO files with package ID @ref pkgId
+ *
+ * @param[in] pkgId
+ * @return resulting Smack label
+ */
+std::string generatePkgROLabel(const std::string &pkgId);
+
+
 } // namespace SmackLabels
 } // namespace SecurityManager
 
index 5aadc12..c67c370 100644 (file)
@@ -155,6 +155,17 @@ private:
      */
     static void uninstallRules (const std::string &path);
 
+    /**
+     * Helper method: replace all occurrences of \ref needle in \ref haystack
+     * with \ref replace.
+     *
+     * @param[in,out] haystack string to modify
+     * @param needle string to find in \ref haystack
+     * @param replace string to replace \ref needle with
+     */
+    static void strReplace(std::string &haystack, const std::string &needle,
+            const std::string &replace);
+
     smack_accesses *m_handle;
 };
 
index 3f959a9..469f6a4 100644 (file)
@@ -168,7 +168,7 @@ bool ServiceImpl::isSubDir(const char *parent, const char *subdir)
         if (*parent++ != *subdir++)
             return false;
 
-    return (*subdir == '/');
+    return (*subdir == '/' || *parent == *subdir);
 }
 
 bool ServiceImpl::getUserAppDir(const uid_t &uid, std::string &userAppDir)
@@ -201,7 +201,7 @@ bool ServiceImpl::getUserAppDir(const uid_t &uid, std::string &userAppDir)
     return true;
 }
 
-bool ServiceImpl::installRequestAuthCheck(const app_inst_req &req, uid_t uid, bool &isCorrectPath, std::string &appPath)
+bool ServiceImpl::installRequestAuthCheck(const app_inst_req &req, uid_t uid, std::string &appPath)
 {
     std::string userHome;
     std::string userAppDir;
@@ -219,7 +219,7 @@ bool ServiceImpl::installRequestAuthCheck(const app_inst_req &req, uid_t uid, bo
 
     appPath = userAppDir;
     correctPath.clear();
-    correctPath << userAppDir << "/" << req.pkgId << "/" << req.appId;
+    correctPath << userAppDir << "/" << req.pkgId;
     LogDebug("correctPath: " << correctPath.str());
 
     for (const auto &appPath : req.appPaths) {
@@ -232,20 +232,8 @@ bool ServiceImpl::installRequestAuthCheck(const app_inst_req &req, uid_t uid, bo
         }
         LogDebug("Requested path is '" << appPath.first.c_str()
                 << "'. User's APPS_DIR is '" << userAppDir << "'");
-        if (!isSubDir(userAppDir.c_str(), real_path.get())) {
-            LogWarning("User's apps may have registered folders only in user's APPS_DIR");
-            return false;
-        }
-
         if (!isSubDir(correctPath.str().c_str(), real_path.get())) {
-            LogWarning("Installation is outside correct path: " << correctPath.str());
-            //return false;
-        } else
-            isCorrectPath = true;
-
-        app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
-        if (pathType == SECURITY_MANAGER_PATH_PUBLIC) {
-            LogWarning("Only root can register SECURITY_MANAGER_PATH_PUBLIC path");
+            LogWarning("Installation is outside correct path: " << correctPath.str() << "," << real_path.get());
             return false;
         }
     }
@@ -274,7 +262,6 @@ int ServiceImpl::appInstall(const app_inst_req &req, uid_t uid, bool isSlave)
     std::vector<std::string> removedPermissions;
     std::vector<std::string> pkgContents;
     std::string uidstr;
-    bool isCorrectPath = false;
     std::string appPath;
     std::string appLabel;
     std::string pkgLabel;
@@ -299,7 +286,7 @@ int ServiceImpl::appInstall(const app_inst_req &req, uid_t uid, bool isSlave)
     }
     checkGlobalUser(uid, uidstr);
 
-    if (!installRequestAuthCheck(req, uid, isCorrectPath, appPath)) {
+    if (!installRequestAuthCheck(req, uid, appPath)) {
         LogError("Request from uid " << uid << " for app installation denied");
         return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
     }
@@ -365,14 +352,14 @@ int ServiceImpl::appInstall(const app_inst_req &req, uid_t uid, bool isSlave)
     }
 
     try {
-        if (isCorrectPath)
-            SmackLabels::setupCorrectPath(req.pkgId, req.appId, appPath, zoneId);
+        if (!req.appPaths.empty())
+            SmackLabels::setupAppBasePath(req.pkgId, appPath);
 
         // register paths
         for (const auto &appPath : req.appPaths) {
             const std::string &path = appPath.first;
             app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
-            SmackLabels::setupPath(req.appId, path, pathType, zoneId);
+            SmackLabels::setupPath(req.pkgId, path, pathType, zoneId);
         }
 
         if (isSlave) {
index 236d090..c01d555 100644 (file)
@@ -42,8 +42,8 @@
 namespace SecurityManager {
 namespace SmackLabels {
 
-/* Const defined below is used to label files accessible to apps only for reading */
-const char *const LABEL_FOR_APP_RO_PATH = "User::Home";
+//! Smack label used for SECURITY_MANAGER_PATH_PUBLIC_RO paths (RO for all apps)
+const char *const LABEL_FOR_APP_PUBLIC_RO_PATH = "User::Home";
 
 typedef std::function<bool(const FTSENT*)> LabelDecisionFn;
 
@@ -126,34 +126,27 @@ static void labelDir(const std::string &path, const std::string &label,
         dirSetSmack(path, label, XATTR_NAME_SMACKEXEC, &labelExecs);
 }
 
-void setupPath(const std::string &appId, const std::string &path, app_install_path_type pathType)
-{
-    setupPath(appId, path, pathType, std::string());
-}
-
-void setupPath(const std::string &appId, const std::string &path, app_install_path_type pathType,
+void setupPath(const std::string &pkgId, const std::string &path, app_install_path_type pathType,
         const std::string &zoneId)
 {
     std::string label;
     bool label_executables, label_transmute;
 
     switch (pathType) {
-    case SECURITY_MANAGER_PATH_PRIVATE:
     case SECURITY_MANAGER_PATH_RW:
-        label = zoneSmackLabelGenerate(generateAppLabel(appId), zoneId);
+        label = zoneSmackLabelGenerate(generatePkgLabel(pkgId), zoneId);
         label_executables = true;
         label_transmute = false;
         break;
-    case SECURITY_MANAGER_PATH_PUBLIC:
     case SECURITY_MANAGER_PATH_RO:
-        label.assign(LABEL_FOR_APP_RO_PATH);
+        label = zoneSmackLabelGenerate(generatePkgROLabel(pkgId), zoneId);
         label_executables = false;
-        label_transmute = true;
+        label_transmute = false;
         break;
     case SECURITY_MANAGER_PATH_PUBLIC_RO:
-        label.assign("_");
+        label.assign(LABEL_FOR_APP_PUBLIC_RO_PATH);
         label_executables = false;
-        label_transmute = false;
+        label_transmute = true;
         break;
     default:
         LogError("Path type not known.");
@@ -162,20 +155,10 @@ void setupPath(const std::string &appId, const std::string &path, app_install_pa
     return labelDir(path, label, label_transmute, label_executables);
 }
 
-void setupCorrectPath(const std::string &pkgId, const std::string &appId, const std::string &basePath)
-{
-    setupCorrectPath(pkgId, appId, basePath, std::string());
-}
-
-void setupCorrectPath(const std::string &pkgId, const std::string &appId, const std::string &basePath,
-        const std::string& zoneId)
+void setupAppBasePath(const std::string &pkgId, const std::string &basePath)
 {
     std::string pkgPath = basePath + "/" + pkgId;
-    std::string appPath = pkgPath + "/" + appId;
-
-    pathSetSmack(pkgPath.c_str(), zoneSmackLabelGenerate(generatePkgLabel(pkgId), zoneId), XATTR_NAME_SMACK);
-    pathSetSmack(appPath.c_str(), zoneSmackLabelGenerate(generateAppLabel(appId), zoneId), XATTR_NAME_SMACK);
-    pathSetSmack(appPath.c_str(), "TRUE", XATTR_NAME_SMACKTRANSMUTE);
+    pathSetSmack(pkgPath.c_str(), LABEL_FOR_APP_PUBLIC_RO_PATH, XATTR_NAME_SMACK);
 }
 
 std::string generateAppNameFromLabel(const std::string &label)
@@ -208,5 +191,16 @@ std::string generatePkgLabel(const std::string &pkgId)
     return label;
 }
 
+std::string generatePkgROLabel(const std::string &pkgId)
+{
+    std::string label = "User::Pkg::" + pkgId + "::RO";
+
+    if (smack_label_length(label.c_str()) <= 0)
+        ThrowMsg(SmackException::InvalidLabel, "Invalid Smack label generated from pkgId " << pkgId);
+
+    return label;
+}
+
+
 } // namespace SmackLabels
 } // namespace SecurityManager
index d3bdf22..ce4f6e2 100644 (file)
@@ -177,17 +177,10 @@ void SmackRules::addFromTemplate(const std::vector<std::string> &templateRules,
             ThrowMsg(SmackException::FileError, "Invalid rule template: " << rule);
         }
 
-        if (subject == SMACK_APP_LABEL_TEMPLATE)
-            subject = SmackLabels::generateAppLabel(appId);
-
-        if (subject == SMACK_PKG_LABEL_TEMPLATE)
-            subject = SmackLabels::generatePkgLabel(pkgId);
-
-        if (object == SMACK_APP_LABEL_TEMPLATE)
-            object = SmackLabels::generateAppLabel(appId);
-
-        if (object == SMACK_PKG_LABEL_TEMPLATE)
-            object = SmackLabels::generatePkgLabel(pkgId);
+        strReplace(subject, SMACK_APP_LABEL_TEMPLATE, SmackLabels::generateAppLabel(appId));
+        strReplace(subject, SMACK_PKG_LABEL_TEMPLATE, SmackLabels::generatePkgLabel(pkgId));
+        strReplace(object,  SMACK_APP_LABEL_TEMPLATE, SmackLabels::generateAppLabel(appId));
+        strReplace(object,  SMACK_PKG_LABEL_TEMPLATE, SmackLabels::generatePkgLabel(pkgId));
 
         if (!zoneId.empty()) {
             // FIXME replace with vasum calls. See zone-utils.h
@@ -307,4 +300,12 @@ void SmackRules::uninstallRules(const std::string &path)
     }
 }
 
+void SmackRules::strReplace(std::string &haystack, const std::string &needle,
+            const std::string &replace)
+{
+    size_t pos;
+    while ((pos = haystack.find(needle)) != std::string::npos)
+        haystack.replace(pos, needle.size(), replace);
+}
+
 } // namespace SecurityManager
index 3c1304e..d9a735e 100644 (file)
@@ -46,17 +46,13 @@ enum lib_retcode {
 
 /*! \brief accesses types for application installation paths*/
 enum app_install_path_type {
-    //accessible read-write only for applications with same package id
-    SECURITY_MANAGER_PATH_PRIVATE,
-    //read-write access for all applications
-    SECURITY_MANAGER_PATH_PUBLIC,
-    //read only access for all applications
+    //! RO access for all applications
     SECURITY_MANAGER_PATH_PUBLIC_RO,
-    //accessible for writing to all apps within its package
+    //! RW access for given application package
     SECURITY_MANAGER_PATH_RW,
-    //accessible to apps for reading
+    //! RO access for given application package
     SECURITY_MANAGER_PATH_RO,
-    //this is only for range limit
+    //this is only for range limit
     SECURITY_MANAGER_ENUM_END
 };