Loading core/java/com/android/internal/os/WebViewZygoteInit.java +3 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,9 @@ class WebViewZygoteInit { ClassLoader loader = ApplicationLoaders.getDefault().createAndCacheWebViewClassLoader( packagePath, libsPath); // Add the APK to the Zygote's list of allowed files for children. Zygote.nativeAllowFileAcrossFork(packagePath); // Once we have the classloader, look up the WebViewFactoryProvider implementation and // call preloadInZygote() on it to give it the opportunity to preload the native library // and perform any other initialisation work that should be shared among the children. Loading core/java/com/android/internal/os/Zygote.java +5 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,11 @@ public final class Zygote { native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities); /** * Lets children of the zygote inherit open file descriptors to this path. */ native protected static void nativeAllowFileAcrossFork(String path); /** * Zygote unmount storage space on initializing. * This method is called once. Loading core/jni/com_android_internal_os_Zygote.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -709,6 +709,16 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( return pid; } static void com_android_internal_os_Zygote_nativeAllowFileAcrossFork( JNIEnv* env, jclass, jstring path) { ScopedUtfChars path_native(env, path); const char* path_cstr = path_native.c_str(); if (!path_cstr) { RuntimeAbort(env, __LINE__, "path_cstr == NULL"); } FileDescriptorWhitelist::Get()->Allow(path_cstr); } static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* env, jclass) { // Zygote process unmount root storage space initially before every child processes are forked. // Every forked child processes (include SystemServer) only mount their own root storage space Loading Loading @@ -753,6 +763,8 @@ static const JNINativeMethod gMethods[] = { (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize }, { "nativeForkSystemServer", "(II[II[[IJJ)I", (void *) com_android_internal_os_Zygote_nativeForkSystemServer }, { "nativeAllowFileAcrossFork", "(Ljava/lang/String;)V", (void *) com_android_internal_os_Zygote_nativeAllowFileAcrossFork }, { "nativeUnmountStorageOnInit", "()V", (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit } }; Loading core/jni/fd_utils.cpp +92 −79 Original line number Diff line number Diff line Loading @@ -29,17 +29,7 @@ #include <android-base/strings.h> #include <cutils/log.h> // Whitelist of open paths that the zygote is allowed to keep open. // // In addition to the paths listed here, all files ending with // ".jar" under /system/framework" are whitelisted. See // FileDescriptorInfo::IsWhitelisted for the canonical definition. // // If the whitelisted path is associated with a regular file or a // character device, the file is reopened after a fork with the same // offset and mode. If the whilelisted path is associated with a // AF_UNIX socket, the socket will refer to /dev/null after each // fork, and all operations on it will fail. // Static whitelist of open paths that the zygote is allowed to keep open. static const char* kPathWhitelist[] = { "/dev/null", "/dev/socket/zygote", Loading @@ -54,6 +44,93 @@ static const char* kPathWhitelist[] = { static const char kFdPath[] = "/proc/self/fd"; // static FileDescriptorWhitelist* FileDescriptorWhitelist::Get() { if (instance_ == nullptr) { instance_ = new FileDescriptorWhitelist(); } return instance_; } bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { // Check the static whitelist path. for (const auto& whitelist_path : kPathWhitelist) { if (path == whitelist_path) return true; } // Check any paths added to the dynamic whitelist. for (const auto& whitelist_path : whitelist_) { if (path == whitelist_path) return true; } static const std::string kFrameworksPrefix = "/system/framework/"; static const std::string kJarSuffix = ".jar"; if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) { return true; } // Whitelist files needed for Runtime Resource Overlay, like these: // /system/vendor/overlay/framework-res.apk // /system/vendor/overlay-subdir/pg/framework-res.apk // /vendor/overlay/framework-res.apk // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap // See AssetManager.cpp for more details on overlay-subdir. static const std::string kOverlayDir = "/system/vendor/overlay/"; static const std::string kVendorOverlayDir = "/vendor/overlay"; static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/"; static const std::string kApkSuffix = ".apk"; if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir) || StartsWith(path, kVendorOverlayDir)) && EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) { return true; } static const std::string kOverlayIdmapPrefix = "/data/resource-cache/"; static const std::string kOverlayIdmapSuffix = ".apk@idmap"; if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix) && path.find("/../") == std::string::npos) { return true; } // All regular files that are placed under this path are whitelisted automatically. static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/"; if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) { return true; } return false; } FileDescriptorWhitelist::FileDescriptorWhitelist() : whitelist_() { } // TODO: Call android::base::StartsWith instead of copying the code here. // static bool FileDescriptorWhitelist::StartsWith(const std::string& str, const std::string& prefix) { return str.compare(0, prefix.size(), prefix) == 0; } // TODO: Call android::base::EndsWith instead of copying the code here. // static bool FileDescriptorWhitelist::EndsWith(const std::string& str, const std::string& suffix) { if (suffix.size() > str.size()) { return false; } return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; } FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr; // static FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { struct stat f_stat; Loading @@ -64,13 +141,15 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { return NULL; } const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get(); if (S_ISSOCK(f_stat.st_mode)) { std::string socket_name; if (!GetSocketName(fd, &socket_name)) { return NULL; } if (!IsWhitelisted(socket_name)) { if (!whitelist->IsAllowed(socket_name)) { ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd); return NULL; } Loading Loading @@ -98,7 +177,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { return NULL; } if (!IsWhitelisted(file_path)) { if (!whitelist->IsAllowed(file_path)) { ALOGE("Not whitelisted : %s", file_path.c_str()); return NULL; } Loading Loading @@ -218,72 +297,6 @@ FileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file is_sock(false) { } // TODO: Call android::base::StartsWith instead of copying the code here. // static bool FileDescriptorInfo::StartsWith(const std::string& str, const std::string& prefix) { return str.compare(0, prefix.size(), prefix) == 0; } // TODO: Call android::base::EndsWith instead of copying the code here. // static bool FileDescriptorInfo::EndsWith(const std::string& str, const std::string& suffix) { if (suffix.size() > str.size()) { return false; } return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; } // static bool FileDescriptorInfo::IsWhitelisted(const std::string& path) { for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) { if (kPathWhitelist[i] == path) { return true; } } static const std::string kFrameworksPrefix = "/system/framework/"; static const std::string kJarSuffix = ".jar"; if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) { return true; } // Whitelist files needed for Runtime Resource Overlay, like these: // /system/vendor/overlay/framework-res.apk // /system/vendor/overlay-subdir/pg/framework-res.apk // /vendor/overlay/framework-res.apk // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap // See AssetManager.cpp for more details on overlay-subdir. static const std::string kOverlayDir = "/system/vendor/overlay/"; static const std::string kVendorOverlayDir = "/vendor/overlay"; static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/"; static const std::string kApkSuffix = ".apk"; if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir) || StartsWith(path, kVendorOverlayDir)) && EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) { return true; } static const std::string kOverlayIdmapPrefix = "/data/resource-cache/"; static const std::string kOverlayIdmapSuffix = ".apk@idmap"; if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix) && path.find("/../") == std::string::npos) { return true; } // All regular files that are placed under this path are whitelisted automatically. static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/"; if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) { return true; } return false; } // TODO: Call android::base::Readlink instead of copying the code here. // static bool FileDescriptorInfo::Readlink(const int fd, std::string* result) { Loading core/jni/fd_utils.h +43 −10 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <set> #include <string> #include <unordered_map> #include <vector> #include <dirent.h> #include <inttypes.h> Loading @@ -27,6 +28,48 @@ #include <android-base/macros.h> // Whitelist of open paths that the zygote is allowed to keep open. // // In addition to the paths listed in kPathWhitelist in file_utils.cpp, and // paths dynamically added with Allow(), all files ending with ".jar" // under /system/framework" are whitelisted. See IsAllowed() for the canonical // definition. // // If the whitelisted path is associated with a regular file or a // character device, the file is reopened after a fork with the same // offset and mode. If the whilelisted path is associated with a // AF_UNIX socket, the socket will refer to /dev/null after each // fork, and all operations on it will fail. class FileDescriptorWhitelist { public: // Lazily creates the global whitelist. static FileDescriptorWhitelist* Get(); // Adds a path to the whitelist. void Allow(const std::string& path) { whitelist_.push_back(path); } // Returns true iff. a given path is whitelisted. A path is whitelisted // if it belongs to the whitelist (see kPathWhitelist) or if it's a path // under /system/framework that ends with ".jar" or if it is a system // framework overlay. bool IsAllowed(const std::string& path) const; private: FileDescriptorWhitelist(); static bool StartsWith(const std::string& str, const std::string& prefix); static bool EndsWith(const std::string& str, const std::string& suffix); static FileDescriptorWhitelist* instance_; std::vector<std::string> whitelist_; DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist); }; // Keeps track of all relevant information (flags, offset etc.) of an // open zygote file descriptor. class FileDescriptorInfo { Loading Loading @@ -56,16 +99,6 @@ class FileDescriptorInfo { FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, int fd_flags, int fs_flags, off_t offset); static bool StartsWith(const std::string& str, const std::string& prefix); static bool EndsWith(const std::string& str, const std::string& suffix); // Returns true iff. a given path is whitelisted. A path is whitelisted // if it belongs to the whitelist (see kPathWhitelist) or if it's a path // under /system/framework that ends with ".jar" or if it is a system // framework overlay. static bool IsWhitelisted(const std::string& path); static bool Readlink(const int fd, std::string* result); // Returns the locally-bound name of the socket |fd|. Returns true Loading Loading
core/java/com/android/internal/os/WebViewZygoteInit.java +3 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,9 @@ class WebViewZygoteInit { ClassLoader loader = ApplicationLoaders.getDefault().createAndCacheWebViewClassLoader( packagePath, libsPath); // Add the APK to the Zygote's list of allowed files for children. Zygote.nativeAllowFileAcrossFork(packagePath); // Once we have the classloader, look up the WebViewFactoryProvider implementation and // call preloadInZygote() on it to give it the opportunity to preload the native library // and perform any other initialisation work that should be shared among the children. Loading
core/java/com/android/internal/os/Zygote.java +5 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,11 @@ public final class Zygote { native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities); /** * Lets children of the zygote inherit open file descriptors to this path. */ native protected static void nativeAllowFileAcrossFork(String path); /** * Zygote unmount storage space on initializing. * This method is called once. Loading
core/jni/com_android_internal_os_Zygote.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -709,6 +709,16 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( return pid; } static void com_android_internal_os_Zygote_nativeAllowFileAcrossFork( JNIEnv* env, jclass, jstring path) { ScopedUtfChars path_native(env, path); const char* path_cstr = path_native.c_str(); if (!path_cstr) { RuntimeAbort(env, __LINE__, "path_cstr == NULL"); } FileDescriptorWhitelist::Get()->Allow(path_cstr); } static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* env, jclass) { // Zygote process unmount root storage space initially before every child processes are forked. // Every forked child processes (include SystemServer) only mount their own root storage space Loading Loading @@ -753,6 +763,8 @@ static const JNINativeMethod gMethods[] = { (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize }, { "nativeForkSystemServer", "(II[II[[IJJ)I", (void *) com_android_internal_os_Zygote_nativeForkSystemServer }, { "nativeAllowFileAcrossFork", "(Ljava/lang/String;)V", (void *) com_android_internal_os_Zygote_nativeAllowFileAcrossFork }, { "nativeUnmountStorageOnInit", "()V", (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit } }; Loading
core/jni/fd_utils.cpp +92 −79 Original line number Diff line number Diff line Loading @@ -29,17 +29,7 @@ #include <android-base/strings.h> #include <cutils/log.h> // Whitelist of open paths that the zygote is allowed to keep open. // // In addition to the paths listed here, all files ending with // ".jar" under /system/framework" are whitelisted. See // FileDescriptorInfo::IsWhitelisted for the canonical definition. // // If the whitelisted path is associated with a regular file or a // character device, the file is reopened after a fork with the same // offset and mode. If the whilelisted path is associated with a // AF_UNIX socket, the socket will refer to /dev/null after each // fork, and all operations on it will fail. // Static whitelist of open paths that the zygote is allowed to keep open. static const char* kPathWhitelist[] = { "/dev/null", "/dev/socket/zygote", Loading @@ -54,6 +44,93 @@ static const char* kPathWhitelist[] = { static const char kFdPath[] = "/proc/self/fd"; // static FileDescriptorWhitelist* FileDescriptorWhitelist::Get() { if (instance_ == nullptr) { instance_ = new FileDescriptorWhitelist(); } return instance_; } bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { // Check the static whitelist path. for (const auto& whitelist_path : kPathWhitelist) { if (path == whitelist_path) return true; } // Check any paths added to the dynamic whitelist. for (const auto& whitelist_path : whitelist_) { if (path == whitelist_path) return true; } static const std::string kFrameworksPrefix = "/system/framework/"; static const std::string kJarSuffix = ".jar"; if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) { return true; } // Whitelist files needed for Runtime Resource Overlay, like these: // /system/vendor/overlay/framework-res.apk // /system/vendor/overlay-subdir/pg/framework-res.apk // /vendor/overlay/framework-res.apk // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap // See AssetManager.cpp for more details on overlay-subdir. static const std::string kOverlayDir = "/system/vendor/overlay/"; static const std::string kVendorOverlayDir = "/vendor/overlay"; static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/"; static const std::string kApkSuffix = ".apk"; if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir) || StartsWith(path, kVendorOverlayDir)) && EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) { return true; } static const std::string kOverlayIdmapPrefix = "/data/resource-cache/"; static const std::string kOverlayIdmapSuffix = ".apk@idmap"; if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix) && path.find("/../") == std::string::npos) { return true; } // All regular files that are placed under this path are whitelisted automatically. static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/"; if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) { return true; } return false; } FileDescriptorWhitelist::FileDescriptorWhitelist() : whitelist_() { } // TODO: Call android::base::StartsWith instead of copying the code here. // static bool FileDescriptorWhitelist::StartsWith(const std::string& str, const std::string& prefix) { return str.compare(0, prefix.size(), prefix) == 0; } // TODO: Call android::base::EndsWith instead of copying the code here. // static bool FileDescriptorWhitelist::EndsWith(const std::string& str, const std::string& suffix) { if (suffix.size() > str.size()) { return false; } return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; } FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr; // static FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { struct stat f_stat; Loading @@ -64,13 +141,15 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { return NULL; } const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get(); if (S_ISSOCK(f_stat.st_mode)) { std::string socket_name; if (!GetSocketName(fd, &socket_name)) { return NULL; } if (!IsWhitelisted(socket_name)) { if (!whitelist->IsAllowed(socket_name)) { ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd); return NULL; } Loading Loading @@ -98,7 +177,7 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { return NULL; } if (!IsWhitelisted(file_path)) { if (!whitelist->IsAllowed(file_path)) { ALOGE("Not whitelisted : %s", file_path.c_str()); return NULL; } Loading Loading @@ -218,72 +297,6 @@ FileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file is_sock(false) { } // TODO: Call android::base::StartsWith instead of copying the code here. // static bool FileDescriptorInfo::StartsWith(const std::string& str, const std::string& prefix) { return str.compare(0, prefix.size(), prefix) == 0; } // TODO: Call android::base::EndsWith instead of copying the code here. // static bool FileDescriptorInfo::EndsWith(const std::string& str, const std::string& suffix) { if (suffix.size() > str.size()) { return false; } return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; } // static bool FileDescriptorInfo::IsWhitelisted(const std::string& path) { for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) { if (kPathWhitelist[i] == path) { return true; } } static const std::string kFrameworksPrefix = "/system/framework/"; static const std::string kJarSuffix = ".jar"; if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) { return true; } // Whitelist files needed for Runtime Resource Overlay, like these: // /system/vendor/overlay/framework-res.apk // /system/vendor/overlay-subdir/pg/framework-res.apk // /vendor/overlay/framework-res.apk // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap // See AssetManager.cpp for more details on overlay-subdir. static const std::string kOverlayDir = "/system/vendor/overlay/"; static const std::string kVendorOverlayDir = "/vendor/overlay"; static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/"; static const std::string kApkSuffix = ".apk"; if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir) || StartsWith(path, kVendorOverlayDir)) && EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) { return true; } static const std::string kOverlayIdmapPrefix = "/data/resource-cache/"; static const std::string kOverlayIdmapSuffix = ".apk@idmap"; if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix) && path.find("/../") == std::string::npos) { return true; } // All regular files that are placed under this path are whitelisted automatically. static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/"; if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) { return true; } return false; } // TODO: Call android::base::Readlink instead of copying the code here. // static bool FileDescriptorInfo::Readlink(const int fd, std::string* result) { Loading
core/jni/fd_utils.h +43 −10 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <set> #include <string> #include <unordered_map> #include <vector> #include <dirent.h> #include <inttypes.h> Loading @@ -27,6 +28,48 @@ #include <android-base/macros.h> // Whitelist of open paths that the zygote is allowed to keep open. // // In addition to the paths listed in kPathWhitelist in file_utils.cpp, and // paths dynamically added with Allow(), all files ending with ".jar" // under /system/framework" are whitelisted. See IsAllowed() for the canonical // definition. // // If the whitelisted path is associated with a regular file or a // character device, the file is reopened after a fork with the same // offset and mode. If the whilelisted path is associated with a // AF_UNIX socket, the socket will refer to /dev/null after each // fork, and all operations on it will fail. class FileDescriptorWhitelist { public: // Lazily creates the global whitelist. static FileDescriptorWhitelist* Get(); // Adds a path to the whitelist. void Allow(const std::string& path) { whitelist_.push_back(path); } // Returns true iff. a given path is whitelisted. A path is whitelisted // if it belongs to the whitelist (see kPathWhitelist) or if it's a path // under /system/framework that ends with ".jar" or if it is a system // framework overlay. bool IsAllowed(const std::string& path) const; private: FileDescriptorWhitelist(); static bool StartsWith(const std::string& str, const std::string& prefix); static bool EndsWith(const std::string& str, const std::string& suffix); static FileDescriptorWhitelist* instance_; std::vector<std::string> whitelist_; DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist); }; // Keeps track of all relevant information (flags, offset etc.) of an // open zygote file descriptor. class FileDescriptorInfo { Loading Loading @@ -56,16 +99,6 @@ class FileDescriptorInfo { FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, int fd_flags, int fs_flags, off_t offset); static bool StartsWith(const std::string& str, const std::string& prefix); static bool EndsWith(const std::string& str, const std::string& suffix); // Returns true iff. a given path is whitelisted. A path is whitelisted // if it belongs to the whitelist (see kPathWhitelist) or if it's a path // under /system/framework that ends with ".jar" or if it is a system // framework overlay. static bool IsWhitelisted(const std::string& path); static bool Readlink(const int fd, std::string* result); // Returns the locally-bound name of the socket |fd|. Returns true Loading