From 4b077c51f269c9a167e62b03f5ae546d17b2bb59 Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Wed, 11 Dec 2019 07:56:51 -0800 Subject: [PATCH] Require 'exact', 'prefix', or '' for match operation in property_contexts The previous code would lazily check for 'exact' and accept any other value as a prefix match. This should be a tighter check allowing only 'exact', 'prefix', or an empty string for this option. Test: build fails if an invalid string is used for the match operation Test: build succeeds normally Test: `getprop -Z` shows exact vs prefix is differentiated correctly Change-Id: I21dcb193810d65f468f8960967eabfd261f71e21 --- init/host_init_verifier.cpp | 2 +- init/property_service.cpp | 3 ++- .../property_info_serializer.h | 7 ++----- .../property_info_file.cpp | 21 ++++++++++++++----- .../property_info_checker.cpp | 2 +- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/init/host_init_verifier.cpp b/init/host_init_verifier.cpp index 3acc3cc97..22de8467d 100644 --- a/init/host_init_verifier.cpp +++ b/init/host_init_verifier.cpp @@ -191,7 +191,7 @@ void HandlePropertyContexts(const std::string& filename, } auto errors = std::vector{}; - ParsePropertyInfoFile(file_contents, property_infos, &errors); + ParsePropertyInfoFile(file_contents, true, property_infos, &errors); for (const auto& error : errors) { LOG(ERROR) << "Could not read line from '" << filename << "': " << error; } diff --git a/init/property_service.cpp b/init/property_service.cpp index adf892905..5b35ad2e9 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -925,7 +925,8 @@ bool LoadPropertyInfoFromFile(const std::string& filename, } auto errors = std::vector{}; - ParsePropertyInfoFile(file_contents, property_infos, &errors); + bool require_prefix_or_exact = SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__; + ParsePropertyInfoFile(file_contents, require_prefix_or_exact, property_infos, &errors); // Individual parsing errors are reported but do not cause a failed boot, which is what // returning false would do here. for (const auto& error : errors) { diff --git a/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h b/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h index 439813d12..dfb1d1179 100644 --- a/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h +++ b/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h @@ -14,8 +14,7 @@ // limitations under the License. // -#ifndef PROPERTY_INFO_SERIALIZER_H -#define PROPERTY_INFO_SERIALIZER_H +#pragma once #include #include @@ -41,11 +40,9 @@ bool BuildTrie(const std::vector& property_info, const std::string& default_context, const std::string& default_type, std::string* serialized_trie, std::string* error); -void ParsePropertyInfoFile(const std::string& file_contents, +void ParsePropertyInfoFile(const std::string& file_contents, bool require_prefix_or_exact, std::vector* property_infos, std::vector* errors); } // namespace properties } // namespace android - -#endif diff --git a/property_service/libpropertyinfoserializer/property_info_file.cpp b/property_service/libpropertyinfoserializer/property_info_file.cpp index 2cdc62dce..771a9cec9 100644 --- a/property_service/libpropertyinfoserializer/property_info_file.cpp +++ b/property_service/libpropertyinfoserializer/property_info_file.cpp @@ -56,7 +56,8 @@ bool IsTypeValid(const std::vector& type_strings) { return false; } -bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std::string* error) { +bool ParsePropertyInfoLine(const std::string& line, bool require_prefix_or_exact, + PropertyInfoEntry* out, std::string* error) { auto tokenizer = SpaceTokenizer(line); auto property = tokenizer.GetNext(); @@ -72,7 +73,7 @@ bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std: } // It is not an error to not find exact_match or a type, as older files will not contain them. - auto exact_match = tokenizer.GetNext(); + auto match_operation = tokenizer.GetNext(); // We reformat type to be space deliminated regardless of the input whitespace for easier storage // and subsequent parsing. auto type_strings = std::vector{}; @@ -82,18 +83,27 @@ bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std: type = tokenizer.GetNext(); } + bool exact_match = false; + if (match_operation == "exact") { + exact_match = true; + } else if (match_operation != "prefix" && match_operation != "" && require_prefix_or_exact) { + *error = "Match operation '" + match_operation + + "' is not valid: must be either 'prefix' or 'exact'"; + return false; + } + if (!type_strings.empty() && !IsTypeValid(type_strings)) { *error = "Type '" + Join(type_strings, " ") + "' is not valid"; return false; } - *out = {property, context, Join(type_strings, " "), exact_match == "exact"}; + *out = {property, context, Join(type_strings, " "), exact_match}; return true; } } // namespace -void ParsePropertyInfoFile(const std::string& file_contents, +void ParsePropertyInfoFile(const std::string& file_contents, bool require_prefix_or_exact, std::vector* property_infos, std::vector* errors) { // Do not clear property_infos to allow this function to be called on multiple files, with @@ -108,7 +118,8 @@ void ParsePropertyInfoFile(const std::string& file_contents, auto property_info_entry = PropertyInfoEntry{}; auto parse_error = std::string{}; - if (!ParsePropertyInfoLine(trimmed_line, &property_info_entry, &parse_error)) { + if (!ParsePropertyInfoLine(trimmed_line, require_prefix_or_exact, &property_info_entry, + &parse_error)) { errors->emplace_back(parse_error); continue; } diff --git a/property_service/property_info_checker/property_info_checker.cpp b/property_service/property_info_checker/property_info_checker.cpp index 52c4383ad..61b368ec0 100644 --- a/property_service/property_info_checker/property_info_checker.cpp +++ b/property_service/property_info_checker/property_info_checker.cpp @@ -153,7 +153,7 @@ int main(int argc, char** argv) { } auto errors = std::vector{}; - ParsePropertyInfoFile(file_contents, &property_info_entries, &errors); + ParsePropertyInfoFile(file_contents, true, &property_info_entries, &errors); if (!errors.empty()) { for (const auto& error : errors) { std::cerr << "Could not read line from '" << filename << "': " << error << std::endl;