From 5fd34eabbd37092077ba083eefa2c42c3ce93c5a Mon Sep 17 00:00:00 2001 From: Jeremy Meyer Date: Thu, 15 Dec 2022 18:43:36 +0000 Subject: Have aapt2 check library names the same as package manager Bug: 231297692 Test: Manual Change-Id: I11a660969443aa90cf6b51a0947accca4231310f --- libs/androidfw/ApkParsing.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 libs/androidfw/ApkParsing.cpp (limited to 'libs/androidfw/ApkParsing.cpp') diff --git a/libs/androidfw/ApkParsing.cpp b/libs/androidfw/ApkParsing.cpp new file mode 100644 index 000000000000..cf4fbb9b8462 --- /dev/null +++ b/libs/androidfw/ApkParsing.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "androidfw/ApkParsing.h" +#include +#include +#include +#include +#include + +const std::string_view APK_LIB = "lib/"; +const size_t APK_LIB_LEN = APK_LIB.size(); + +const std::string_view LIB_PREFIX = "/lib"; +const size_t LIB_PREFIX_LEN = LIB_PREFIX.size(); + +const std::string_view LIB_SUFFIX = ".so"; +const size_t LIB_SUFFIX_LEN = LIB_SUFFIX.size(); + +static const std::array abis = {"arm64-v8a", "x86_64"}; + +namespace android::util { +const char* ValidLibraryPathLastSlash(const char* fileName, bool suppress64Bit, bool debuggable) { + // Make sure the filename is at least to the minimum library name size. + const size_t fileNameLen = strlen(fileName); + static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN; + if (fileNameLen < minLength) { + return nullptr; + } + + const char* lastSlash = strrchr(fileName, '/'); + if (!lastSlash) { + return nullptr; + } + + // Skip directories. + if (*(lastSlash + 1) == 0) { + return nullptr; + } + + // Make sure the filename is safe. + if (!isFilenameSafe(lastSlash + 1)) { + return nullptr; + } + + // Make sure there aren't subdirectories + const char* abiOffset = fileName + APK_LIB_LEN; + const size_t abiSize = lastSlash - abiOffset; + if (memchr(abiOffset, '/', abiSize)) { + return nullptr; + } + + if (!debuggable) { + // Make sure the filename starts with lib and ends with ".so". + if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX.data(), LIB_SUFFIX_LEN) != 0 + || strncmp(lastSlash, LIB_PREFIX.data(), LIB_PREFIX_LEN) != 0) { + return nullptr; + } + } + + // Don't include 64 bit versions if they are suppressed + if (suppress64Bit && std::find(abis.begin(), abis.end(), std::string_view( + fileName + APK_LIB_LEN, lastSlash - fileName - APK_LIB_LEN)) != abis.end()) { + return nullptr; + } + + return lastSlash; +} + +bool isFilenameSafe(const char* filename) { + off_t offset = 0; + for (;;) { + switch (*(filename + offset)) { + case 0: + // Null. + // If we've reached the end, all the other characters are good. + return true; + + case 'A' ... 'Z': + case 'a' ... 'z': + case '0' ... '9': + case '+': + case ',': + case '-': + case '.': + case '/': + case '=': + case '_': + offset++; + break; + + default: + // We found something that is not good. + return false; + } + } + // Should not reach here. +} +} \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 12312e073546b1dab9ee80c7ab28a4c55c3102a8 Mon Sep 17 00:00:00 2001 From: Jeremy Meyer Date: Tue, 14 Feb 2023 00:21:19 +0000 Subject: Fix checking for subdirs when parsing apks This fixes the check for subdirectories in lib paths. The old check caused a crash. Test: Automated Fixes: 268582810 Change-Id: I520f1fd6772b11821e7c5c97bd51b45b603f5a7b --- libs/androidfw/ApkParsing.cpp | 6 ++---- libs/androidfw/tests/ApkParsing_test.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'libs/androidfw/ApkParsing.cpp') diff --git a/libs/androidfw/ApkParsing.cpp b/libs/androidfw/ApkParsing.cpp index cf4fbb9b8462..32d2c5b05acb 100644 --- a/libs/androidfw/ApkParsing.cpp +++ b/libs/androidfw/ApkParsing.cpp @@ -56,10 +56,8 @@ const char* ValidLibraryPathLastSlash(const char* fileName, bool suppress64Bit, return nullptr; } - // Make sure there aren't subdirectories - const char* abiOffset = fileName + APK_LIB_LEN; - const size_t abiSize = lastSlash - abiOffset; - if (memchr(abiOffset, '/', abiSize)) { + // Make sure there aren't subdirectories by checking if the next / after lib/ is the last slash + if (memchr(fileName + APK_LIB_LEN, '/', fileNameLen - APK_LIB_LEN) != lastSlash) { return nullptr; } diff --git a/libs/androidfw/tests/ApkParsing_test.cpp b/libs/androidfw/tests/ApkParsing_test.cpp index 4aab0a146ecf..62e88c619e5c 100644 --- a/libs/androidfw/tests/ApkParsing_test.cpp +++ b/libs/androidfw/tests/ApkParsing_test.cpp @@ -68,4 +68,10 @@ TEST(ApkParsingTest, InvalidSubdirectories) { auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); ASSERT_THAT(lastSlash, IsNull()); } + +TEST(ApkParsingTest, InvalidFileAtRoot) { + const char* path = "lib/library.so"; + auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); + ASSERT_THAT(lastSlash, IsNull()); +} } \ No newline at end of file -- cgit v1.2.3-59-g8ed1b