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
This commit is contained in:
parent
d888e343b7
commit
882faa6448
2 changed files with 142 additions and 5 deletions
|
@ -7,6 +7,7 @@ cc_binary {
|
|||
"libpropertyinfoserializer",
|
||||
"libpropertyinfoparser",
|
||||
"libbase",
|
||||
"libsepol",
|
||||
],
|
||||
srcs: ["property_info_checker.cpp"],
|
||||
}
|
||||
|
|
|
@ -1,26 +1,150 @@
|
|||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
|
||||
#include <property_info_parser/property_info_parser.h>
|
||||
#include <property_info_serializer/property_info_serializer.h>
|
||||
#include <sepol/context.h>
|
||||
#include <sepol/context_record.h>
|
||||
#include <sepol/handle.h>
|
||||
#include <sepol/policydb.h>
|
||||
#include <sepol/policydb/policydb.h>
|
||||
|
||||
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<type_datum*>(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_t, decltype(&sepol_context_free)>{
|
||||
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<type_datum*>(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<PropertyInfoEntry>{};
|
||||
|
||||
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<PropertyInfoArea*>(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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue