[vold] Check incremental paths before mounting

Vold was trusting system_server too much and allowed for pretty
much any path in mount()/bindMount() calls for incremental.
This CL adds validation to make sure it's only accessing own
directories. This includes enforcing no symlinks in the paths

Ignore-AOSP-First: security fix
Bug: 198657657
Test: manual
Change-Id: I6035447f94ef44c4ae3294c3ae47de2d7210683a
Merged-In: I6035447f94ef44c4ae3294c3ae47de2d7210683a
diff --git a/Utils.cpp b/Utils.cpp
index 4635975..2144a3a 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1695,5 +1695,55 @@
 
     return OK;
 }
+
+namespace ab = android::base;
+
+static ab::unique_fd openDirFd(int parentFd, const char* name) {
+    return ab::unique_fd{::openat(parentFd, name, O_CLOEXEC | O_DIRECTORY | O_PATH | O_NOFOLLOW)};
+}
+
+static ab::unique_fd openAbsolutePathFd(std::string_view path) {
+    if (path.empty() || path[0] != '/') {
+        errno = EINVAL;
+        return {};
+    }
+    if (path == "/") {
+        return openDirFd(-1, "/");
+    }
+
+    // first component is special - it includes the leading slash
+    auto next = path.find('/', 1);
+    auto component = std::string(path.substr(0, next));
+    if (component == "..") {
+        errno = EINVAL;
+        return {};
+    }
+    auto fd = openDirFd(-1, component.c_str());
+    if (!fd.ok()) {
+        return fd;
+    }
+    path.remove_prefix(std::min(next + 1, path.size()));
+    while (next != path.npos && !path.empty()) {
+        next = path.find('/');
+        component.assign(path.substr(0, next));
+        fd = openDirFd(fd, component.c_str());
+        if (!fd.ok()) {
+            return fd;
+        }
+        path.remove_prefix(std::min(next + 1, path.size()));
+    }
+    return fd;
+}
+
+std::pair<android::base::unique_fd, std::string> OpenDirInProcfs(std::string_view path) {
+    auto fd = openAbsolutePathFd(path);
+    if (!fd.ok()) {
+        return {};
+    }
+
+    auto linkPath = std::string("/proc/self/fd/") += std::to_string(fd.get());
+    return {std::move(fd), std::move(linkPath)};
+}
+
 }  // namespace vold
 }  // namespace android