Merge "Have DumpPool return futures"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 17f52ce..0e9ce89 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1586,7 +1586,6 @@
DumpFile("BUDDYINFO", "/proc/buddyinfo");
DumpExternalFragmentationInfo();
- DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
RunCommand("PROCESSES AND THREADS",
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 00babc3..fd38ddf 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -10,6 +10,7 @@
cc_defaults {
name: "installd_defaults",
+ cpp_std: "c++2a",
cflags: [
"-Wall",
"-Werror",
@@ -41,6 +42,7 @@
"libbinder",
"libcrypto",
"libcutils",
+ "libext2_uuid",
"liblog",
"liblogwrap",
"libprocessgroup",
@@ -239,6 +241,8 @@
cc_binary {
name: "otapreopt",
+
+ cpp_std: "c++2a",
cflags: [
"-Wall",
"-Werror",
@@ -268,6 +272,7 @@
"libbase",
"libcrypto",
"libcutils",
+ "libext2_uuid",
"liblog",
"liblogwrap",
"libprocessgroup",
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index c3256fc..91f7d3b 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -103,11 +103,6 @@
static constexpr const char* CACHE_DIR_POSTFIX = "/cache";
static constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache";
-// fsverity assumes the page size is always 4096. If not, the feature can not be
-// enabled.
-static constexpr int kVerityPageSize = 4096;
-static constexpr size_t kSha256Size = 32;
-static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode";
static constexpr const char* kFuseProp = "persist.sys.fuse";
/**
@@ -261,12 +256,6 @@
} \
}
-#define ASSERT_PAGE_SIZE_4K() { \
- if (getpagesize() != kVerityPageSize) { \
- return error("FSVerity only supports 4K pages"); \
- } \
-}
-
#ifdef GRANULAR_LOCKS
/**
@@ -698,9 +687,6 @@
if (!status.isOk()) {
return status;
}
- if (previousUid != uid) {
- chown_app_profile_dir(packageName, appId, userId);
- }
// Remember inode numbers of cache directories so that we can clear
// contents while CE storage is locked
@@ -726,6 +712,9 @@
if (!status.isOk()) {
return status;
}
+ if (previousUid != uid) {
+ chown_app_profile_dir(packageName, appId, userId);
+ }
if (!prepare_app_profile_dir(packageName, appId, userId)) {
return error("Failed to prepare profiles for " + packageName);
@@ -968,13 +957,13 @@
binder::Status res = ok();
if (flags & FLAG_STORAGE_CE) {
auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
- if (delete_dir_contents_and_dir(path) != 0) {
+ if (rename_delete_dir_contents_and_dir(path) != 0) {
res = error("Failed to delete " + path);
}
}
if (flags & FLAG_STORAGE_DE) {
auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
- if (delete_dir_contents_and_dir(path) != 0) {
+ if (rename_delete_dir_contents_and_dir(path) != 0) {
res = error("Failed to delete " + path);
}
if ((flags & FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
@@ -1008,7 +997,6 @@
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete contents of " + path);
}
-
path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete contents of " + path);
@@ -2959,142 +2947,6 @@
return *_aidl_return == -1 ? error() : ok();
}
-// This kernel feature is experimental.
-// TODO: remove local definition once upstreamed
-#ifndef FS_IOC_ENABLE_VERITY
-
-#define FS_IOC_ENABLE_VERITY _IO('f', 133)
-#define FS_IOC_SET_VERITY_MEASUREMENT _IOW('f', 134, struct fsverity_measurement)
-
-#define FS_VERITY_ALG_SHA256 1
-
-struct fsverity_measurement {
- __u16 digest_algorithm;
- __u16 digest_size;
- __u32 reserved1;
- __u64 reserved2[3];
- __u8 digest[];
-};
-
-#endif
-
-binder::Status InstalldNativeService::installApkVerity(const std::string& filePath,
- android::base::unique_fd verityInputAshmem, int32_t contentSize) {
- ENFORCE_UID(AID_SYSTEM);
- CHECK_ARGUMENT_PATH(filePath);
- LOCK_PACKAGE();
-
- if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
- return ok();
- }
-#ifndef NDEBUG
- ASSERT_PAGE_SIZE_4K();
-#endif
- // TODO: also check fsverity support in the current file system if compiled with DEBUG.
- // TODO: change ashmem to some temporary file to support huge apk.
- if (!ashmem_valid(verityInputAshmem.get())) {
- return error("FD is not an ashmem");
- }
-
- // 1. Seek to the next page boundary beyond the end of the file.
- ::android::base::unique_fd wfd(open(filePath.c_str(), O_WRONLY));
- if (wfd.get() < 0) {
- return error("Failed to open " + filePath);
- }
- struct stat st;
- if (fstat(wfd.get(), &st) < 0) {
- return error("Failed to stat " + filePath);
- }
- // fsverity starts from the block boundary.
- off_t padding = kVerityPageSize - st.st_size % kVerityPageSize;
- if (padding == kVerityPageSize) {
- padding = 0;
- }
- if (lseek(wfd.get(), st.st_size + padding, SEEK_SET) < 0) {
- return error("Failed to lseek " + filePath);
- }
-
- // 2. Write everything in the ashmem to the file. Note that allocated
- // ashmem size is multiple of page size, which is different from the
- // actual content size.
- int shmSize = ashmem_get_size_region(verityInputAshmem.get());
- if (shmSize < 0) {
- return error("Failed to get ashmem size: " + std::to_string(shmSize));
- }
- if (contentSize < 0) {
- return error("Invalid content size: " + std::to_string(contentSize));
- }
- if (contentSize > shmSize) {
- return error("Content size overflow: " + std::to_string(contentSize) + " > " +
- std::to_string(shmSize));
- }
- auto data = std::unique_ptr<void, std::function<void (void *)>>(
- mmap(nullptr, contentSize, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0),
- [contentSize] (void* ptr) {
- if (ptr != MAP_FAILED) {
- munmap(ptr, contentSize);
- }
- });
-
- if (data.get() == MAP_FAILED) {
- return error("Failed to mmap the ashmem");
- }
- char* cursor = reinterpret_cast<char*>(data.get());
- int remaining = contentSize;
- while (remaining > 0) {
- int ret = TEMP_FAILURE_RETRY(write(wfd.get(), cursor, remaining));
- if (ret < 0) {
- return error("Failed to write to " + filePath + " (" + std::to_string(remaining) +
- + "/" + std::to_string(contentSize) + ")");
- }
- cursor += ret;
- remaining -= ret;
- }
- wfd.reset();
-
- // 3. Enable fsverity (needs readonly fd. Once it's done, the file becomes immutable.
- ::android::base::unique_fd rfd(open(filePath.c_str(), O_RDONLY));
- if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, nullptr) < 0) {
- return error("Failed to enable fsverity on " + filePath);
- }
- return ok();
-}
-
-binder::Status InstalldNativeService::assertFsverityRootHashMatches(const std::string& filePath,
- const std::vector<uint8_t>& expectedHash) {
- ENFORCE_UID(AID_SYSTEM);
- CHECK_ARGUMENT_PATH(filePath);
- LOCK_PACKAGE();
-
- if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
- return ok();
- }
- // TODO: also check fsverity support in the current file system if compiled with DEBUG.
- if (expectedHash.size() != kSha256Size) {
- return error("verity hash size should be " + std::to_string(kSha256Size) + " but is " +
- std::to_string(expectedHash.size()));
- }
-
- ::android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY));
- if (fd.get() < 0) {
- return error("Failed to open " + filePath + ": " + strerror(errno));
- }
-
- unsigned int buffer_size = sizeof(fsverity_measurement) + kSha256Size;
- std::vector<char> buffer(buffer_size, 0);
-
- fsverity_measurement* config = reinterpret_cast<fsverity_measurement*>(buffer.data());
- config->digest_algorithm = FS_VERITY_ALG_SHA256;
- config->digest_size = kSha256Size;
- memcpy(config->digest, expectedHash.data(), kSha256Size);
- if (ioctl(fd.get(), FS_IOC_SET_VERITY_MEASUREMENT, config) < 0) {
- // This includes an expected failure case with no FSVerity setup. It normally happens when
- // the apk does not contains the Merkle tree root hash.
- return error("Failed to measure fsverity on " + filePath + ": " + strerror(errno));
- }
- return ok(); // hashes match
-}
-
binder::Status InstalldNativeService::reconcileSecondaryDexFile(
const std::string& dexPath, const std::string& packageName, int32_t uid,
const std::vector<std::string>& isas, const std::optional<std::string>& volumeUuid,
@@ -3324,5 +3176,22 @@
return ok();
}
+binder::Status InstalldNativeService::cleanupInvalidPackageDirs(
+ const std::optional<std::string>& uuid, int32_t userId, int32_t flags) {
+ const char* uuid_cstr = uuid ? uuid->c_str() : nullptr;
+
+ if (flags & FLAG_STORAGE_CE) {
+ auto ce_path = create_data_user_ce_path(uuid_cstr, userId);
+ cleanup_invalid_package_dirs_under_path(ce_path);
+ }
+
+ if (flags & FLAG_STORAGE_DE) {
+ auto de_path = create_data_user_de_path(uuid_cstr, userId);
+ cleanup_invalid_package_dirs_under_path(de_path);
+ }
+
+ return ok();
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 09581bb..96783c3 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -164,10 +164,6 @@
const std::string& outputPath);
binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet,
const std::optional<std::string>& outputPath, int64_t* _aidl_return);
- binder::Status installApkVerity(const std::string& filePath,
- android::base::unique_fd verityInput, int32_t contentSize);
- binder::Status assertFsverityRootHashMatches(const std::string& filePath,
- const std::vector<uint8_t>& expectedHash);
binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
const std::optional<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
@@ -188,6 +184,9 @@
binder::Status migrateLegacyObbData();
+ binder::Status cleanupInvalidPackageDirs(const std::optional<std::string>& uuid, int32_t userId,
+ int32_t flags);
+
private:
std::recursive_mutex mLock;
std::unordered_map<userid_t, std::weak_ptr<std::shared_mutex>> mUserIdLock;
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 637a9f2..f4fd9a9 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -97,9 +97,6 @@
@utf8InCpp String outputPath);
long deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
@nullable @utf8InCpp String outputPath);
- void installApkVerity(@utf8InCpp String filePath, in FileDescriptor verityInput,
- int contentSize);
- void assertFsverityRootHashMatches(@utf8InCpp String filePath, in byte[] expectedHash);
boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
@@ -129,6 +126,8 @@
void migrateLegacyObbData();
+ void cleanupInvalidPackageDirs(@nullable @utf8InCpp String uuid, int userId, int flags);
+
const int FLAG_STORAGE_DE = 0x1;
const int FLAG_STORAGE_CE = 0x2;
const int FLAG_STORAGE_EXTERNAL = 0x4;
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 51f7716..a16587e 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -8,46 +8,47 @@
default_applicable_licenses: ["frameworks_native_license"],
}
-cc_test {
- name: "installd_utils_test",
+cc_defaults {
+ name: "installd_tests_defaults",
test_suites: ["device-tests"],
clang: true,
- srcs: ["installd_utils_test.cpp"],
+ cpp_std: "c++2a",
cflags: [
"-Wall",
"-Werror",
],
shared_libs: [
"libbase",
- "libutils",
"libcutils",
+ "libext2_uuid",
+ "libutils",
],
static_libs: [
+ "liblog",
+ ],
+}
+
+cc_test {
+ name: "installd_utils_test",
+ defaults: ["installd_tests_defaults"],
+ srcs: ["installd_utils_test.cpp"],
+ static_libs: [
"libasync_safe",
"libdiskusage",
"libinstalld",
- "liblog",
],
test_config: "installd_utils_test.xml",
}
cc_test {
name: "installd_cache_test",
- test_suites: ["device-tests"],
- clang: true,
+ defaults: ["installd_tests_defaults"],
srcs: ["installd_cache_test.cpp"],
- cflags: [
- "-Wall",
- "-Werror",
- ],
shared_libs: [
- "libbase",
"libbinder",
"libcrypto",
- "libcutils",
"libprocessgroup",
"libselinux",
- "libutils",
"server_configurable_flags",
],
static_libs: [
@@ -55,7 +56,6 @@
"libdiskusage",
"libinstalld",
"libziparchive",
- "liblog",
"liblogwrap",
],
test_config: "installd_cache_test.xml",
@@ -78,21 +78,13 @@
cc_test {
name: "installd_service_test",
- test_suites: ["device-tests"],
- clang: true,
+ defaults: ["installd_tests_defaults"],
srcs: ["installd_service_test.cpp"],
- cflags: [
- "-Wall",
- "-Werror",
- ],
shared_libs: [
- "libbase",
"libbinder",
"libcrypto",
- "libcutils",
"libprocessgroup",
"libselinux",
- "libutils",
"packagemanager_aidl-cpp",
"server_configurable_flags",
],
@@ -101,7 +93,6 @@
"libdiskusage",
"libinstalld",
"libziparchive",
- "liblog",
"liblogwrap",
],
test_config: "installd_service_test.xml",
@@ -124,28 +115,19 @@
cc_test {
name: "installd_dexopt_test",
- test_suites: ["device-tests"],
- clang: true,
+ defaults: ["installd_tests_defaults"],
srcs: ["installd_dexopt_test.cpp"],
- cflags: [
- "-Wall",
- "-Werror",
- ],
shared_libs: [
- "libbase",
"libbinder",
"libcrypto",
- "libcutils",
"libprocessgroup",
"libselinux",
- "libutils",
"server_configurable_flags",
],
static_libs: [
"libasync_safe",
"libdiskusage",
"libinstalld",
- "liblog",
"liblogwrap",
"libziparchive",
"libz",
@@ -170,41 +152,21 @@
cc_test {
name: "installd_otapreopt_test",
- test_suites: ["device-tests"],
- clang: true,
+ defaults: ["installd_tests_defaults"],
srcs: ["installd_otapreopt_test.cpp"],
- cflags: [
- "-Wall",
- "-Werror",
- ],
shared_libs: [
- "libbase",
- "libcutils",
- "libutils",
"server_configurable_flags",
],
static_libs: [
- "liblog",
"libotapreoptparameters",
],
}
cc_test {
name: "installd_file_test",
- test_suites: ["device-tests"],
- clang: true,
+ defaults: ["installd_tests_defaults"],
srcs: ["installd_file_test.cpp"],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- shared_libs: [
- "libbase",
- "libcutils",
- "libutils",
- ],
static_libs: [
"libinstalld",
- "liblog",
],
}
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index b831515..806797f 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -75,6 +75,7 @@
namespace installd {
constexpr const char* kTestUuid = "TEST";
+constexpr const char* kTestPath = "/data/local/tmp/user/0";
#define FLAG_FORCE InstalldNativeService::FLAG_FORCE
@@ -97,7 +98,7 @@
}
static std::string get_full_path(const char* path) {
- return StringPrintf("/data/local/tmp/user/0/%s", path);
+ return StringPrintf("%s/%s", kTestPath, path);
}
static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
@@ -107,12 +108,16 @@
EXPECT_EQ(::chmod(fullPath.c_str(), mode), 0);
}
-static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
+static int create(const char* path, uid_t owner, gid_t group, mode_t mode) {
int fd = ::open(get_full_path(path).c_str(), O_RDWR | O_CREAT, mode);
EXPECT_NE(fd, -1);
EXPECT_EQ(::fchown(fd, owner, group), 0);
EXPECT_EQ(::fchmod(fd, mode), 0);
- EXPECT_EQ(::close(fd), 0);
+ return fd;
+}
+
+static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
+ EXPECT_EQ(::close(create(path, owner, group, mode)), 0);
}
static int stat_gid(const char* path) {
@@ -127,6 +132,35 @@
return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
}
+static bool exists(const char* path) {
+ return ::access(get_full_path(path).c_str(), F_OK) == 0;
+}
+
+template <class Pred>
+static bool find_file(const char* path, Pred&& pred) {
+ bool result = false;
+ auto d = opendir(path);
+ if (d == nullptr) {
+ return result;
+ }
+ struct dirent* de;
+ while ((de = readdir(d))) {
+ const char* name = de->d_name;
+ if (pred(name, de->d_type == DT_DIR)) {
+ result = true;
+ break;
+ }
+ }
+ closedir(d);
+ return result;
+}
+
+static bool exists_renamed_deleted_dir() {
+ return find_file(kTestPath, [](std::string_view name, bool is_dir) {
+ return is_dir && is_renamed_deleted_dir(name);
+ });
+}
+
class ServiceTest : public testing::Test {
protected:
InstalldNativeService* service;
@@ -193,6 +227,134 @@
EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
}
+TEST_F(ServiceTest, DestroyUserData) {
+ LOG(INFO) << "DestroyUserData";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0700);
+ mkdir("com.example/bar", 10000, 20000, 0700);
+ touch("com.example/bar/file", 10000, 20000, 0700);
+
+ EXPECT_TRUE(exists("com.example/foo"));
+ EXPECT_TRUE(exists("com.example/foo/file"));
+ EXPECT_TRUE(exists("com.example/bar"));
+ EXPECT_TRUE(exists("com.example/bar/file"));
+
+ service->destroyUserData(testUuid, 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE);
+
+ EXPECT_FALSE(exists("com.example/foo"));
+ EXPECT_FALSE(exists("com.example/foo/file"));
+ EXPECT_FALSE(exists("com.example/bar"));
+ EXPECT_FALSE(exists("com.example/bar/file"));
+
+ EXPECT_FALSE(exists_renamed_deleted_dir());
+}
+
+TEST_F(ServiceTest, DestroyAppData) {
+ LOG(INFO) << "DestroyAppData";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0700);
+ mkdir("com.example/bar", 10000, 20000, 0700);
+ touch("com.example/bar/file", 10000, 20000, 0700);
+
+ EXPECT_TRUE(exists("com.example/foo"));
+ EXPECT_TRUE(exists("com.example/foo/file"));
+ EXPECT_TRUE(exists("com.example/bar"));
+ EXPECT_TRUE(exists("com.example/bar/file"));
+
+ service->destroyAppData(testUuid, "com.example", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, 0);
+
+ EXPECT_FALSE(exists("com.example/foo"));
+ EXPECT_FALSE(exists("com.example/foo/file"));
+ EXPECT_FALSE(exists("com.example/bar"));
+ EXPECT_FALSE(exists("com.example/bar/file"));
+
+ EXPECT_FALSE(exists_renamed_deleted_dir());
+}
+
+TEST_F(ServiceTest, CleanupInvalidPackageDirs) {
+ LOG(INFO) << "CleanupInvalidPackageDirs";
+
+ mkdir("5b14b6458a44==deleted==", 10000, 10000, 0700);
+ mkdir("5b14b6458a44==deleted==/foo", 10000, 10000, 0700);
+ touch("5b14b6458a44==deleted==/foo/file", 10000, 20000, 0700);
+ mkdir("5b14b6458a44==deleted==/bar", 10000, 20000, 0700);
+ touch("5b14b6458a44==deleted==/bar/file", 10000, 20000, 0700);
+
+ auto fd = create("5b14b6458a44==deleted==/bar/opened_file", 10000, 20000, 0700);
+
+ mkdir("b14b6458a44NOTdeleted", 10000, 10000, 0700);
+ mkdir("b14b6458a44NOTdeleted/foo", 10000, 10000, 0700);
+ touch("b14b6458a44NOTdeleted/foo/file", 10000, 20000, 0700);
+ mkdir("b14b6458a44NOTdeleted/bar", 10000, 20000, 0700);
+ touch("b14b6458a44NOTdeleted/bar/file", 10000, 20000, 0700);
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0700);
+ mkdir("com.example/bar", 10000, 20000, 0700);
+ touch("com.example/bar/file", 10000, 20000, 0700);
+
+ mkdir("==deleted==", 10000, 10000, 0700);
+ mkdir("==deleted==/foo", 10000, 10000, 0700);
+ touch("==deleted==/foo/file", 10000, 20000, 0700);
+ mkdir("==deleted==/bar", 10000, 20000, 0700);
+ touch("==deleted==/bar/file", 10000, 20000, 0700);
+
+ EXPECT_TRUE(exists("5b14b6458a44==deleted==/foo"));
+ EXPECT_TRUE(exists("5b14b6458a44==deleted==/foo/file"));
+ EXPECT_TRUE(exists("5b14b6458a44==deleted==/bar"));
+ EXPECT_TRUE(exists("5b14b6458a44==deleted==/bar/file"));
+ EXPECT_TRUE(exists("5b14b6458a44==deleted==/bar/opened_file"));
+
+ EXPECT_TRUE(exists("b14b6458a44NOTdeleted/foo"));
+ EXPECT_TRUE(exists("b14b6458a44NOTdeleted/foo/file"));
+ EXPECT_TRUE(exists("b14b6458a44NOTdeleted/bar"));
+ EXPECT_TRUE(exists("b14b6458a44NOTdeleted/bar/file"));
+
+ EXPECT_TRUE(exists("com.example/foo"));
+ EXPECT_TRUE(exists("com.example/foo/file"));
+ EXPECT_TRUE(exists("com.example/bar"));
+ EXPECT_TRUE(exists("com.example/bar/file"));
+
+ EXPECT_TRUE(exists("==deleted==/foo"));
+ EXPECT_TRUE(exists("==deleted==/foo/file"));
+ EXPECT_TRUE(exists("==deleted==/bar"));
+ EXPECT_TRUE(exists("==deleted==/bar/file"));
+
+ EXPECT_TRUE(exists_renamed_deleted_dir());
+
+ service->cleanupInvalidPackageDirs(testUuid, 0, FLAG_STORAGE_CE | FLAG_STORAGE_DE);
+
+ EXPECT_EQ(::close(fd), 0);
+
+ EXPECT_FALSE(exists("5b14b6458a44==deleted==/foo"));
+ EXPECT_FALSE(exists("5b14b6458a44==deleted==/foo/file"));
+ EXPECT_FALSE(exists("5b14b6458a44==deleted==/bar"));
+ EXPECT_FALSE(exists("5b14b6458a44==deleted==/bar/file"));
+ EXPECT_FALSE(exists("5b14b6458a44==deleted==/bar/opened_file"));
+
+ EXPECT_TRUE(exists("b14b6458a44NOTdeleted/foo"));
+ EXPECT_TRUE(exists("b14b6458a44NOTdeleted/foo/file"));
+ EXPECT_TRUE(exists("b14b6458a44NOTdeleted/bar"));
+ EXPECT_TRUE(exists("b14b6458a44NOTdeleted/bar/file"));
+
+ EXPECT_TRUE(exists("com.example/foo"));
+ EXPECT_TRUE(exists("com.example/foo/file"));
+ EXPECT_TRUE(exists("com.example/bar"));
+ EXPECT_TRUE(exists("com.example/bar/file"));
+
+ EXPECT_FALSE(exists("==deleted==/foo"));
+ EXPECT_FALSE(exists("==deleted==/foo/file"));
+ EXPECT_FALSE(exists("==deleted==/bar"));
+ EXPECT_FALSE(exists("==deleted==/bar/file"));
+
+ EXPECT_FALSE(exists_renamed_deleted_dir());
+}
+
TEST_F(ServiceTest, HashSecondaryDex) {
LOG(INFO) << "HashSecondaryDex";
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 0f8a732..8a00be9 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -22,9 +22,10 @@
#include <stdlib.h>
#include <sys/capability.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <sys/wait.h>
#include <sys/xattr.h>
-#include <sys/statvfs.h>
+#include <uuid/uuid.h>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -47,6 +48,7 @@
#define DEBUG_XATTRS 0
+using android::base::Dirname;
using android::base::EndsWith;
using android::base::Fdopendir;
using android::base::StringPrintf;
@@ -55,6 +57,10 @@
namespace android {
namespace installd {
+using namespace std::literals;
+
+static constexpr auto deletedSuffix = "==deleted=="sv;
+
/**
* Check that given string is valid filename, and that it attempts no
* parent or child directory traversal.
@@ -595,6 +601,93 @@
return res;
}
+static std::string make_unique_name(std::string_view suffix) {
+ static constexpr auto uuidStringSize = 36;
+
+ uuid_t guid;
+ uuid_generate(guid);
+
+ std::string name;
+ const auto suffixSize = suffix.size();
+ name.reserve(uuidStringSize + suffixSize);
+
+ name.resize(uuidStringSize);
+ uuid_unparse(guid, name.data());
+ name.append(suffix);
+
+ return name;
+}
+
+static int rename_delete_dir_contents(const std::string& pathname,
+ int (*exclusion_predicate)(const char*, const int),
+ bool ignore_if_missing) {
+ auto temp_dir_name = make_unique_name(deletedSuffix);
+ auto temp_dir_path =
+ base::StringPrintf("%s/%s", Dirname(pathname).c_str(), temp_dir_name.c_str());
+
+ if (::rename(pathname.c_str(), temp_dir_path.c_str())) {
+ if (ignore_if_missing && (errno == ENOENT)) {
+ return 0;
+ }
+ ALOGE("Couldn't rename %s -> %s: %s \n", pathname.c_str(), temp_dir_path.c_str(),
+ strerror(errno));
+ return -errno;
+ }
+
+ return delete_dir_contents(temp_dir_path.c_str(), 1, exclusion_predicate, ignore_if_missing);
+}
+
+bool is_renamed_deleted_dir(std::string_view path) {
+ return path.ends_with(deletedSuffix);
+}
+
+int rename_delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) {
+ return rename_delete_dir_contents(pathname, nullptr, ignore_if_missing);
+}
+
+static auto open_dir(const char* dir) {
+ struct DirCloser {
+ void operator()(DIR* d) const noexcept { ::closedir(d); }
+ };
+ return std::unique_ptr<DIR, DirCloser>(::opendir(dir));
+}
+
+void cleanup_invalid_package_dirs_under_path(const std::string& pathname) {
+ auto dir = open_dir(pathname.c_str());
+ if (!dir) {
+ return;
+ }
+ int dfd = dirfd(dir.get());
+ if (dfd < 0) {
+ ALOGE("Couldn't dirfd %s: %s\n", pathname.c_str(), strerror(errno));
+ return;
+ }
+
+ struct dirent* de;
+ while ((de = readdir(dir.get()))) {
+ if (de->d_type != DT_DIR) {
+ continue;
+ }
+
+ std::string name{de->d_name};
+ // always skip "." and ".."
+ if (name == "." || name == "..") {
+ continue;
+ }
+
+ if (is_renamed_deleted_dir(name) || !is_valid_filename(name) ||
+ !is_valid_package_name(name)) {
+ ALOGI("Deleting renamed or invalid data directory: %s\n", name.c_str());
+ // Deleting the content.
+ delete_dir_contents_fd(dfd, name.c_str());
+ // Deleting the directory
+ if (unlinkat(dfd, name.c_str(), AT_REMOVEDIR) < 0) {
+ ALOGE("Couldn't unlinkat %s: %s\n", name.c_str(), strerror(errno));
+ }
+ }
+ }
+}
+
int delete_dir_contents_fd(int dfd, const char *name)
{
int fd, res;
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 549fc6c..04f3bc9 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -120,6 +120,11 @@
int delete_dir_contents(const std::string& pathname, bool ignore_if_missing = false);
int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing = false);
+bool is_renamed_deleted_dir(std::string_view path);
+int rename_delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing = true);
+
+void cleanup_invalid_package_dirs_under_path(const std::string& pathname);
+
int delete_dir_contents(const char *pathname,
int also_delete_dir,
int (*exclusion_predicate)(const char *name, const int is_dir),
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 269b086..1821729 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -368,7 +368,7 @@
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
pid_t pid = getpid();
String8 name;
- name.appendFormat("Binder:%d_%X", pid, s);
+ name.appendFormat("%d_%X:%s", pid, s, mDriverName.c_str());
return name;
}
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index 4f63194..79cc15f 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -13,12 +13,13 @@
shared_libs: [
"libbase",
"libbpf_bcc",
- "libbpf_android",
"libbpf_minimal",
"liblog",
- "libnetdutils"
],
- header_libs: ["bpf_prog_headers"],
+ header_libs: [
+ "bpf_prog_headers",
+ "bpf_headers",
+ ],
cflags: [
"-Werror",
"-Wall",
@@ -33,12 +34,13 @@
shared_libs: [
"libbase",
"libbpf_bcc",
- "libbpf_android",
"libbpf_minimal",
"libtimeinstate",
- "libnetdutils",
],
- header_libs: ["bpf_prog_headers"],
+ header_libs: [
+ "bpf_prog_headers",
+ "bpf_headers",
+ ],
cflags: [
"-Werror",
"-Wall",
diff --git a/libs/gralloc/OWNERS b/libs/gralloc/OWNERS
index 93879d8..72ff978 100644
--- a/libs/gralloc/OWNERS
+++ b/libs/gralloc/OWNERS
@@ -1 +1,4 @@
+# Graphics team
+alecmouri@google.com
chrisforbes@google.com
+jreck@google.com
\ No newline at end of file
diff --git a/libs/gralloc/types/Gralloc4.cpp b/libs/gralloc/types/Gralloc4.cpp
index e2f072a..81a529d 100644
--- a/libs/gralloc/types/Gralloc4.cpp
+++ b/libs/gralloc/types/Gralloc4.cpp
@@ -196,6 +196,35 @@
status_t validateMetadataType(InputHidlVec* input, const MetadataType& expectedMetadataType);
/**
+ * Private helper functions
+ */
+template <class T>
+status_t encodeInteger(const T& input, OutputHidlVec* output) {
+ static_assert(std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
+ std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
+ std::is_same<T, float>::value || std::is_same<T, double>::value);
+ if (!output) {
+ return BAD_VALUE;
+ }
+
+ const uint8_t* tmp = reinterpret_cast<const uint8_t*>(&input);
+ return output->encode(tmp, sizeof(input));
+}
+
+template <class T>
+status_t decodeInteger(InputHidlVec* input, T* output) {
+ static_assert(std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
+ std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
+ std::is_same<T, float>::value || std::is_same<T, double>::value);
+ if (!output) {
+ return BAD_VALUE;
+ }
+
+ uint8_t* tmp = reinterpret_cast<uint8_t*>(output);
+ return input->decode(tmp, sizeof(*output));
+}
+
+/**
* encode/encodeMetadata are the main encoding functions. They take in T and uses the encodeHelper
* function to turn T into the hidl_vec byte stream.
*
@@ -251,10 +280,45 @@
template <class T>
status_t encodeOptionalMetadata(const MetadataType& metadataType, const std::optional<T>& input,
hidl_vec<uint8_t>* output, EncodeHelper<T> encodeHelper) {
- if (!input) {
- return NO_ERROR;
+ OutputHidlVec outputHidlVec{output};
+
+ status_t err = encodeMetadataType(metadataType, &outputHidlVec);
+ if (err) {
+ return err;
}
- return encodeMetadata(metadataType, *input, output, encodeHelper);
+
+ err = encodeInteger<uint32_t>(input.has_value() ? 1 : 0, &outputHidlVec);
+ if (err) {
+ return err;
+ }
+
+ if (input) {
+ err = encodeHelper(*input, &outputHidlVec);
+ if (err) {
+ return err;
+ }
+ }
+
+ err = outputHidlVec.resize();
+ if (err) {
+ return err;
+ }
+
+ err = encodeMetadataType(metadataType, &outputHidlVec);
+ if (err) {
+ return err;
+ }
+
+ err = encodeInteger<uint32_t>(input.has_value() ? 1 : 0, &outputHidlVec);
+ if (err) {
+ return err;
+ }
+
+ if (input) {
+ return encodeHelper(*input, &outputHidlVec);
+ }
+
+ return NO_ERROR;
}
/**
@@ -315,45 +379,36 @@
if (!output) {
return BAD_VALUE;
}
- if (input.size() <= 0) {
- output->reset();
- return NO_ERROR;
+
+ InputHidlVec inputHidlVec{&input};
+
+ status_t err = validateMetadataType(&inputHidlVec, metadataType);
+ if (err) {
+ return err;
}
- T tmp;
- status_t err = decodeMetadata(metadataType, input, &tmp, decodeHelper);
- if (!err) {
+
+ uint32_t present = 0;
+ err = decodeInteger<uint32_t>(&inputHidlVec, &present);
+ if (err) {
+ return err;
+ }
+
+ if (present) {
+ T tmp;
+ err = decodeHelper(&inputHidlVec, &tmp);
+ if (err) {
+ return err;
+ }
+
*output = tmp;
}
- return err;
-}
-/**
- * Private helper functions
- */
-template <class T>
-status_t encodeInteger(const T& input, OutputHidlVec* output) {
- static_assert(std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
- std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
- std::is_same<T, float>::value || std::is_same<T, double>::value);
- if (!output) {
+ err = inputHidlVec.hasRemainingData();
+ if (err) {
return BAD_VALUE;
}
- const uint8_t* tmp = reinterpret_cast<const uint8_t*>(&input);
- return output->encode(tmp, sizeof(input));
-}
-
-template <class T>
-status_t decodeInteger(InputHidlVec* input, T* output) {
- static_assert(std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
- std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
- std::is_same<T, float>::value || std::is_same<T, double>::value);
- if (!output) {
- return BAD_VALUE;
- }
-
- uint8_t* tmp = reinterpret_cast<uint8_t*>(output);
- return input->decode(tmp, sizeof(*output));
+ return NO_ERROR;
}
status_t encodeString(const std::string& input, OutputHidlVec* output) {
diff --git a/services/gpuservice/gpumem/Android.bp b/services/gpuservice/gpumem/Android.bp
index 24087ac..d0ea856 100644
--- a/services/gpuservice/gpumem/Android.bp
+++ b/services/gpuservice/gpumem/Android.bp
@@ -26,19 +26,17 @@
srcs: [
"GpuMem.cpp",
],
+ header_libs: ["bpf_headers"],
shared_libs: [
"libbase",
"libbpf_bcc",
- "libbpf_android",
"libcutils",
"liblog",
"libutils",
],
export_include_dirs: ["include"],
- export_shared_lib_headers: [
- "libbase",
- "libbpf_android",
- ],
+ export_header_lib_headers: ["bpf_headers"],
+ export_shared_lib_headers: ["libbase"],
cppflags: [
"-Wall",
"-Werror",
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 5b69f96..4fb0d2e 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -32,10 +32,10 @@
"GpuMemTracerTest.cpp",
"GpuStatsTest.cpp",
],
+ header_libs: ["bpf_headers"],
shared_libs: [
"libbase",
"libbpf_bcc",
- "libbpf_android",
"libcutils",
"libgfxstats",
"libgpumem",