From dd6eefca303755264434454fddc0cc627e834577 Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Tue, 19 Mar 2019 11:39:14 -0700 Subject: [PATCH] libcutils: android_get_control_file uses realpath. If the path to android_get_control_file is a symlink, the final sanity check will fail that the fd does not have the same path as the given file. We can't expect callers to readlink() because this would change the environment key. Instead, try to call realpath on both paths. Bug: 126233777 Test: lpdump Change-Id: I0df10d7dbe3e572b8335faad812e5cd80bff1733 --- libcutils/android_get_control_file.cpp | 35 +++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/libcutils/android_get_control_file.cpp b/libcutils/android_get_control_file.cpp index f9964d2b0..d5b0894b2 100644 --- a/libcutils/android_get_control_file.cpp +++ b/libcutils/android_get_control_file.cpp @@ -39,6 +39,11 @@ #include #include +#include + +#include +#include + #include "android_get_control_env.h" int __android_get_control_from_env(const char* prefix, const char* name) { @@ -72,26 +77,22 @@ int __android_get_control_from_env(const char* prefix, const char* name) { } int android_get_control_file(const char* path) { - int fd = __android_get_control_from_env(ANDROID_FILE_ENV_PREFIX, path); + std::string given_path; + if (!android::base::Realpath(path, &given_path)) return -1; + + // Try path, then realpath(path), as keys to get the fd from env. + auto fd = __android_get_control_from_env(ANDROID_FILE_ENV_PREFIX, path); + if (fd < 0) { + fd = __android_get_control_from_env(ANDROID_FILE_ENV_PREFIX, given_path.c_str()); + if (fd < 0) return fd; + } // Find file path from /proc and make sure it is correct - char *proc = NULL; - if (asprintf(&proc, "/proc/self/fd/%d", fd) < 0) return -1; - if (!proc) return -1; + auto proc = android::base::StringPrintf("/proc/self/fd/%d", fd); + std::string fd_path; + if (!android::base::Realpath(proc, &fd_path)) return -1; - size_t len = strlen(path); - // readlink() does not guarantee a nul byte, len+2 so we catch truncation. - char *buf = static_cast(calloc(1, len + 2)); - if (!buf) { - free(proc); - return -1; - } - ssize_t ret = TEMP_FAILURE_RETRY(readlink(proc, buf, len + 1)); - free(proc); - int cmp = (len != static_cast(ret)) || strcmp(buf, path); - free(buf); - if (ret < 0) return -1; - if (cmp != 0) return -1; + if (given_path != fd_path) return -1; // It is what we think it is return fd;