diff --git a/init/action.cpp b/init/action.cpp index 0c476df21..97b1c1a97 100644 --- a/init/action.cpp +++ b/init/action.cpp @@ -35,9 +35,11 @@ Result RunBuiltinFunction(const BuiltinFunction& function, builtin_arguments.args.resize(args.size()); builtin_arguments.args[0] = args[0]; for (std::size_t i = 1; i < args.size(); ++i) { - if (!expand_props(args[i], &builtin_arguments.args[i])) { - return Error() << "cannot expand '" << args[i] << "'"; + auto expanded_arg = ExpandProps(args[i]); + if (!expanded_arg) { + return expanded_arg.error(); } + builtin_arguments.args[i] = std::move(*expanded_arg); } return function(builtin_arguments); diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h index 7c0544ab1..f9a08a543 100644 --- a/init/host_init_stubs.h +++ b/init/host_init_stubs.h @@ -26,6 +26,7 @@ // android/api-level.h #define __ANDROID_API_P__ 28 +#define __ANDROID_API_R__ 30 // sys/system_properties.h #define PROP_VALUE_MAX 92 diff --git a/init/import_parser.cpp b/init/import_parser.cpp index c72b7d65e..1a43508d7 100644 --- a/init/import_parser.cpp +++ b/init/import_parser.cpp @@ -29,15 +29,14 @@ Result ImportParser::ParseSection(std::vector&& args, return Error() << "single argument needed for import\n"; } - std::string conf_file; - bool ret = expand_props(args[1], &conf_file); - if (!ret) { - return Error() << "error while expanding import"; + auto conf_file = ExpandProps(args[1]); + if (!conf_file) { + return Error() << "Could not expand import: " << conf_file.error(); } - LOG(INFO) << "Added '" << conf_file << "' to import list"; + LOG(INFO) << "Added '" << *conf_file << "' to import list"; if (filename_.empty()) filename_ = filename; - imports_.emplace_back(std::move(conf_file), line); + imports_.emplace_back(std::move(*conf_file), line); return {}; } diff --git a/init/property_service.cpp b/init/property_service.cpp index 37617505d..3819042e9 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -648,13 +648,14 @@ static void LoadProperties(char* data, const char* filter, const char* filename, } std::string raw_filename(fn); - std::string expanded_filename; - if (!expand_props(raw_filename, &expanded_filename)) { - LOG(ERROR) << "Could not expand filename '" << raw_filename << "'"; + auto expanded_filename = ExpandProps(raw_filename); + + if (!expanded_filename) { + LOG(ERROR) << "Could not expand filename ': " << expanded_filename.error(); continue; } - load_properties_from_file(expanded_filename.c_str(), key, properties); + load_properties_from_file(expanded_filename->c_str(), key, properties); } else { value = strchr(key, '='); if (!value) continue; diff --git a/init/selinux.cpp b/init/selinux.cpp index 54be08696..143cdfdae 100644 --- a/init/selinux.cpp +++ b/init/selinux.cpp @@ -497,24 +497,28 @@ void SelinuxSetupKernelLogging() { // This function returns the Android version with which the vendor SEPolicy was compiled. // It is used for version checks such as whether or not vendor_init should be used int SelinuxGetVendorAndroidVersion() { - if (!IsSplitPolicyDevice()) { - // If this device does not split sepolicy files, it's not a Treble device and therefore, - // we assume it's always on the latest platform. - return __ANDROID_API_FUTURE__; - } + static int vendor_android_version = [] { + if (!IsSplitPolicyDevice()) { + // If this device does not split sepolicy files, it's not a Treble device and therefore, + // we assume it's always on the latest platform. + return __ANDROID_API_FUTURE__; + } - std::string version; - if (!GetVendorMappingVersion(&version)) { - LOG(FATAL) << "Could not read vendor SELinux version"; - } + std::string version; + if (!GetVendorMappingVersion(&version)) { + LOG(FATAL) << "Could not read vendor SELinux version"; + } - int major_version; - std::string major_version_str(version, 0, version.find('.')); - if (!ParseInt(major_version_str, &major_version)) { - PLOG(FATAL) << "Failed to parse the vendor sepolicy major version " << major_version_str; - } + int major_version; + std::string major_version_str(version, 0, version.find('.')); + if (!ParseInt(major_version_str, &major_version)) { + PLOG(FATAL) << "Failed to parse the vendor sepolicy major version " + << major_version_str; + } - return major_version; + return major_version; + }(); + return vendor_android_version; } // This function initializes SELinux then execs init to run in the init SELinux context. diff --git a/init/service.cpp b/init/service.cpp index 47f4db94e..380c93bfe 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -100,9 +100,11 @@ static bool ExpandArgsAndExecv(const std::vector& args, bool sigsto expanded_args.resize(args.size()); c_strings.push_back(const_cast(args[0].data())); for (std::size_t i = 1; i < args.size(); ++i) { - if (!expand_props(args[i], &expanded_args[i])) { - LOG(FATAL) << args[0] << ": cannot expand '" << args[i] << "'"; + auto expanded_arg = ExpandProps(args[i]); + if (!expanded_arg) { + LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error(); } + expanded_args[i] = *expanded_arg; c_strings.push_back(expanded_args[i].data()); } c_strings.push_back(nullptr); diff --git a/init/service_parser.cpp b/init/service_parser.cpp index 65d96c665..e45e80415 100644 --- a/init/service_parser.cpp +++ b/init/service_parser.cpp @@ -193,9 +193,9 @@ Result ServiceParser::ParseIoprio(std::vector&& args) { Result ServiceParser::ParseKeycodes(std::vector&& args) { auto it = args.begin() + 1; if (args.size() == 2 && StartsWith(args[1], "$")) { - std::string expanded; - if (!expand_props(args[1], &expanded)) { - return Error() << "Could not expand property '" << args[1] << "'"; + auto expanded = ExpandProps(args[1]); + if (!expanded) { + return expanded.error(); } // If the property is not set, it defaults to none, in which case there are no keycodes @@ -204,7 +204,7 @@ Result ServiceParser::ParseKeycodes(std::vector&& args) { return {}; } - args = Split(expanded, ","); + args = Split(*expanded, ","); it = args.begin(); } @@ -422,9 +422,11 @@ Result ServiceParser::ParseFile(std::vector&& args) { FileDescriptor file; file.type = args[2]; - if (!expand_props(args[1], &file.name)) { - return Error() << "Could not expand property in file path '" << args[1] << "'"; + auto file_name = ExpandProps(args[1]); + if (!file_name) { + return Error() << "Could not expand file path ': " << file_name.error(); } + file.name = *file_name; if (file.name[0] != '/' || file.name.find("../") != std::string::npos) { return Error() << "file name must not be relative"; } diff --git a/init/subcontext.cpp b/init/subcontext.cpp index a13f0c766..00f91d830 100644 --- a/init/subcontext.cpp +++ b/init/subcontext.cpp @@ -151,15 +151,15 @@ void SubcontextProcess::RunCommand(const SubcontextCommand::ExecuteCommand& exec void SubcontextProcess::ExpandArgs(const SubcontextCommand::ExpandArgsCommand& expand_args_command, SubcontextReply* reply) const { for (const auto& arg : expand_args_command.args()) { - auto expanded_prop = std::string{}; - if (!expand_props(arg, &expanded_prop)) { + auto expanded_arg = ExpandProps(arg); + if (!expanded_arg) { auto* failure = reply->mutable_failure(); - failure->set_error_string("Failed to expand '" + arg + "'"); + failure->set_error_string(expanded_arg.error().message()); failure->set_error_errno(0); return; } else { auto* expand_args_reply = reply->mutable_expand_args_reply(); - expand_args_reply->add_expanded_args(expanded_prop); + expand_args_reply->add_expanded_args(*expanded_arg); } } } diff --git a/init/subcontext_test.cpp b/init/subcontext_test.cpp index e120a6272..ae89c389c 100644 --- a/init/subcontext_test.cpp +++ b/init/subcontext_test.cpp @@ -166,7 +166,8 @@ TEST(subcontext, ExpandArgsFailure) { }; auto result = subcontext.ExpandArgs(args); ASSERT_FALSE(result); - EXPECT_EQ("Failed to expand '" + args[1] + "'", result.error().message()); + EXPECT_EQ("unexpected end of string in '" + args[1] + "', looking for }", + result.error().message()); }); } diff --git a/init/util.cpp b/init/util.cpp index 8bfb75598..169f086e0 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -41,8 +41,11 @@ #include #if defined(__ANDROID__) +#include + #include "reboot_utils.h" #include "selabel.h" +#include "selinux.h" #else #include "host_init_stubs.h" #endif @@ -267,12 +270,10 @@ bool is_dir(const char* pathname) { return S_ISDIR(info.st_mode); } -bool expand_props(const std::string& src, std::string* dst) { +Result ExpandProps(const std::string& src) { const char* src_ptr = src.c_str(); - if (!dst) { - return false; - } + std::string dst; /* - variables can either be $x.y or ${x.y}, in case they are only part * of the string. @@ -286,19 +287,19 @@ bool expand_props(const std::string& src, std::string* dst) { c = strchr(src_ptr, '$'); if (!c) { - dst->append(src_ptr); - return true; + dst.append(src_ptr); + return dst; } - dst->append(src_ptr, c); + dst.append(src_ptr, c); c++; if (*c == '$') { - dst->push_back(*(c++)); + dst.push_back(*(c++)); src_ptr = c; continue; } else if (*c == '\0') { - return true; + return dst; } std::string prop_name; @@ -308,8 +309,7 @@ bool expand_props(const std::string& src, std::string* dst) { const char* end = strchr(c, '}'); if (!end) { // failed to find closing brace, abort. - LOG(ERROR) << "unexpected end of string in '" << src << "', looking for }"; - return false; + return Error() << "unexpected end of string in '" << src << "', looking for }"; } prop_name = std::string(c, end); c = end + 1; @@ -320,29 +320,34 @@ bool expand_props(const std::string& src, std::string* dst) { } } else { prop_name = c; - LOG(ERROR) << "using deprecated syntax for specifying property '" << c << "', use ${name} instead"; + if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) { + return Error() << "using deprecated syntax for specifying property '" << c + << "', use ${name} instead"; + } else { + LOG(ERROR) << "using deprecated syntax for specifying property '" << c + << "', use ${name} instead"; + } c += prop_name.size(); } if (prop_name.empty()) { - LOG(ERROR) << "invalid zero-length property name in '" << src << "'"; - return false; + return Error() << "invalid zero-length property name in '" << src << "'"; } std::string prop_val = android::base::GetProperty(prop_name, ""); if (prop_val.empty()) { if (def_val.empty()) { - LOG(ERROR) << "property '" << prop_name << "' doesn't exist while expanding '" << src << "'"; - return false; + return Error() << "property '" << prop_name << "' doesn't exist while expanding '" + << src << "'"; } prop_val = def_val; } - dst->append(prop_val); + dst.append(prop_val); src_ptr = c; } - return true; + return dst; } static std::string init_android_dt_dir() { diff --git a/init/util.h b/init/util.h index 6a12fb6f1..98de1f2bb 100644 --- a/init/util.h +++ b/init/util.h @@ -52,7 +52,7 @@ void import_kernel_cmdline(bool in_qemu, const std::function&); bool make_dir(const std::string& path, mode_t mode); bool is_dir(const char* pathname); -bool expand_props(const std::string& src, std::string* dst); +Result ExpandProps(const std::string& src); // Returns the platform's Android DT directory as specified in the kernel cmdline. // If the platform does not configure a custom DT path, returns the standard one (based in procfs).