diff options
| author | 2023-08-25 12:59:08 -0700 | |
|---|---|---|
| committer | 2023-08-25 12:59:08 -0700 | |
| commit | 7d3ffbae618e9e728644a96647ed709bf39ae759 (patch) | |
| tree | ab369a30c6a0e17a69c8f80c6353be4de3692e10 /libs/androidfw/ApkParsing.cpp | |
| parent | a8a87bbca9162af7add830139198c4ee899fa123 (diff) | |
| parent | 8a809c6e46007521f75ac035ad4b1dcc1d00d9cf (diff) | |
Merge Android U (ab/10368041)
Bug: 291102124
Merged-In: I3c9e9d15786fbead1b874636b46844f6c24bccc2
Change-Id: Id6cf6cc13baef4e67486c6271a1510146204affa
Diffstat (limited to 'libs/androidfw/ApkParsing.cpp')
| -rw-r--r-- | libs/androidfw/ApkParsing.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/libs/androidfw/ApkParsing.cpp b/libs/androidfw/ApkParsing.cpp new file mode 100644 index 000000000000..32d2c5b05acb --- /dev/null +++ b/libs/androidfw/ApkParsing.cpp @@ -0,0 +1,110 @@ +/* + * 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 <algorithm> +#include <array> +#include <stdlib.h> +#include <string_view> +#include <sys/types.h> + +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<std::string_view, 2> 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 by checking if the next / after lib/ is the last slash + if (memchr(fileName + APK_LIB_LEN, '/', fileNameLen - APK_LIB_LEN) != lastSlash) { + 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 |