From ffedc57563a2562d3bda1a8e593267508d1d7cd9 Mon Sep 17 00:00:00 2001 From: Ricky Wai Date: Mon, 20 Jan 2020 17:07:58 +0000 Subject: [PATCH] Copy directory name before closedir in Zygote We should not do closedir() before returning ent->d_name as ent is free after closedir(). Test: adb shell am instrument -w -r -e class com.android.launcher3.ui.TaplTestsLauncher3#testDragAppIcon com.google.android.apps.nexuslauncher.tests/androidx.test.runner.AndroidJUnitRunner Bug: 147746712 Bug: 143937733 Change-Id: I82ef70e0c5990e7b74ec58a9b47df7c770dec946 --- core/jni/com_android_internal_os_Zygote.cpp | 29 ++++++++++----------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 05b573ab90b43..c5b3873a004f5 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -1094,19 +1094,19 @@ static std::string getAppDataDirName(std::string_view parent_path, std::string_v fail_fn(CREATE_ERROR("Unexpected error in getAppDataDirName: %s", strerror(errno))); return nullptr; } - // Directory doesn't exist, try to search the name from inode - DIR* dir = opendir(parent_path.data()); - if (dir == nullptr) { - fail_fn(CREATE_ERROR("Failed to opendir %s", parent_path.data())); - } - struct dirent* ent; - while ((ent = readdir(dir))) { - if (ent->d_ino == ce_data_inode) { - closedir(dir); - return ent->d_name; + { + // Directory doesn't exist, try to search the name from inode + std::unique_ptr dir(opendir(parent_path.data()), closedir); + if (dir == nullptr) { + fail_fn(CREATE_ERROR("Failed to opendir %s", parent_path.data())); + } + struct dirent* ent; + while ((ent = readdir(dir.get()))) { + if (ent->d_ino == ce_data_inode) { + return ent->d_name; + } } } - closedir(dir); // Fallback due to b/145989852, ce_data_inode stored in package manager may be corrupted // if ino_t is 32 bits. @@ -1117,19 +1117,18 @@ static std::string getAppDataDirName(std::string_view parent_path, std::string_v fixed_ce_data_inode = ((ce_data_inode >> 32) & LOWER_HALF_WORD_MASK); } if (fixed_ce_data_inode != 0) { - dir = opendir(parent_path.data()); + std::unique_ptr dir(opendir(parent_path.data()), closedir); if (dir == nullptr) { fail_fn(CREATE_ERROR("Failed to opendir %s", parent_path.data())); } - while ((ent = readdir(dir))) { + struct dirent* ent; + while ((ent = readdir(dir.get()))) { if (ent->d_ino == fixed_ce_data_inode) { long long d_ino = ent->d_ino; ALOGW("Fallback success inode %lld -> %lld", ce_data_inode, d_ino); - closedir(dir); return ent->d_name; } } - closedir(dir); } // Fallback done