From daaf3aa226d91d57dc69acfe3874247c281e2c8b Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Fri, 23 Mar 2018 14:09:23 -0700 Subject: [PATCH] Verify the SELabels used in property_contexts Verify that the SELabels used in property_contexts correspond to a real type in the SEPolicy and that this type has the property_type attribute. Bug: 74078792 Test: Build property_contexts on bullhead successfully Test: See failure when using a faulty SELabel in property_contexts Change-Id: If1618c2c3dae4c0cd3efa5f88056478a6db6bd0b (cherry picked from commit 882faa644876cddac03b98526b6029fe7b25cf9f) --- .../property_info_checker/Android.bp | 1 + .../property_info_checker.cpp | 146 +++++++++++++++++- 2 files changed, 142 insertions(+), 5 deletions(-) diff --git a/property_service/property_info_checker/Android.bp b/property_service/property_info_checker/Android.bp index 6ee649af0..7d6619967 100644 --- a/property_service/property_info_checker/Android.bp +++ b/property_service/property_info_checker/Android.bp @@ -7,6 +7,7 @@ cc_binary { "libpropertyinfoserializer", "libpropertyinfoparser", "libbase", + "libsepol", ], srcs: ["property_info_checker.cpp"], } diff --git a/property_service/property_info_checker/property_info_checker.cpp b/property_service/property_info_checker/property_info_checker.cpp index e4f8264d4..52c4383ad 100644 --- a/property_service/property_info_checker/property_info_checker.cpp +++ b/property_service/property_info_checker/property_info_checker.cpp @@ -1,26 +1,150 @@ #include +#include #include #include #include - +#include #include +#include +#include +#include +#include +#include using android::base::ReadFileToString; using android::properties::BuildTrie; using android::properties::ParsePropertyInfoFile; +using android::properties::PropertyInfoArea; using android::properties::PropertyInfoEntry; +class ContextChecker { + public: + ContextChecker() + : policy_file_(nullptr), + sepol_handle_(nullptr), + sepol_policy_file_(nullptr), + sepol_policy_db_(nullptr) {} + + ~ContextChecker() { + if (sepol_policy_db_ != nullptr) { + sepol_policydb_free(sepol_policy_db_); + } + + if (sepol_policy_file_ != nullptr) { + sepol_policy_file_free(sepol_policy_file_); + } + + if (sepol_handle_ != nullptr) { + sepol_handle_destroy(sepol_handle_); + } + + if (policy_file_ != nullptr) { + fclose(policy_file_); + } + } + + bool Initialize(const char* policy_file) { + policy_file_ = fopen(policy_file, "re"); + if (policy_file_ == nullptr) { + std::cerr << "Could not open policy file, " << policy_file << std::endl; + return false; + } + + sepol_handle_ = sepol_handle_create(); + if (sepol_handle_ == nullptr) { + std::cerr << "Could not create policy handle." << std::endl; + return false; + } + + if (sepol_policy_file_create(&sepol_policy_file_) < 0) { + std::cerr << "Could not create policy file." << std::endl; + return false; + } + + if (sepol_policydb_create(&sepol_policy_db_) < 0) { + std::cerr << "Could not create policy db." << std::endl; + return false; + } + + sepol_policy_file_set_fp(sepol_policy_file_, policy_file_); + sepol_policy_file_set_handle(sepol_policy_file_, sepol_handle_); + + if (sepol_policydb_read(sepol_policy_db_, sepol_policy_file_) < 0) { + std::cerr << "Could not read policy file into policy db." << std::endl; + return false; + } + + auto* attr = + reinterpret_cast(hashtab_search(policy_db_->p_types.table, "property_type")); + if (attr == nullptr || attr->flavor != TYPE_ATTRIB) { + std::cerr << "'property_type' is not defined correctly." << std::endl; + return false; + } + + property_type_bit_ = attr->s.value - 1; + + return true; + } + + bool CheckContext(const char* context) { + sepol_context_t* sepol_context_raw; + if (sepol_context_from_string(sepol_handle_, context, &sepol_context_raw) < 0) { + std::cerr << "Could not allocate context for " << context << std::endl; + return false; + } + auto sepol_context = std::unique_ptr{ + sepol_context_raw, sepol_context_free}; + + if (sepol_context_check(sepol_handle_, sepol_policy_db_, sepol_context.get()) < 0) { + std::cerr << "Sepol context check failed for " << context << std::endl; + return false; + } + + const char* context_type = sepol_context_get_type(sepol_context.get()); + + auto* type = + reinterpret_cast(hashtab_search(policy_db_->p_types.table, context_type)); + if (type == nullptr) { + std::cerr << "Could not find context '" << context << "' in policy database" << std::endl; + return false; + } + + if (type->flavor != TYPE_TYPE) { + std::cerr << "Context '" << context << "' is not defined as a type in policy database" + << std::endl; + return false; + } + + if (!ebitmap_get_bit(&policy_db_->type_attr_map[type->s.value - 1], property_type_bit_)) { + std::cerr << "Context '" << context << "' does not have property_type attribute" << std::endl; + return false; + } + + return true; + } + + private: + FILE* policy_file_; + sepol_handle_t* sepol_handle_; + sepol_policy_file_t* sepol_policy_file_; + union { + sepol_policydb_t* sepol_policy_db_; + policydb_t* policy_db_; + }; + unsigned int property_type_bit_; +}; + int main(int argc, char** argv) { - if (argc < 2) { - std::cerr << "A list of property info files to be checked is expected on the command line" - << std::endl; + if (argc < 3) { + std::cerr << "usage: " << argv[0] + << " COMPILED_SEPOLICY PROPERTY_INFO_FILE [PROPERTY_INFO_FILE]..." << std::endl; return -1; } auto property_info_entries = std::vector{}; - for (int i = 1; i < argc; ++i) { + for (int i = 2; i < argc; ++i) { auto filename = argv[i]; auto file_contents = std::string{}; if (!ReadFileToString(filename, &file_contents)) { @@ -47,5 +171,17 @@ int main(int argc, char** argv) { return -1; } + auto checker = ContextChecker{}; + if (!checker.Initialize(argv[1])) { + return -1; + } + + auto property_info_area = reinterpret_cast(serialized_contexts.data()); + for (size_t i = 0; i < property_info_area->num_contexts(); ++i) { + if (!checker.CheckContext(property_info_area->context(i))) { + return -1; + } + } + return 0; }