New structure of application file paths 85/34985/17
authorZbigniew Jasinski <z.jasinski@samsung.com>
Mon, 2 Feb 2015 15:16:53 +0000 (16:16 +0100)
committerRafal Krypa <r.krypa@samsung.com>
Mon, 2 Mar 2015 15:19:54 +0000 (16:19 +0100)
Application paths should be structures as:

<ROOT_APP>/<pkg_id>/<app_id>

where ROOT_APP should equlas to:

- TZ_USER_APP in single user's installation
- TZ_SYS_RW_APP in common/global installation

Change-Id: I4a407551d28401a2b94a80c34da690e0c91cfee7

src/common/include/smack-labels.h
src/common/service_impl.cpp
src/common/smack-labels.cpp

index 1e80305..ce48a28 100644 (file)
@@ -55,6 +55,17 @@ bool setupPath(const std::string &appId, const std::string &path,
 std::string generateAppNameFromLabel(const std::string &label);
 
 /**
+ * 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 path[in] <ROOT_APP> path
+ */
+bool setupCorrectPath(const std::string &pkgID, const std::string &appID,
+        const std::string &path);
+
+/**
  * Generates label for an application with a specific application ID
  * read from @ref appId and assigns it to @ref label.
  *
index feedde5..9576faa 100644 (file)
@@ -163,27 +163,57 @@ static inline bool isSubDir(const char *parent, const char *subdir)
     return (*subdir == '/');
 }
 
-static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
+static bool getUserAppDir(const uid_t &uid, std::string &userAppDir)
 {
-    struct passwd *pwd;
-    do {
-        errno = 0;
-        pwd = getpwuid(uid);
-        if (!pwd && errno != EINTR) {
-            LogError("getpwuid failed with '" << uid
-                    << "' as parameter: " << strerror(errno));
-            return false;
-        }
-    } while (!pwd);
+    struct tzplatform_context *tz_ctx = nullptr;
 
-    std::unique_ptr<char, std::function<void(void*)>> home(
-        realpath(pwd->pw_dir, NULL), free);
-    if (!home.get()) {
-            LogError("realpath failed with '" << pwd->pw_dir
-                    << "' as parameter: " << strerror(errno));
+    if (tzplatform_context_create(&tz_ctx))
             return false;
+
+    if (tzplatform_context_set_user(tz_ctx, uid)) {
+        tzplatform_context_destroy(tz_ctx);
+        tz_ctx = nullptr;
+        return false;
+    }
+
+    enum tzplatform_variable id =
+            (uid == getGlobalUserId()) ? TZ_SYS_RW_APP : TZ_USER_APP;
+    const char *appDir = tzplatform_context_getenv(tz_ctx, id);
+    if (!appDir) {
+        tzplatform_context_destroy(tz_ctx);
+        tz_ctx = nullptr;
+        return false;
     }
 
+    userAppDir = appDir;
+
+    tzplatform_context_destroy(tz_ctx);
+    tz_ctx = nullptr;
+
+    return true;
+}
+
+static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid, bool &isCorrectPath, std::string &appPath)
+{
+    std::string userHome;
+    std::string userAppDir;
+    std::stringstream correctPath;
+
+    if (uid != getGlobalUserId())
+        LogDebug("Installation type: single user");
+    else
+        LogDebug("Installation type: global installation");
+
+    if (!getUserAppDir(uid, userAppDir)) {
+        LogError("Failed getting app dir for user uid: " << uid);
+        return false;
+    }
+
+    appPath = userAppDir;
+    correctPath.clear();
+    correctPath << userAppDir << "/" << req.pkgId << "/" << req.appId;
+    LogDebug("correctPath: " << correctPath.str());
+
     for (const auto &appPath : req.appPaths) {
         std::unique_ptr<char, std::function<void(void*)>> real_path(
             realpath(appPath.first.c_str(), NULL), free);
@@ -193,12 +223,18 @@ static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
             return false;
         }
         LogDebug("Requested path is '" << appPath.first.c_str()
-                << "'. User's HOME is '" << pwd->pw_dir << "'");
-        if (!isSubDir(home.get(), real_path.get())) {
-            LogWarning("User's apps may have registered folders only in user's home dir");
+                << "'. 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");
@@ -214,6 +250,8 @@ int appInstall(const app_inst_req &req, uid_t uid)
     std::vector<std::string> removedPermissions;
     std::vector<std::string> pkgContents;
     std::string uidstr;
+    bool isCorrectPath = false;
+    std::string appPath;
     if (uid) {
         if (uid != req.uid) {
             LogError("User " << uid <<
@@ -226,7 +264,7 @@ int appInstall(const app_inst_req &req, uid_t uid)
     }
     checkGlobalUser(uid, uidstr);
 
-    if (!installRequestAuthCheck(req, uid)) {
+    if (!installRequestAuthCheck(req, uid, isCorrectPath, appPath)) {
         LogError("Request from uid " << uid << " for app installation denied");
         return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
     }
@@ -287,6 +325,12 @@ int appInstall(const app_inst_req &req, uid_t uid)
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
     }
 
+    if (isCorrectPath)
+        if (!setupCorrectPath(req.pkgId, req.appId, appPath)) {
+            LogError("Can't setup <APP_ROOT> dirs");
+            return false;
+        }
+
     // register paths
     for (const auto &appPath : req.appPaths) {
         const std::string &path = appPath.first;
index f60eab3..2e822a1 100644 (file)
@@ -73,6 +73,15 @@ static FileDecision labelExecs(const FTSENT *ftsent)
     return FileDecision::SKIP;
 }
 
+static inline bool pathSetSmack(const char *path, const std::string &label,
+        const char *xattr_name)
+{
+    if (lsetxattr(path, xattr_name, label.c_str(), label.length(), 0) != 0)
+        return false;
+
+    return true;
+}
+
 static bool dirSetSmack(const std::string &path, const std::string &label,
         const char *xattr_name, LabelDecisionFn fn)
 {
@@ -107,8 +116,8 @@ static bool dirSetSmack(const std::string &path, const std::string &label,
         }
 
         if (ret == FileDecision::LABEL) {
-            if (lsetxattr(ftsent->fts_path, xattr_name, label.c_str(), label.length(), 0) != 0) {
-                LogError("lsetxattr failed.");
+            if (!pathSetSmack(ftsent->fts_path, label, xattr_name)) {
+                LogError("pathSetSmack failed.");
                 return false;
             }
         }
@@ -123,7 +132,6 @@ static bool dirSetSmack(const std::string &path, const std::string &label,
     return true;
 }
 
-
 static bool labelDir(const std::string &path, const std::string &label,
         bool set_transmutable, bool set_executables)
 {
@@ -195,6 +203,39 @@ std::string generateAppNameFromLabel(const std::string &label)
     return label;
 }
 
+bool setupCorrectPath(const std::string &pkgId, const std::string &appId, const std::string &appPath)
+{
+    std::string tmpPath;
+    std::string label;
+
+    tmpPath.clear();
+    tmpPath = appPath + "/" + pkgId;
+
+    label.clear();
+    generatePkgLabel(pkgId, label);
+
+    if (!pathSetSmack(tmpPath.c_str(), label, XATTR_NAME_SMACK)) {
+        LogError("pathSetSmack failed (access label) on: " << tmpPath);
+        return false;
+    }
+
+    label.clear();
+    generateAppLabel(appId, label);
+    tmpPath += "/" + appId;
+
+    if (!pathSetSmack(tmpPath.c_str(), label, XATTR_NAME_SMACK)) {
+        LogError("pathSetSmack failed (access label) on: " << tmpPath);
+        return false;
+    }
+
+    if (!pathSetSmack(tmpPath.c_str(), "TRUE", XATTR_NAME_SMACKTRANSMUTE)) {
+        LogError("pathSetSmack failed (transmute) on: " << tmpPath);
+        return false;
+    }
+
+    return true;
+}
+
 bool generateAppLabel(const std::string &appId, std::string &label)
 {
     (void) appId;