Check /mnt/expand paths as if /data.
The layout of adopted storage devices is identical to the internal
userdata partition, so we should re-use the same logic to determine
if a given path is legitimate.
Bug: 77654971
Test: adb shell /data/nativetest64/installd_utils_test/installd_utils_test
Change-Id: I856788a8e9910f618a4f259a20a264e14b46e079
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index bbff6fb..bcdd03e 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -33,7 +33,7 @@
#define TEST_APP_PRIVATE_DIR "/data/app-private/"
#define TEST_APP_EPHEMERAL_DIR "/data/app-ephemeral/"
#define TEST_ASEC_DIR "/mnt/asec/"
-#define TEST_EXPAND_DIR "/mnt/expand/"
+#define TEST_EXPAND_DIR "/mnt/expand/00000000-0000-0000-0000-000000000000/"
#define TEST_SYSTEM_DIR1 "/system/app/"
#define TEST_SYSTEM_DIR2 "/vendor/app/"
@@ -116,6 +116,41 @@
<< bad_path5 << " should be rejected as a invalid path";
}
+TEST_F(UtilsTest, IsValidApkPath_TopDir) {
+ EXPECT_EQ(0, validate_apk_path(TEST_DATA_DIR "app/com.example"));
+ EXPECT_EQ(0, validate_apk_path(TEST_EXPAND_DIR "app/com.example"));
+ EXPECT_EQ(-1, validate_apk_path(TEST_DATA_DIR "data/com.example"));
+ EXPECT_EQ(-1, validate_apk_path(TEST_EXPAND_DIR "data/com.example"));
+}
+
+TEST_F(UtilsTest, IsValidApkPath_TopFile) {
+ EXPECT_EQ(0, validate_apk_path(TEST_DATA_DIR "app/com.example/base.apk"));
+ EXPECT_EQ(0, validate_apk_path(TEST_EXPAND_DIR "app/com.example/base.apk"));
+ EXPECT_EQ(-1, validate_apk_path(TEST_DATA_DIR "data/com.example/base.apk"));
+ EXPECT_EQ(-1, validate_apk_path(TEST_EXPAND_DIR "data/com.example/base.apk"));
+}
+
+TEST_F(UtilsTest, IsValidApkPath_OatDir) {
+ EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat"));
+ EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat"));
+ EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat"));
+ EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat"));
+}
+
+TEST_F(UtilsTest, IsValidApkPath_OatDirDir) {
+ EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat/arm64"));
+ EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat/arm64"));
+ EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat/arm64"));
+ EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat/arm64"));
+}
+
+TEST_F(UtilsTest, IsValidApkPath_OatDirDirFile) {
+ EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat/arm64/base.odex"));
+ EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat/arm64/base.odex"));
+ EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat/arm64/base.odex"));
+ EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat/arm64/base.odex"));
+}
+
TEST_F(UtilsTest, IsValidApkPath_Private) {
// Internal directories
const char *private1 = TEST_APP_PRIVATE_DIR "example.apk";
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index a8c32ed..1ff45e4 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -855,21 +855,25 @@
* that path. Returns -1 when an invalid path is encountered and 0 when a valid path
* is encountered.
*/
-static int validate_apk_path_internal(const char *path, int maxSubdirs) {
- std::string path_ = path;
- if (validate_path(android_app_dir, path_, maxSubdirs) == 0) {
+static int validate_apk_path_internal(const std::string& path, int maxSubdirs) {
+ if (validate_path(android_app_dir, path, maxSubdirs) == 0) {
return 0;
- } else if (validate_path(android_app_private_dir, path_, maxSubdirs) == 0) {
+ } else if (validate_path(android_app_private_dir, path, maxSubdirs) == 0) {
return 0;
- } else if (validate_path(android_app_ephemeral_dir, path_, maxSubdirs) == 0) {
+ } else if (validate_path(android_app_ephemeral_dir, path, maxSubdirs) == 0) {
return 0;
- } else if (validate_path(android_asec_dir, path_, maxSubdirs) == 0) {
+ } else if (validate_path(android_asec_dir, path, maxSubdirs) == 0) {
return 0;
- } else if (validate_path(android_mnt_expand_dir, path_, std::max(maxSubdirs, 2)) == 0) {
- return 0;
- } else {
- return -1;
+ } else if (android::base::StartsWith(path, android_mnt_expand_dir)) {
+ // Rewrite the path as if it were on internal storage, and test that
+ size_t end = path.find('/', android_mnt_expand_dir.size() + 1);
+ if (end != std::string::npos) {
+ auto modified = path;
+ modified.replace(0, end + 1, android_data_dir);
+ return validate_apk_path_internal(modified, maxSubdirs);
+ }
}
+ return -1;
}
int validate_apk_path(const char* path) {