From fd88ff2edd954117e36372fb095b6f5f35aad0e3 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Fri, 15 Aug 2014 15:45:51 +0100 Subject: [PATCH] Allow apk path to contain one subdirectory. In the current directory layout this prevented rm_dex and move_dex commands to validate the apk path and thus cleaning up resources. Bug: 16888084 Change-Id: Iba579d075a9c6d7de047e7ffef95441498257086 --- cmds/installd/tests/installd_utils_test.cpp | 24 ++++++++++++----- cmds/installd/utils.c | 29 +++++++-------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp index 0b182afda..eeafa1043 100644 --- a/cmds/installd/tests/installd_utils_test.cpp +++ b/cmds/installd/tests/installd_utils_test.cpp @@ -101,6 +101,11 @@ TEST_F(UtilsTest, IsValidApkPath_Internal) { EXPECT_EQ(0, validate_apk_path(internal1)) << internal1 << " should be allowed as a valid path"; + // b/16888084 + const char *path2 = TEST_APP_DIR "example.com/example.apk"; + EXPECT_EQ(0, validate_apk_path(path2)) + << path2 << " should be allowed as a valid path"; + const char *badint1 = TEST_APP_DIR "../example.apk"; EXPECT_EQ(-1, validate_apk_path(badint1)) << badint1 << " should be rejected as a invalid path"; @@ -109,9 +114,10 @@ TEST_F(UtilsTest, IsValidApkPath_Internal) { EXPECT_EQ(-1, validate_apk_path(badint2)) << badint2 << " should be rejected as a invalid path"; - const char *badint3 = TEST_APP_DIR "example.com/pkg.apk"; - EXPECT_EQ(-1, validate_apk_path(badint3)) - << badint3 << " should be rejected as a invalid path"; + // Only one subdir should be allowed. + const char *bad_path3 = TEST_APP_DIR "example.com/subdir/pkg.apk"; + EXPECT_EQ(-1, validate_apk_path(bad_path3)) + << bad_path3 << " should be rejected as a invalid path"; } TEST_F(UtilsTest, IsValidApkPath_Private) { @@ -120,6 +126,11 @@ TEST_F(UtilsTest, IsValidApkPath_Private) { EXPECT_EQ(0, validate_apk_path(private1)) << private1 << " should be allowed as a valid path"; + // b/16888084 + const char *path2 = TEST_APP_DIR "example.com/example.apk"; + EXPECT_EQ(0, validate_apk_path(path2)) + << path2 << " should be allowed as a valid path"; + const char *badpriv1 = TEST_APP_PRIVATE_DIR "../example.apk"; EXPECT_EQ(-1, validate_apk_path(badpriv1)) << badpriv1 << " should be rejected as a invalid path"; @@ -128,9 +139,10 @@ TEST_F(UtilsTest, IsValidApkPath_Private) { EXPECT_EQ(-1, validate_apk_path(badpriv2)) << badpriv2 << " should be rejected as a invalid path"; - const char *badpriv3 = TEST_APP_PRIVATE_DIR "example.com/pkg.apk"; - EXPECT_EQ(-1, validate_apk_path(badpriv3)) - << badpriv3 << " should be rejected as a invalid path"; + // Only one subdir should be allowed. + const char *bad_path3 = TEST_APP_PRIVATE_DIR "example.com/subdir/pkg.apk"; + EXPECT_EQ(-1, validate_apk_path(bad_path3)) + << bad_path3 << " should be rejected as a invalid path"; } diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c index 35172def8..def2fc7fe 100644 --- a/cmds/installd/utils.c +++ b/cmds/installd/utils.c @@ -914,16 +914,13 @@ int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { } /** - * Check whether path points to a valid path for an APK file. An ASEC - * directory is allowed to have one level of subdirectory names. Returns -1 - * when an invalid path is encountered and 0 when a valid path is encountered. + * Check whether path points to a valid path for an APK file. Only one level of + * subdirectory names is allowed. Returns -1 when an invalid path is encountered + * and 0 when a valid path is encountered. */ int validate_apk_path(const char *path) { - int allowsubdir = 0; - char *subdir = NULL; size_t dir_len; - size_t path_len; if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { dir_len = android_app_dir.len; @@ -931,32 +928,24 @@ int validate_apk_path(const char *path) dir_len = android_app_private_dir.len; } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) { dir_len = android_asec_dir.len; - allowsubdir = 1; } else { ALOGE("invalid apk path '%s' (bad prefix)\n", path); return -1; } - path_len = strlen(path); + const char* subdir = strchr(path + dir_len, '/'); - /* - * Only allow the path to have a subdirectory if it's been marked as being allowed. - */ - if ((subdir = strchr(path + dir_len, '/')) != NULL) { + // Only allow the path to have at most one subdirectory. + if (subdir != NULL) { ++subdir; - if (!allowsubdir - || (path_len > (size_t) (subdir - path) && (strchr(subdir, '/') != NULL))) { + if (strchr(subdir, '/') != NULL) { ALOGE("invalid apk path '%s' (subdir?)\n", path); return -1; } } - /* - * Directories can't have a period directly after the directory markers - * to prevent ".." - */ - if (path[dir_len] == '.' - || (subdir != NULL && ((*subdir == '.') || (strchr(subdir, '/') != NULL)))) { + // Directories can't have a period directly after the directory markers to prevent "..". + if ((path[dir_len] == '.') || ((subdir != NULL) && (*subdir == '.'))) { ALOGE("invalid apk path '%s' (trickery)\n", path); return -1; }