Skip to content

Commit b5f2ec0

Browse files
author
Tom Cherry
committed
init: check property type in host_init_verifier
We have all of the 'type' information for properties available during build time, so let's check this when setting properties in init. Test: setprop apexd.status bad results in: host_init_verifier: Command 'setprop apexd.status bad' (out/soong/.intermediates/system/core/rootdir/init.rc/android_x86_core/init.rc:927) failed: Property type check failed, value doesn't match expected type 'enum starting ready' host_init_verifier: Failed to parse init script 'out/soong/.intermediates/system/core/rootdir/init.rc/android_x86_core/init.rc' with 1 errors Test: CF builds without that error Change-Id: Iaad07747c09f4a10b2b816c455d6e8a485357ab9
1 parent 1d28400 commit b5f2ec0

File tree

5 files changed

+92
-3
lines changed

5 files changed

+92
-3
lines changed

init/Android.bp

+3
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ cc_binary {
281281
static_libs: [
282282
"libbase",
283283
"libselinux",
284+
"libpropertyinfoserializer",
285+
"libpropertyinfoparser",
284286
],
285287
whole_static_libs: ["libcap"],
286288
shared_libs: [
@@ -304,6 +306,7 @@ cc_binary {
304306
"host_import_parser.cpp",
305307
"host_init_verifier.cpp",
306308
"parser.cpp",
309+
"property_type.cpp",
307310
"rlimit_parser.cpp",
308311
"tokenizer.cpp",
309312
"service.cpp",

init/check_builtins.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
#include <android-base/strings.h>
3030

3131
#include "builtin_arguments.h"
32+
#include "host_init_verifier.h"
3233
#include "interface_utils.h"
34+
#include "property_type.h"
3335
#include "rlimit_parser.h"
3436
#include "service.h"
3537
#include "util.h"
@@ -171,6 +173,15 @@ Result<void> check_setprop(const BuiltinArguments& args) {
171173
<< "' from init; use the restorecon builtin directly";
172174
}
173175

176+
const char* target_context = nullptr;
177+
const char* type = nullptr;
178+
property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
179+
180+
if (!CheckType(type, value)) {
181+
return Error() << "Property type check failed, value doesn't match expected type '"
182+
<< (type ?: "(null)") << "'";
183+
}
184+
174185
return {};
175186
}
176187

init/host_init_verifier.cpp

+50-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
// limitations under the License.
1515
//
1616

17+
#include "host_init_verifier.h"
18+
1719
#include <errno.h>
1820
#include <getopt.h>
1921
#include <pwd.h>
@@ -31,6 +33,7 @@
3133
#include <android-base/parseint.h>
3234
#include <android-base/strings.h>
3335
#include <hidl/metadata.h>
36+
#include <property_info_serializer/property_info_serializer.h>
3437

3538
#include "action.h"
3639
#include "action_manager.h"
@@ -53,6 +56,10 @@ using namespace std::literals;
5356
using android::base::ParseInt;
5457
using android::base::ReadFileToString;
5558
using android::base::Split;
59+
using android::properties::BuildTrie;
60+
using android::properties::ParsePropertyInfoFile;
61+
using android::properties::PropertyInfoArea;
62+
using android::properties::PropertyInfoEntry;
5663

5764
static std::vector<std::string> passwd_files;
5865

@@ -143,11 +150,12 @@ static Result<void> check_stub(const BuiltinArguments& args) {
143150
#include "generated_stub_builtin_function_map.h"
144151

145152
void PrintUsage() {
146-
std::cout << "usage: host_init_verifier [-p FILE] <init rc file>\n"
153+
std::cout << "usage: host_init_verifier [options] <init rc file>\n"
147154
"\n"
148155
"Tests an init script for correctness\n"
149156
"\n"
150157
"-p FILE\tSearch this passwd file for users and groups\n"
158+
"--property_contexts=FILE\t Use this file for property_contexts\n"
151159
<< std::endl;
152160
}
153161

@@ -172,23 +180,53 @@ Result<InterfaceInheritanceHierarchyMap> ReadInterfaceInheritanceHierarchy() {
172180
return result;
173181
}
174182

183+
const PropertyInfoArea* property_info_area;
184+
185+
void HandlePropertyContexts(const std::string& filename,
186+
std::vector<PropertyInfoEntry>* property_infos) {
187+
auto file_contents = std::string();
188+
if (!ReadFileToString(filename, &file_contents)) {
189+
PLOG(ERROR) << "Could not read properties from '" << filename << "'";
190+
exit(EXIT_FAILURE);
191+
}
192+
193+
auto errors = std::vector<std::string>{};
194+
ParsePropertyInfoFile(file_contents, property_infos, &errors);
195+
for (const auto& error : errors) {
196+
LOG(ERROR) << "Could not read line from '" << filename << "': " << error;
197+
}
198+
if (!errors.empty()) {
199+
exit(EXIT_FAILURE);
200+
}
201+
}
202+
175203
int main(int argc, char** argv) {
176204
android::base::InitLogging(argv, &android::base::StdioLogger);
177205
android::base::SetMinimumLogSeverity(android::base::ERROR);
178206

207+
auto property_infos = std::vector<PropertyInfoEntry>();
208+
179209
while (true) {
210+
static const char kPropertyContexts[] = "property-contexts=";
180211
static const struct option long_options[] = {
181212
{"help", no_argument, nullptr, 'h'},
213+
{kPropertyContexts, required_argument, nullptr, 0},
182214
{nullptr, 0, nullptr, 0},
183215
};
184216

185-
int arg = getopt_long(argc, argv, "p:", long_options, nullptr);
217+
int option_index;
218+
int arg = getopt_long(argc, argv, "p:", long_options, &option_index);
186219

187220
if (arg == -1) {
188221
break;
189222
}
190223

191224
switch (arg) {
225+
case 0:
226+
if (long_options[option_index].name == kPropertyContexts) {
227+
HandlePropertyContexts(optarg, &property_infos);
228+
}
229+
break;
192230
case 'h':
193231
PrintUsage();
194232
return EXIT_FAILURE;
@@ -216,6 +254,16 @@ int main(int argc, char** argv) {
216254
}
217255
SetKnownInterfaces(*interface_inheritance_hierarchy_map);
218256

257+
std::string serialized_contexts;
258+
std::string trie_error;
259+
if (!BuildTrie(property_infos, "u:object_r:default_prop:s0", "string", &serialized_contexts,
260+
&trie_error)) {
261+
LOG(ERROR) << "Unable to serialize property contexts: " << trie_error;
262+
return EXIT_FAILURE;
263+
}
264+
265+
property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_contexts.c_str());
266+
219267
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
220268
Action::set_function_map(&function_map);
221269
ActionManager& am = ActionManager::GetInstance();

init/host_init_verifier.h

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (C) 2019 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <property_info_parser/property_info_parser.h>
20+
21+
namespace android {
22+
namespace init {
23+
24+
extern const android::properties::PropertyInfoArea* property_info_area;
25+
26+
} // namespace init
27+
} // namespace android

init/property_service.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value,
478478
return PROP_ERROR_PERMISSION_DENIED;
479479
}
480480

481-
if (type == nullptr || !CheckType(type, value)) {
481+
if (!CheckType(type, value)) {
482482
*error = StringPrintf("Property type check failed, value doesn't match expected type '%s'",
483483
(type ?: "(null)"));
484484
return PROP_ERROR_INVALID_VALUE;

0 commit comments

Comments
 (0)