Merge "Create a host side checker for property info file correctness"
This commit is contained in:
commit
db976aa526
9 changed files with 164 additions and 51 deletions
|
|
@ -58,7 +58,6 @@
|
||||||
|
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "persistent_properties.h"
|
#include "persistent_properties.h"
|
||||||
#include "space_tokenizer.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
using android::base::ReadFileToString;
|
using android::base::ReadFileToString;
|
||||||
|
|
@ -69,6 +68,7 @@ using android::base::Timer;
|
||||||
using android::base::Trim;
|
using android::base::Trim;
|
||||||
using android::base::WriteStringToFile;
|
using android::base::WriteStringToFile;
|
||||||
using android::properties::BuildTrie;
|
using android::properties::BuildTrie;
|
||||||
|
using android::properties::ParsePropertyInfoFile;
|
||||||
using android::properties::PropertyInfoAreaFile;
|
using android::properties::PropertyInfoAreaFile;
|
||||||
using android::properties::PropertyInfoEntry;
|
using android::properties::PropertyInfoEntry;
|
||||||
|
|
||||||
|
|
@ -728,22 +728,6 @@ static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<PropertyInfoEntry> ParsePropertyInfoLine(const std::string& line) {
|
|
||||||
auto tokenizer = SpaceTokenizer(line);
|
|
||||||
|
|
||||||
auto property = tokenizer.GetNext();
|
|
||||||
if (property.empty()) return Error() << "Did not find a property entry in '" << line << "'";
|
|
||||||
|
|
||||||
auto context = tokenizer.GetNext();
|
|
||||||
if (context.empty()) return Error() << "Did not find a context entry in '" << line << "'";
|
|
||||||
|
|
||||||
// It is not an error to not find these, as older files will not contain them.
|
|
||||||
auto exact_match = tokenizer.GetNext();
|
|
||||||
auto schema = tokenizer.GetRemaining();
|
|
||||||
|
|
||||||
return {property, context, schema, exact_match == "exact"};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LoadPropertyInfoFromFile(const std::string& filename,
|
bool LoadPropertyInfoFromFile(const std::string& filename,
|
||||||
std::vector<PropertyInfoEntry>* property_infos) {
|
std::vector<PropertyInfoEntry>* property_infos) {
|
||||||
auto file_contents = std::string();
|
auto file_contents = std::string();
|
||||||
|
|
@ -752,20 +736,14 @@ bool LoadPropertyInfoFromFile(const std::string& filename,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& line : Split(file_contents, "\n")) {
|
auto errors = std::vector<std::string>{};
|
||||||
auto trimmed_line = Trim(line);
|
ParsePropertyInfoFile(file_contents, property_infos, &errors);
|
||||||
if (trimmed_line.empty() || StartsWith(trimmed_line, "#")) {
|
// Individual parsing errors are reported but do not cause a failed boot, which is what
|
||||||
continue;
|
// returning false would do here.
|
||||||
}
|
for (const auto& error : errors) {
|
||||||
|
LOG(ERROR) << "Could not read line from '" << filename << "': " << error;
|
||||||
auto property_info = ParsePropertyInfoLine(line);
|
|
||||||
if (!property_info) {
|
|
||||||
LOG(ERROR) << "Could not read line from '" << filename << "': " << property_info.error();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
property_infos->emplace_back(*property_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
cc_library_static {
|
cc_library_static {
|
||||||
name: "libpropertyinfoparser",
|
name: "libpropertyinfoparser",
|
||||||
|
host_supported: true,
|
||||||
srcs: ["property_info_parser.cpp"],
|
srcs: ["property_info_parser.cpp"],
|
||||||
|
|
||||||
cpp_std: "experimental",
|
cpp_std: "experimental",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#define PROPERTY_INFO_PARSER_H
|
#define PROPERTY_INFO_PARSER_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace properties {
|
namespace properties {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
cc_defaults {
|
cc_defaults {
|
||||||
name: "propertyinfoserializer_defaults",
|
name: "propertyinfoserializer_defaults",
|
||||||
|
host_supported: true,
|
||||||
cpp_std: "experimental",
|
cpp_std: "experimental",
|
||||||
sanitize: {
|
sanitize: {
|
||||||
misc_undefined: ["signed-integer-overflow"],
|
misc_undefined: ["signed-integer-overflow"],
|
||||||
|
|
@ -19,6 +20,7 @@ cc_library_static {
|
||||||
name: "libpropertyinfoserializer",
|
name: "libpropertyinfoserializer",
|
||||||
defaults: ["propertyinfoserializer_defaults"],
|
defaults: ["propertyinfoserializer_defaults"],
|
||||||
srcs: [
|
srcs: [
|
||||||
|
"property_info_file.cpp",
|
||||||
"property_info_serializer.cpp",
|
"property_info_serializer.cpp",
|
||||||
"trie_builder.cpp",
|
"trie_builder.cpp",
|
||||||
"trie_serializer.cpp",
|
"trie_serializer.cpp",
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,10 @@ bool BuildTrie(const std::vector<PropertyInfoEntry>& property_info,
|
||||||
const std::string& default_context, const std::string& default_schema,
|
const std::string& default_context, const std::string& default_schema,
|
||||||
std::string* serialized_trie, std::string* error);
|
std::string* serialized_trie, std::string* error);
|
||||||
|
|
||||||
|
void ParsePropertyInfoFile(const std::string& file_contents,
|
||||||
|
std::vector<PropertyInfoEntry>* property_infos,
|
||||||
|
std::vector<std::string>* errors);
|
||||||
|
|
||||||
} // namespace properties
|
} // namespace properties
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
#include <property_info_serializer/property_info_serializer.h>
|
||||||
|
|
||||||
|
#include <android-base/strings.h>
|
||||||
|
|
||||||
|
#include "space_tokenizer.h"
|
||||||
|
|
||||||
|
using android::base::Split;
|
||||||
|
using android::base::StartsWith;
|
||||||
|
using android::base::Trim;
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace properties {
|
||||||
|
|
||||||
|
bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std::string* error) {
|
||||||
|
auto tokenizer = SpaceTokenizer(line);
|
||||||
|
|
||||||
|
auto property = tokenizer.GetNext();
|
||||||
|
if (property.empty()) {
|
||||||
|
*error = "Did not find a property entry in '" + line + "'";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto context = tokenizer.GetNext();
|
||||||
|
if (context.empty()) {
|
||||||
|
*error = "Did not find a context entry in '" + line + "'";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is not an error to not find these, as older files will not contain them.
|
||||||
|
auto exact_match = tokenizer.GetNext();
|
||||||
|
auto schema = tokenizer.GetRemaining();
|
||||||
|
|
||||||
|
*out = {property, context, schema, exact_match == "exact"};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParsePropertyInfoFile(const std::string& file_contents,
|
||||||
|
std::vector<PropertyInfoEntry>* property_infos,
|
||||||
|
std::vector<std::string>* errors) {
|
||||||
|
// Do not clear property_infos to allow this function to be called on multiple files, with
|
||||||
|
// their results concatenated.
|
||||||
|
errors->clear();
|
||||||
|
|
||||||
|
for (const auto& line : Split(file_contents, "\n")) {
|
||||||
|
auto trimmed_line = Trim(line);
|
||||||
|
if (trimmed_line.empty() || StartsWith(trimmed_line, "#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto property_info_entry = PropertyInfoEntry{};
|
||||||
|
auto parse_error = std::string{};
|
||||||
|
if (!ParsePropertyInfoLine(trimmed_line, &property_info_entry, &parse_error)) {
|
||||||
|
errors->emplace_back(parse_error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
property_infos->emplace_back(property_info_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace properties
|
||||||
|
} // namespace android
|
||||||
|
|
@ -14,37 +14,37 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _INIT_SPACE_TOKENIZER_H
|
#ifndef PROPERTY_INFO_SERIALIZER_SPACE_TOKENIZER_H
|
||||||
#define _INIT_SPACE_TOKENIZER_H
|
#define PROPERTY_INFO_SERIALIZER_SPACE_TOKENIZER_H
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace init {
|
namespace properties {
|
||||||
|
|
||||||
class SpaceTokenizer {
|
class SpaceTokenizer {
|
||||||
public:
|
public:
|
||||||
SpaceTokenizer(const std::string& string)
|
SpaceTokenizer(const std::string& string)
|
||||||
: string_(string), it_(string_.begin()), end_(string_.end()) {}
|
: string_(string), it_(string_.begin()), end_(string_.end()) {}
|
||||||
|
|
||||||
std::string GetNext() {
|
std::string GetNext() {
|
||||||
auto next = std::string();
|
auto next = std::string();
|
||||||
while (it_ != end_ && !isspace(*it_)) {
|
while (it_ != end_ && !isspace(*it_)) {
|
||||||
next.push_back(*it_++);
|
next.push_back(*it_++);
|
||||||
}
|
|
||||||
while (it_ != end_ && isspace(*it_)) {
|
|
||||||
it_++;
|
|
||||||
}
|
|
||||||
return next;
|
|
||||||
}
|
}
|
||||||
|
while (it_ != end_ && isspace(*it_)) {
|
||||||
|
it_++;
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetRemaining() { return std::string(it_, end_); }
|
std::string GetRemaining() { return std::string(it_, end_); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string string_;
|
std::string string_;
|
||||||
std::string::const_iterator it_;
|
std::string::const_iterator it_;
|
||||||
std::string::const_iterator end_;
|
std::string::const_iterator end_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace init
|
} // namespace properties
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
14
property_service/property_info_checker/Android.bp
Normal file
14
property_service/property_info_checker/Android.bp
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
cc_binary {
|
||||||
|
name: "property_info_checker",
|
||||||
|
host_supported: true,
|
||||||
|
cpp_std: "experimental",
|
||||||
|
sanitize: {
|
||||||
|
misc_undefined: ["signed-integer-overflow"],
|
||||||
|
},
|
||||||
|
static_libs: [
|
||||||
|
"libpropertyinfoserializer",
|
||||||
|
"libpropertyinfoparser",
|
||||||
|
"libbase",
|
||||||
|
],
|
||||||
|
srcs: ["property_info_checker.cpp"],
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <android-base/file.h>
|
||||||
|
|
||||||
|
#include <property_info_serializer/property_info_serializer.h>
|
||||||
|
|
||||||
|
using android::base::ReadFileToString;
|
||||||
|
using android::properties::BuildTrie;
|
||||||
|
using android::properties::ParsePropertyInfoFile;
|
||||||
|
using android::properties::PropertyInfoEntry;
|
||||||
|
|
||||||
|
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;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto property_info_entries = std::vector<PropertyInfoEntry>{};
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
auto filename = argv[i];
|
||||||
|
auto file_contents = std::string{};
|
||||||
|
if (!ReadFileToString(filename, &file_contents)) {
|
||||||
|
std::cerr << "Could not read properties from '" << filename << "'" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto errors = std::vector<std::string>{};
|
||||||
|
ParsePropertyInfoFile(file_contents, &property_info_entries, &errors);
|
||||||
|
if (!errors.empty()) {
|
||||||
|
for (const auto& error : errors) {
|
||||||
|
std::cerr << "Could not read line from '" << filename << "': " << error << std::endl;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto serialized_contexts = std::string{};
|
||||||
|
auto build_trie_error = std::string{};
|
||||||
|
|
||||||
|
if (!BuildTrie(property_info_entries, "u:object_r:default_prop:s0", "\\s*", &serialized_contexts,
|
||||||
|
&build_trie_error)) {
|
||||||
|
std::cerr << "Unable to serialize property contexts: " << build_trie_error << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue