diff options
| -rw-r--r-- | Android.mk | 2 | ||||
| -rw-r--r-- | libdexfile/dex/hidden_api_access_flags.h | 4 | ||||
| -rw-r--r-- | tools/veridex/Android.mk | 1 | ||||
| -rwxr-xr-x | tools/veridex/appcompat.sh | 3 | ||||
| -rw-r--r-- | tools/veridex/hidden_api.h | 17 | ||||
| -rw-r--r-- | tools/veridex/hidden_api_finder.cc | 12 | ||||
| -rw-r--r-- | tools/veridex/precise_hidden_api_finder.cc | 2 | ||||
| -rw-r--r-- | tools/veridex/veridex.cc | 47 |
8 files changed, 63 insertions, 25 deletions
diff --git a/Android.mk b/Android.mk index 7852be519f..0c20973edc 100644 --- a/Android.mk +++ b/Android.mk @@ -427,7 +427,7 @@ endif define build-art-hiddenapi $(shell if [ ! -d frameworks/base ]; then \ mkdir -p ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING; \ - touch ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING/hiddenapi-{blacklist,dark-greylist,light-greylist}.txt; \ + touch ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING/hiddenapi-{whitelist,blacklist,dark-greylist,light-greylist}.txt; \ fi;) endef diff --git a/libdexfile/dex/hidden_api_access_flags.h b/libdexfile/dex/hidden_api_access_flags.h index 1aaeabd783..369615d678 100644 --- a/libdexfile/dex/hidden_api_access_flags.h +++ b/libdexfile/dex/hidden_api_access_flags.h @@ -62,6 +62,7 @@ class HiddenApiAccessFlags { kLightGreylist, kDarkGreylist, kBlacklist, + kNoList, }; static ALWAYS_INLINE ApiList DecodeFromDex(uint32_t dex_access_flags) { @@ -159,6 +160,9 @@ inline std::ostream& operator<<(std::ostream& os, HiddenApiAccessFlags::ApiList case HiddenApiAccessFlags::kBlacklist: os << "blacklist"; break; + case HiddenApiAccessFlags::kNoList: + os << "no list"; + break; } return os; } diff --git a/tools/veridex/Android.mk b/tools/veridex/Android.mk index 2faa577262..99ced7be2c 100644 --- a/tools/veridex/Android.mk +++ b/tools/veridex/Android.mk @@ -31,6 +31,7 @@ $(oahl_stub_dex): $(call get-prebuilt-sdk-dir,current)/org.apache.http.legacy.ja $(transform-classes.jar-to-dex) app_compat_lists := \ + $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST) \ $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \ $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) diff --git a/tools/veridex/appcompat.sh b/tools/veridex/appcompat.sh index e7b735d30b..9a24d82c9b 100755 --- a/tools/veridex/appcompat.sh +++ b/tools/veridex/appcompat.sh @@ -22,6 +22,7 @@ echo "that do not exist. It can also miss on reflection uses." SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" if [[ -e ${SCRIPT_DIR}/veridex && \ + -e ${SCRIPT_DIR}/hiddenapi-whitelist.txt && \ -e ${SCRIPT_DIR}/hiddenapi-blacklist.txt && \ -e ${SCRIPT_DIR}/hiddenapi-light-greylist.txt && \ -e ${SCRIPT_DIR}/hiddenapi-dark-greylist.txt && \ @@ -29,6 +30,7 @@ if [[ -e ${SCRIPT_DIR}/veridex && \ -e ${SCRIPT_DIR}/system-stubs.zip ]]; then exec ${SCRIPT_DIR}/veridex \ --core-stubs=${SCRIPT_DIR}/system-stubs.zip:${SCRIPT_DIR}/org.apache.http.legacy-stubs.zip \ + --whitelist=${SCRIPT_DIR}/hiddenapi-whitelist.txt \ --blacklist=${SCRIPT_DIR}/hiddenapi-blacklist.txt \ --light-greylist=${SCRIPT_DIR}/hiddenapi-light-greylist.txt \ --dark-greylist=${SCRIPT_DIR}/hiddenapi-dark-greylist.txt \ @@ -62,6 +64,7 @@ fi ${ANDROID_HOST_OUT}/bin/veridex \ --core-stubs=${PACKAGING}/core_dex_intermediates/classes.dex:${PACKAGING}/oahl_dex_intermediates/classes.dex \ + --whitelist=${PACKAGING}/hiddenapi-whitelist.txt \ --blacklist=${PACKAGING}/hiddenapi-blacklist.txt \ --light-greylist=${PACKAGING}/hiddenapi-light-greylist.txt \ --dark-greylist=${PACKAGING}/hiddenapi-dark-greylist.txt \ diff --git a/tools/veridex/hidden_api.h b/tools/veridex/hidden_api.h index b1c8559374..68485bdbd5 100644 --- a/tools/veridex/hidden_api.h +++ b/tools/veridex/hidden_api.h @@ -33,10 +33,14 @@ class DexFile; */ class HiddenApi { public: - HiddenApi(const char* blacklist, const char* dark_greylist, const char* light_greylist) { + HiddenApi(const char* whitelist, + const char* blacklist, + const char* dark_greylist, + const char* light_greylist) { FillList(light_greylist, light_greylist_); FillList(dark_greylist, dark_greylist_); FillList(blacklist, blacklist_); + FillList(whitelist, whitelist_); } HiddenApiAccessFlags::ApiList GetApiList(const std::string& name) const { @@ -46,13 +50,15 @@ class HiddenApi { return HiddenApiAccessFlags::kDarkGreylist; } else if (IsInList(name, light_greylist_)) { return HiddenApiAccessFlags::kLightGreylist; - } else { + } else if (IsInList(name, whitelist_)) { return HiddenApiAccessFlags::kWhitelist; + } else { + return HiddenApiAccessFlags::kNoList; } } - bool IsInRestrictionList(const std::string& name) const { - return GetApiList(name) != HiddenApiAccessFlags::kWhitelist; + bool IsInAnyList(const std::string& name) const { + return GetApiList(name) != HiddenApiAccessFlags::kNoList; } static std::string GetApiMethodName(const DexFile& dex_file, uint32_t method_index); @@ -76,6 +82,7 @@ class HiddenApi { static void FillList(const char* filename, std::set<std::string>& entries); + std::set<std::string> whitelist_; std::set<std::string> blacklist_; std::set<std::string> light_greylist_; std::set<std::string> dark_greylist_; @@ -85,7 +92,7 @@ struct HiddenApiStats { uint32_t count = 0; uint32_t reflection_count = 0; uint32_t linking_count = 0; - uint32_t api_counts[4] = { 0, 0, 0, 0 }; + uint32_t api_counts[5] = { 0, 0, 0, 0, 0 }; }; } // namespace art diff --git a/tools/veridex/hidden_api_finder.cc b/tools/veridex/hidden_api_finder.cc index d81f133f67..9e2f9366fc 100644 --- a/tools/veridex/hidden_api_finder.cc +++ b/tools/veridex/hidden_api_finder.cc @@ -35,7 +35,7 @@ void HiddenApiFinder::CheckMethod(uint32_t method_id, // Note: we always query whether a method is in a list, as the app // might define blacklisted APIs (which won't be used at runtime). std::string name = HiddenApi::GetApiMethodName(resolver->GetDexFile(), method_id); - if (hidden_api_.IsInRestrictionList(name)) { + if (hidden_api_.IsInAnyList(name)) { method_locations_[name].push_back(ref); } } @@ -46,7 +46,7 @@ void HiddenApiFinder::CheckField(uint32_t field_id, // Note: we always query whether a field is in a list, as the app // might define blacklisted APIs (which won't be used at runtime). std::string name = HiddenApi::GetApiFieldName(resolver->GetDexFile(), field_id); - if (hidden_api_.IsInRestrictionList(name)) { + if (hidden_api_.IsInAnyList(name)) { field_locations_[name].push_back(ref); } } @@ -57,7 +57,7 @@ void HiddenApiFinder::CollectAccesses(VeridexResolver* resolver) { // types can lead to being used through reflection. for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) { std::string name(dex_file.StringByTypeIdx(dex::TypeIndex(i))); - if (hidden_api_.IsInRestrictionList(name)) { + if (hidden_api_.IsInAnyList(name)) { classes_.insert(name); } } @@ -81,9 +81,9 @@ void HiddenApiFinder::CollectAccesses(VeridexResolver* resolver) { // private methods and fields in them. // We don't add class names to the `strings_` set as we know method/field names // don't have '.' or '/'. All hidden API class names have a '/'. - if (hidden_api_.IsInRestrictionList(str)) { + if (hidden_api_.IsInAnyList(str)) { classes_.insert(str); - } else if (hidden_api_.IsInRestrictionList(name)) { + } else if (hidden_api_.IsInAnyList(name)) { // Could be something passed to JNI. classes_.insert(name); } else { @@ -210,7 +210,7 @@ void HiddenApiFinder::Dump(std::ostream& os, std::string full_name = cls + "->" + name; HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name); stats->api_counts[api_list]++; - if (api_list != HiddenApiAccessFlags::kWhitelist) { + if (api_list != HiddenApiAccessFlags::kNoList) { stats->reflection_count++; os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name << " potential use(s):"; diff --git a/tools/veridex/precise_hidden_api_finder.cc b/tools/veridex/precise_hidden_api_finder.cc index 445221e8f7..08ac6d7939 100644 --- a/tools/veridex/precise_hidden_api_finder.cc +++ b/tools/veridex/precise_hidden_api_finder.cc @@ -92,7 +92,7 @@ void PreciseHiddenApiFinder::Dump(std::ostream& os, HiddenApiStats* stats) { std::string name(info.name.ToString()); std::string full_name = cls + "->" + name; HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name); - if (api_list != HiddenApiAccessFlags::kWhitelist) { + if (api_list != HiddenApiAccessFlags::kNoList) { named_uses[full_name].push_back(ref); } } diff --git a/tools/veridex/veridex.cc b/tools/veridex/veridex.cc index 1d3a4fbee9..cf1167fe9c 100644 --- a/tools/veridex/veridex.cc +++ b/tools/veridex/veridex.cc @@ -68,11 +68,13 @@ VeriField VeriClass::sdkInt_ = nullptr; struct VeridexOptions { const char* dex_file = nullptr; const char* core_stubs = nullptr; + const char* whitelist = nullptr; const char* blacklist = nullptr; const char* light_greylist = nullptr; const char* dark_greylist = nullptr; bool precise = true; int target_sdk_version = 28; /* P */ + bool only_report_sdk_uses = false; }; static const char* Substr(const char* str, int index) { @@ -90,17 +92,21 @@ static void ParseArgs(VeridexOptions* options, int argc, char** argv) { static const char* kDexFileOption = "--dex-file="; static const char* kStubsOption = "--core-stubs="; + static const char* kWhitelistOption = "--whitelist="; static const char* kBlacklistOption = "--blacklist="; static const char* kDarkGreylistOption = "--dark-greylist="; static const char* kLightGreylistOption = "--light-greylist="; static const char* kImprecise = "--imprecise"; static const char* kTargetSdkVersion = "--target-sdk-version="; + static const char* kOnlyReportSdkUses = "--only-report-sdk-uses"; for (int i = 0; i < argc; ++i) { if (StartsWith(argv[i], kDexFileOption)) { options->dex_file = Substr(argv[i], strlen(kDexFileOption)); } else if (StartsWith(argv[i], kStubsOption)) { options->core_stubs = Substr(argv[i], strlen(kStubsOption)); + } else if (StartsWith(argv[i], kWhitelistOption)) { + options->whitelist = Substr(argv[i], strlen(kWhitelistOption)); } else if (StartsWith(argv[i], kBlacklistOption)) { options->blacklist = Substr(argv[i], strlen(kBlacklistOption)); } else if (StartsWith(argv[i], kDarkGreylistOption)) { @@ -111,6 +117,8 @@ static void ParseArgs(VeridexOptions* options, int argc, char** argv) { options->precise = false; } else if (StartsWith(argv[i], kTargetSdkVersion)) { options->target_sdk_version = atoi(Substr(argv[i], strlen(kTargetSdkVersion))); + } else if (strcmp(argv[i], kOnlyReportSdkUses) == 0) { + options->only_report_sdk_uses = true; } } } @@ -215,8 +223,17 @@ class Veridex { std::vector<std::unique_ptr<VeridexResolver>> app_resolvers; Resolve(app_dex_files, resolver_map, type_map, &app_resolvers); + if (options.only_report_sdk_uses) { + // If we only need to report SDK uses, clear out any of the other lists so that + // the analysis don't report them. + options.blacklist = nullptr; + options.dark_greylist = nullptr; + options.light_greylist = nullptr; + } + // Find and log uses of hidden APIs. - HiddenApi hidden_api(options.blacklist, options.dark_greylist, options.light_greylist); + HiddenApi hidden_api( + options.whitelist, options.blacklist, options.dark_greylist, options.light_greylist); HiddenApiStats stats; HiddenApiFinder api_finder(hidden_api); @@ -229,7 +246,7 @@ class Veridex { precise_api_finder.Dump(std::cout, &stats); } - DumpSummaryStats(std::cout, stats); + DumpSummaryStats(std::cout, stats, options); if (options.precise) { std::cout << "To run an analysis that can give more reflection accesses, " << std::endl @@ -240,17 +257,23 @@ class Veridex { } private: - static void DumpSummaryStats(std::ostream& os, const HiddenApiStats& stats) { + static void DumpSummaryStats(std::ostream& os, + const HiddenApiStats& stats, + const VeridexOptions& options) { static const char* kPrefix = " "; - os << stats.count << " hidden API(s) used: " - << stats.linking_count << " linked against, " - << stats.reflection_count << " through reflection" << std::endl; - os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kBlacklist] - << " in blacklist" << std::endl; - os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kDarkGreylist] - << " in dark greylist" << std::endl; - os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kLightGreylist] - << " in light greylist" << std::endl; + if (options.only_report_sdk_uses) { + os << stats.api_counts[HiddenApiAccessFlags::kWhitelist] << " SDK API uses." << std::endl; + } else { + os << stats.count << " hidden API(s) used: " + << stats.linking_count << " linked against, " + << stats.reflection_count << " through reflection" << std::endl; + os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kBlacklist] + << " in blacklist" << std::endl; + os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kDarkGreylist] + << " in dark greylist" << std::endl; + os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kLightGreylist] + << " in light greylist" << std::endl; + } } static bool Load(const std::string& filename, |
