init: add host side parser for init
Create a host side parser for init such that init rc files can be verified for syntax correctness before being used on the device. Bug: 36970783 Test: run the parser on init files on host Change-Id: I7e8772e278ebaff727057308596ebacf28b6fdda
This commit is contained in:
parent
304dacae8a
commit
de6bd50d42
|
@ -194,4 +194,59 @@ cc_benchmark {
|
|||
static_libs: ["libinit"],
|
||||
}
|
||||
|
||||
// Host Verifier
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
genrule {
|
||||
name: "generated_stub_builtin_function_map",
|
||||
out: ["generated_stub_builtin_function_map.h"],
|
||||
srcs: ["builtins.cpp"],
|
||||
cmd: "sed -n '/Builtin-function-map start/{:a;n;/Builtin-function-map end/q;p;ba}' $(in) | sed -e 's/do_[^}]*/do_stub/g' > $(out)"
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "host_init_verifier",
|
||||
host_supported: true,
|
||||
cpp_std: "experimental",
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wno-unused-parameter",
|
||||
"-Werror",
|
||||
],
|
||||
static_libs: [
|
||||
"libbase",
|
||||
"libselinux",
|
||||
],
|
||||
whole_static_libs: ["libcap"],
|
||||
shared_libs: [
|
||||
"libprotobuf-cpp-lite",
|
||||
"libhidl-gen-utils",
|
||||
"libprocessgroup",
|
||||
"liblog",
|
||||
"libcutils",
|
||||
],
|
||||
srcs: [
|
||||
"action.cpp",
|
||||
"action_manager.cpp",
|
||||
"action_parser.cpp",
|
||||
"capabilities.cpp",
|
||||
"descriptors.cpp",
|
||||
"import_parser.cpp",
|
||||
"host_init_parser.cpp",
|
||||
"host_init_stubs.cpp",
|
||||
"parser.cpp",
|
||||
"rlimit_parser.cpp",
|
||||
"tokenizer.cpp",
|
||||
"service.cpp",
|
||||
"subcontext.cpp",
|
||||
"subcontext.proto",
|
||||
"util.cpp",
|
||||
],
|
||||
proto: {
|
||||
type: "lite",
|
||||
},
|
||||
generated_headers: ["generated_stub_builtin_function_map"],
|
||||
}
|
||||
|
||||
subdirs = ["*"]
|
||||
|
|
|
@ -18,11 +18,16 @@
|
|||
|
||||
#include <android-base/chrono_utils.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android-base/properties.h>
|
||||
#else
|
||||
#include "host_init_stubs.h"
|
||||
#endif
|
||||
|
||||
using android::base::Join;
|
||||
|
||||
namespace android {
|
||||
|
|
|
@ -16,11 +16,16 @@
|
|||
|
||||
#include "action_parser.h"
|
||||
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#include "stable_properties.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android-base/properties.h>
|
||||
#else
|
||||
#include "host_init_stubs.h"
|
||||
#endif
|
||||
|
||||
using android::base::GetBoolProperty;
|
||||
using android::base::StartsWith;
|
||||
|
||||
|
|
|
@ -968,8 +968,8 @@ static Result<Success> do_wait_for_prop(const BuiltinArguments& args) {
|
|||
const char* value = args[2].c_str();
|
||||
size_t value_len = strlen(value);
|
||||
|
||||
if (!is_legal_property_name(name)) {
|
||||
return Error() << "is_legal_property_name(" << name << ") failed";
|
||||
if (!IsLegalPropertyName(name)) {
|
||||
return Error() << "IsLegalPropertyName(" << name << ") failed";
|
||||
}
|
||||
if (value_len >= PROP_VALUE_MAX) {
|
||||
return Error() << "value too long";
|
||||
|
@ -1018,6 +1018,7 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) {
|
|||
{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"});
|
||||
}
|
||||
|
||||
// Builtin-function-map start
|
||||
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
|
||||
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
|
||||
// clang-format off
|
||||
|
@ -1075,6 +1076,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
|
|||
// clang-format on
|
||||
return builtin_functions;
|
||||
}
|
||||
// Builtin-function-map end
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include "capabilities.h"
|
||||
|
||||
#include <sys/capability.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include <map>
|
||||
|
@ -72,10 +71,15 @@ static const std::map<std::string, int> cap_map = {
|
|||
static_assert(CAP_LAST_CAP == CAP_AUDIT_READ, "CAP_LAST_CAP is not CAP_AUDIT_READ");
|
||||
|
||||
static bool ComputeCapAmbientSupported() {
|
||||
#if defined(__ANDROID__)
|
||||
return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >= 0;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned int ComputeLastValidCap() {
|
||||
#if defined(__ANDROID__)
|
||||
// Android does not support kernels < 3.8. 'CAP_WAKE_ALARM' has been present since 3.0, see
|
||||
// http://lxr.free-electrons.com/source/include/linux/capability.h?v=3.0#L360.
|
||||
unsigned int last_valid_cap = CAP_WAKE_ALARM;
|
||||
|
@ -83,6 +87,9 @@ static unsigned int ComputeLastValidCap() {
|
|||
|
||||
// |last_valid_cap| will be the first failing value.
|
||||
return last_valid_cap - 1;
|
||||
#else
|
||||
return CAP_LAST_CAP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool DropBoundingSet(const CapSet& to_keep) {
|
||||
|
@ -139,6 +146,7 @@ static bool SetProcCaps(const CapSet& to_keep, bool add_setpcap) {
|
|||
}
|
||||
|
||||
static bool SetAmbientCaps(const CapSet& to_raise) {
|
||||
#if defined(__ANDROID__)
|
||||
for (size_t cap = 0; cap < to_raise.size(); ++cap) {
|
||||
if (to_raise.test(cap)) {
|
||||
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) != 0) {
|
||||
|
@ -147,6 +155,7 @@ static bool SetAmbientCaps(const CapSet& to_raise) {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,17 @@
|
|||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
#ifndef CAP_BLOCK_SUSPEND
|
||||
#define CAP_BLOCK_SUSPEND 36
|
||||
#endif
|
||||
#ifndef CAP_AUDIT_READ
|
||||
#define CAP_AUDIT_READ 37
|
||||
#endif
|
||||
#undef CAP_LAST_CAP
|
||||
#define CAP_LAST_CAP CAP_AUDIT_READ
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// Copyright (C) 2018 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include <pwd.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "action.h"
|
||||
#include "action_manager.h"
|
||||
#include "action_parser.h"
|
||||
#include "parser.h"
|
||||
#include "result.h"
|
||||
#include "service.h"
|
||||
|
||||
// The host passwd file won't have the Android entries, so we fake success here.
|
||||
passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
|
||||
char dummy_buf[] = "dummy";
|
||||
static passwd dummy_passwd = {
|
||||
.pw_name = dummy_buf,
|
||||
.pw_dir = dummy_buf,
|
||||
.pw_shell = dummy_buf,
|
||||
.pw_uid = 123,
|
||||
.pw_gid = 123,
|
||||
};
|
||||
return &dummy_passwd;
|
||||
}
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
static Result<Success> do_stub(const BuiltinArguments& args) {
|
||||
return Success();
|
||||
}
|
||||
|
||||
#include "generated_stub_builtin_function_map.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
android::base::InitLogging(argv, &android::base::StderrLogger);
|
||||
if (argc != 2) {
|
||||
LOG(ERROR) << "Usage: " << argv[0] << " <init file to parse>";
|
||||
return -1;
|
||||
}
|
||||
const BuiltinFunctionMap function_map;
|
||||
Action::set_function_map(&function_map);
|
||||
ActionManager& am = ActionManager::GetInstance();
|
||||
ServiceList& sl = ServiceList::GetInstance();
|
||||
Parser parser;
|
||||
parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sl, nullptr));
|
||||
parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
|
||||
|
||||
size_t num_errors = 0;
|
||||
if (!parser.ParseConfig(argv[1], &num_errors)) {
|
||||
LOG(ERROR) << "Failed to find script";
|
||||
return -1;
|
||||
}
|
||||
if (num_errors > 0) {
|
||||
LOG(ERROR) << "Parse failed with " << num_errors << " errors";
|
||||
return -1;
|
||||
}
|
||||
LOG(INFO) << "Parse success!";
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
android::init::main(argc, argv);
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "host_init_stubs.h"
|
||||
|
||||
// unistd.h
|
||||
int setgroups(size_t __size, const gid_t* __list) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
std::string GetProperty(const std::string&, const std::string& default_value) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
bool GetBoolProperty(const std::string&, bool default_value) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
// init.h
|
||||
std::string default_console = "/dev/console";
|
||||
|
||||
// property_service.h
|
||||
uint32_t (*property_set)(const std::string& name, const std::string& value) = nullptr;
|
||||
uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&,
|
||||
const ucred&) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// selinux.h
|
||||
void SelabelInitialize() {}
|
||||
|
||||
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _INIT_HOST_INIT_STUBS_H
|
||||
#define _INIT_HOST_INIT_STUBS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
// sys/system_properties.h
|
||||
#define PROP_VALUE_MAX 92
|
||||
|
||||
// unistd.h
|
||||
int setgroups(size_t __size, const gid_t* __list);
|
||||
|
||||
// android-base/properties.h
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
std::string GetProperty(const std::string& key, const std::string& default_value);
|
||||
bool GetBoolProperty(const std::string& key, bool default_value);
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
// init.h
|
||||
extern std::string default_console;
|
||||
|
||||
// property_service.h
|
||||
extern uint32_t (*property_set)(const std::string& name, const std::string& value);
|
||||
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
|
||||
const std::string& source_context, const ucred& cr);
|
||||
|
||||
// selinux.h
|
||||
void SelabelInitialize();
|
||||
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
||||
#endif
|
|
@ -39,7 +39,7 @@ void Parser::AddSingleLineParser(const std::string& prefix, LineCallback callbac
|
|||
line_callbacks_.emplace_back(prefix, callback);
|
||||
}
|
||||
|
||||
void Parser::ParseData(const std::string& filename, const std::string& data) {
|
||||
void Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) {
|
||||
// TODO: Use a parser with const input and remove this copy
|
||||
std::vector<char> data_copy(data.begin(), data.end());
|
||||
data_copy.push_back('\0');
|
||||
|
@ -57,6 +57,7 @@ void Parser::ParseData(const std::string& filename, const std::string& data) {
|
|||
if (section_parser == nullptr) return;
|
||||
|
||||
if (auto result = section_parser->EndSection(); !result) {
|
||||
(*parse_errors)++;
|
||||
LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();
|
||||
}
|
||||
|
||||
|
@ -80,6 +81,7 @@ void Parser::ParseData(const std::string& filename, const std::string& data) {
|
|||
end_section();
|
||||
|
||||
if (auto result = callback(std::move(args)); !result) {
|
||||
(*parse_errors)++;
|
||||
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
|
||||
}
|
||||
break;
|
||||
|
@ -92,12 +94,14 @@ void Parser::ParseData(const std::string& filename, const std::string& data) {
|
|||
if (auto result =
|
||||
section_parser->ParseSection(std::move(args), filename, state.line);
|
||||
!result) {
|
||||
(*parse_errors)++;
|
||||
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
|
||||
section_parser = nullptr;
|
||||
}
|
||||
} else if (section_parser) {
|
||||
if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
|
||||
!result) {
|
||||
(*parse_errors)++;
|
||||
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +114,7 @@ void Parser::ParseData(const std::string& filename, const std::string& data) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Parser::ParseConfigFile(const std::string& path) {
|
||||
bool Parser::ParseConfigFile(const std::string& path, size_t* parse_errors) {
|
||||
LOG(INFO) << "Parsing file " << path << "...";
|
||||
android::base::Timer t;
|
||||
auto config_contents = ReadFile(path);
|
||||
|
@ -120,7 +124,7 @@ bool Parser::ParseConfigFile(const std::string& path) {
|
|||
}
|
||||
|
||||
config_contents->push_back('\n'); // TODO: fix parse_config.
|
||||
ParseData(path, *config_contents);
|
||||
ParseData(path, *config_contents, parse_errors);
|
||||
for (const auto& [section_name, section_parser] : section_parsers_) {
|
||||
section_parser->EndFile();
|
||||
}
|
||||
|
@ -129,7 +133,7 @@ bool Parser::ParseConfigFile(const std::string& path) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseConfigDir(const std::string& path) {
|
||||
bool Parser::ParseConfigDir(const std::string& path, size_t* parse_errors) {
|
||||
LOG(INFO) << "Parsing directory " << path << "...";
|
||||
std::unique_ptr<DIR, decltype(&closedir)> config_dir(opendir(path.c_str()), closedir);
|
||||
if (!config_dir) {
|
||||
|
@ -149,7 +153,7 @@ bool Parser::ParseConfigDir(const std::string& path) {
|
|||
// Sort first so we load files in a consistent order (bug 31996208)
|
||||
std::sort(files.begin(), files.end());
|
||||
for (const auto& file : files) {
|
||||
if (!ParseConfigFile(file)) {
|
||||
if (!ParseConfigFile(file, parse_errors)) {
|
||||
LOG(ERROR) << "could not import file '" << file << "'";
|
||||
}
|
||||
}
|
||||
|
@ -157,10 +161,16 @@ bool Parser::ParseConfigDir(const std::string& path) {
|
|||
}
|
||||
|
||||
bool Parser::ParseConfig(const std::string& path) {
|
||||
size_t parse_errors;
|
||||
return ParseConfig(path, &parse_errors);
|
||||
}
|
||||
|
||||
bool Parser::ParseConfig(const std::string& path, size_t* parse_errors) {
|
||||
*parse_errors = 0;
|
||||
if (is_dir(path.c_str())) {
|
||||
return ParseConfigDir(path);
|
||||
return ParseConfigDir(path, parse_errors);
|
||||
}
|
||||
return ParseConfigFile(path);
|
||||
return ParseConfigFile(path, parse_errors);
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
|
|
|
@ -72,13 +72,14 @@ class Parser {
|
|||
Parser();
|
||||
|
||||
bool ParseConfig(const std::string& path);
|
||||
bool ParseConfig(const std::string& path, size_t* parse_errors);
|
||||
void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser);
|
||||
void AddSingleLineParser(const std::string& prefix, LineCallback callback);
|
||||
|
||||
private:
|
||||
void ParseData(const std::string& filename, const std::string& data);
|
||||
bool ParseConfigFile(const std::string& path);
|
||||
bool ParseConfigDir(const std::string& path);
|
||||
void ParseData(const std::string& filename, const std::string& data, size_t* parse_errors);
|
||||
bool ParseConfigFile(const std::string& path, size_t* parse_errors);
|
||||
bool ParseConfigDir(const std::string& path, size_t* parse_errors);
|
||||
|
||||
std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;
|
||||
std::vector<std::pair<std::string, LineCallback>> line_callbacks_;
|
||||
|
|
|
@ -117,35 +117,10 @@ static bool CheckMacPerms(const std::string& name, const char* target_context,
|
|||
return has_access;
|
||||
}
|
||||
|
||||
bool is_legal_property_name(const std::string& name) {
|
||||
size_t namelen = name.size();
|
||||
|
||||
if (namelen < 1) return false;
|
||||
if (name[0] == '.') return false;
|
||||
if (name[namelen - 1] == '.') return false;
|
||||
|
||||
/* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */
|
||||
/* Don't allow ".." to appear in a property name */
|
||||
for (size_t i = 0; i < namelen; i++) {
|
||||
if (name[i] == '.') {
|
||||
// i=0 is guaranteed to never have a dot. See above.
|
||||
if (name[i-1] == '.') return false;
|
||||
continue;
|
||||
}
|
||||
if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') continue;
|
||||
if (name[i] >= 'a' && name[i] <= 'z') continue;
|
||||
if (name[i] >= 'A' && name[i] <= 'Z') continue;
|
||||
if (name[i] >= '0' && name[i] <= '9') continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t PropertySetImpl(const std::string& name, const std::string& value) {
|
||||
size_t valuelen = value.size();
|
||||
|
||||
if (!is_legal_property_name(name)) {
|
||||
if (!IsLegalPropertyName(name)) {
|
||||
LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: bad name";
|
||||
return PROP_ERROR_INVALID_NAME;
|
||||
}
|
||||
|
@ -416,7 +391,7 @@ class SocketConnection {
|
|||
// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
|
||||
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
|
||||
const std::string& source_context, const ucred& cr) {
|
||||
if (!is_legal_property_name(name)) {
|
||||
if (!IsLegalPropertyName(name)) {
|
||||
LOG(ERROR) << "PropertySet: illegal property name \"" << name << "\"";
|
||||
return PROP_ERROR_INVALID_NAME;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ void property_load_boot_defaults(void);
|
|||
void load_persist_props(void);
|
||||
void load_system_props(void);
|
||||
void start_property_service(void);
|
||||
bool is_legal_property_name(const std::string& name);
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <sys/prctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/system_properties.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <termios.h>
|
||||
|
@ -33,8 +32,6 @@
|
|||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/parseint.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/scopeguard.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <hidl-util/FQName.h>
|
||||
|
@ -42,15 +39,23 @@
|
|||
#include <selinux/selinux.h>
|
||||
#include <system/thread_defs.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "property_service.h"
|
||||
#include "rlimit_parser.h"
|
||||
#include "util.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <sys/system_properties.h>
|
||||
|
||||
#include <android-base/properties.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "property_service.h"
|
||||
#else
|
||||
#include "host_init_stubs.h"
|
||||
#endif
|
||||
|
||||
using android::base::boot_clock;
|
||||
using android::base::GetProperty;
|
||||
using android::base::Join;
|
||||
using android::base::make_scope_guard;
|
||||
using android::base::ParseInt;
|
||||
using android::base::StartsWith;
|
||||
using android::base::StringPrintf;
|
||||
|
@ -1168,7 +1173,7 @@ bool ServiceParser::IsValidName(const std::string& name) const {
|
|||
// Property values can contain any characters, but may only be a certain length.
|
||||
// (The latter restriction is needed because `start` and `stop` work by writing
|
||||
// the service name to the "ctl.start" and "ctl.stop" properties.)
|
||||
return is_legal_property_name("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
|
||||
return IsLegalPropertyName("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
|
|
|
@ -27,12 +27,14 @@
|
|||
#include <selinux/android.h>
|
||||
|
||||
#include "action.h"
|
||||
#include "property_service.h"
|
||||
#include "selinux.h"
|
||||
#include "util.h"
|
||||
|
||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
||||
#include <sys/_system_properties.h>
|
||||
#if defined(__ANDROID__)
|
||||
#include "property_service.h"
|
||||
#include "selinux.h"
|
||||
#else
|
||||
#include "host_init_stubs.h"
|
||||
#endif
|
||||
|
||||
using android::base::GetExecutablePath;
|
||||
using android::base::Join;
|
||||
|
@ -83,7 +85,7 @@ std::vector<std::pair<std::string, std::string>> properties_to_set;
|
|||
|
||||
uint32_t SubcontextPropertySet(const std::string& name, const std::string& value) {
|
||||
properties_to_set.emplace_back(name, value);
|
||||
return PROP_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
class SubcontextProcess {
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
|
@ -42,7 +41,14 @@
|
|||
#include <selinux/android.h>
|
||||
|
||||
#include "reboot.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android-base/properties.h>
|
||||
|
||||
#include "selinux.h"
|
||||
#else
|
||||
#include "host_init_stubs.h"
|
||||
#endif
|
||||
|
||||
#ifdef _INIT_INIT_H
|
||||
#error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals"
|
||||
|
@ -409,5 +415,30 @@ bool is_android_dt_value_expected(const std::string& sub_path, const std::string
|
|||
return false;
|
||||
}
|
||||
|
||||
bool IsLegalPropertyName(const std::string& name) {
|
||||
size_t namelen = name.size();
|
||||
|
||||
if (namelen < 1) return false;
|
||||
if (name[0] == '.') return false;
|
||||
if (name[namelen - 1] == '.') return false;
|
||||
|
||||
/* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */
|
||||
/* Don't allow ".." to appear in a property name */
|
||||
for (size_t i = 0; i < namelen; i++) {
|
||||
if (name[i] == '.') {
|
||||
// i=0 is guaranteed to never have a dot. See above.
|
||||
if (name[i - 1] == '.') return false;
|
||||
continue;
|
||||
}
|
||||
if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') continue;
|
||||
if (name[i] >= 'a' && name[i] <= 'z') continue;
|
||||
if (name[i] >= 'A' && name[i] <= 'Z') continue;
|
||||
if (name[i] >= '0' && name[i] <= '9') continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
|
|
@ -62,6 +62,8 @@ const std::string& get_android_dt_dir();
|
|||
bool read_android_dt_file(const std::string& sub_path, std::string* dt_content);
|
||||
bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content);
|
||||
|
||||
bool IsLegalPropertyName(const std::string& name);
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
||||
|
|
Loading…
Reference in New Issue