Fix checking whether application path is inside user's home directory. 80/26680/1
authorRafal Krypa <r.krypa@samsung.com>
Wed, 27 Aug 2014 16:11:53 +0000 (18:11 +0200)
committerRafal Krypa <r.krypa@samsung.com>
Wed, 27 Aug 2014 16:13:30 +0000 (18:13 +0200)
Internal function installRequestAuthCheck() making this check contained
few bugs. It didn't canonicalize the home directory. It simply checked
for substring instead of subdirectory ("/home/useruser" shouldn't be
considered as subdirectory of "/home/user"). It relied on PATH_MAX for
realpath() calls, which is broken by design according to function manual.
All of the above issues are now corrected.

Change-Id: I446c50e642b38ecbd1b4997ec5e6f7c9b5032291
Signed-off-by: Rafal Krypa <r.krypa@samsung.com>
src/server/service/installer.cpp

index 4caf454..3e9f124 100644 (file)
@@ -178,40 +178,58 @@ bool InstallerService::processOne(const ConnectionID &conn, MessageBuffer &buffe
     return retval;
 }
 
+static inline bool isSubDir(const char *parent, const char *subdir)
+{
+    while (*parent && *subdir)
+        if (*parent++ != *subdir++)
+            return false;
+
+    return (*subdir == '/');
+}
+
 static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
 {
+    if (uid == 0)
+        return true;
+
     struct passwd *pwd;
-    char buffer[PATH_MAX];
     do {
         errno = 0;
         pwd = getpwuid(uid);
         if (!pwd && errno != EINTR) {
-            LogError("getpwuid failed with '" << uid << "' as paramter: " << strerror(errno));
+            LogError("getpwuid failed with '" << uid
+                    << "' as paramter: " << strerror(errno));
             return false;
         }
     } while (!pwd);
 
-    for (const auto &appPath : req.appPaths) {
+    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 paramter: " << strerror(errno));
+            return false;
+    }
 
-        if (uid != 0) {
-            char *real_path = realpath(appPath.first.c_str(), buffer);
-            if (!real_path) {
-                LogError("realpath failed with '" << appPath.first.c_str()
-                        << "' as paramter: " << strerror(errno));
-                return false;
-            }
-            LogDebug("Requested path is '" << appPath.first.c_str()
-                    << "'. User's HOME is '" << pwd->pw_dir << "'");
-            if (strncmp(pwd->pw_dir, real_path, strlen(pwd->pw_dir))!=0) {
-                LogWarning("User's apps may have registered folders only in user's home dir");
-                return false;
-            }
+    for (const auto &appPath : req.appPaths) {
+        std::unique_ptr<char, std::function<void(void*)>> real_path(
+            realpath(appPath.first.c_str(), NULL), free);
+        if (!real_path.get()) {
+            LogError("realpath failed with '" << appPath.first.c_str()
+                    << "' as paramter: " << strerror(errno));
+            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");
+            return false;
+        }
 
-            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");
-                return false;
-            }
+        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");
+            return false;
         }
     }
     return true;