Skip to content

Commit de6bd50

Browse files
author
Tom Cherry
committed
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
1 parent 304daca commit de6bd50

17 files changed

+369
-56
lines changed

init/Android.bp

+55
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,59 @@ cc_benchmark {
194194
static_libs: ["libinit"],
195195
}
196196

197+
// Host Verifier
198+
// ------------------------------------------------------------------------------
199+
200+
genrule {
201+
name: "generated_stub_builtin_function_map",
202+
out: ["generated_stub_builtin_function_map.h"],
203+
srcs: ["builtins.cpp"],
204+
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)"
205+
}
206+
207+
cc_binary {
208+
name: "host_init_verifier",
209+
host_supported: true,
210+
cpp_std: "experimental",
211+
cflags: [
212+
"-Wall",
213+
"-Wextra",
214+
"-Wno-unused-parameter",
215+
"-Werror",
216+
],
217+
static_libs: [
218+
"libbase",
219+
"libselinux",
220+
],
221+
whole_static_libs: ["libcap"],
222+
shared_libs: [
223+
"libprotobuf-cpp-lite",
224+
"libhidl-gen-utils",
225+
"libprocessgroup",
226+
"liblog",
227+
"libcutils",
228+
],
229+
srcs: [
230+
"action.cpp",
231+
"action_manager.cpp",
232+
"action_parser.cpp",
233+
"capabilities.cpp",
234+
"descriptors.cpp",
235+
"import_parser.cpp",
236+
"host_init_parser.cpp",
237+
"host_init_stubs.cpp",
238+
"parser.cpp",
239+
"rlimit_parser.cpp",
240+
"tokenizer.cpp",
241+
"service.cpp",
242+
"subcontext.cpp",
243+
"subcontext.proto",
244+
"util.cpp",
245+
],
246+
proto: {
247+
type: "lite",
248+
},
249+
generated_headers: ["generated_stub_builtin_function_map"],
250+
}
251+
197252
subdirs = ["*"]

init/action.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,16 @@
1818

1919
#include <android-base/chrono_utils.h>
2020
#include <android-base/logging.h>
21-
#include <android-base/properties.h>
2221
#include <android-base/strings.h>
2322

2423
#include "util.h"
2524

25+
#if defined(__ANDROID__)
26+
#include <android-base/properties.h>
27+
#else
28+
#include "host_init_stubs.h"
29+
#endif
30+
2631
using android::base::Join;
2732

2833
namespace android {

init/action_parser.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@
1616

1717
#include "action_parser.h"
1818

19-
#include <android-base/properties.h>
2019
#include <android-base/strings.h>
2120

2221
#include "stable_properties.h"
2322

23+
#if defined(__ANDROID__)
24+
#include <android-base/properties.h>
25+
#else
26+
#include "host_init_stubs.h"
27+
#endif
28+
2429
using android::base::GetBoolProperty;
2530
using android::base::StartsWith;
2631

init/builtins.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -968,8 +968,8 @@ static Result<Success> do_wait_for_prop(const BuiltinArguments& args) {
968968
const char* value = args[2].c_str();
969969
size_t value_len = strlen(value);
970970

971-
if (!is_legal_property_name(name)) {
972-
return Error() << "is_legal_property_name(" << name << ") failed";
971+
if (!IsLegalPropertyName(name)) {
972+
return Error() << "IsLegalPropertyName(" << name << ") failed";
973973
}
974974
if (value_len >= PROP_VALUE_MAX) {
975975
return Error() << "value too long";
@@ -1018,6 +1018,7 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) {
10181018
{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"});
10191019
}
10201020

1021+
// Builtin-function-map start
10211022
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
10221023
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
10231024
// clang-format off
@@ -1075,6 +1076,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
10751076
// clang-format on
10761077
return builtin_functions;
10771078
}
1079+
// Builtin-function-map end
10781080

10791081
} // namespace init
10801082
} // namespace android

init/capabilities.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#include "capabilities.h"
1616

17-
#include <sys/capability.h>
1817
#include <sys/prctl.h>
1918

2019
#include <map>
@@ -72,17 +71,25 @@ static const std::map<std::string, int> cap_map = {
7271
static_assert(CAP_LAST_CAP == CAP_AUDIT_READ, "CAP_LAST_CAP is not CAP_AUDIT_READ");
7372

7473
static bool ComputeCapAmbientSupported() {
74+
#if defined(__ANDROID__)
7575
return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >= 0;
76+
#else
77+
return true;
78+
#endif
7679
}
7780

7881
static unsigned int ComputeLastValidCap() {
82+
#if defined(__ANDROID__)
7983
// Android does not support kernels < 3.8. 'CAP_WAKE_ALARM' has been present since 3.0, see
8084
// http://lxr.free-electrons.com/source/include/linux/capability.h?v=3.0#L360.
8185
unsigned int last_valid_cap = CAP_WAKE_ALARM;
8286
for (; prctl(PR_CAPBSET_READ, last_valid_cap, 0, 0, 0) >= 0; ++last_valid_cap);
8387

8488
// |last_valid_cap| will be the first failing value.
8589
return last_valid_cap - 1;
90+
#else
91+
return CAP_LAST_CAP;
92+
#endif
8693
}
8794

8895
static bool DropBoundingSet(const CapSet& to_keep) {
@@ -139,6 +146,7 @@ static bool SetProcCaps(const CapSet& to_keep, bool add_setpcap) {
139146
}
140147

141148
static bool SetAmbientCaps(const CapSet& to_raise) {
149+
#if defined(__ANDROID__)
142150
for (size_t cap = 0; cap < to_raise.size(); ++cap) {
143151
if (to_raise.test(cap)) {
144152
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) != 0) {
@@ -147,6 +155,7 @@ static bool SetAmbientCaps(const CapSet& to_raise) {
147155
}
148156
}
149157
}
158+
#endif
150159
return true;
151160
}
152161

init/capabilities.h

+11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121
#include <string>
2222
#include <type_traits>
2323

24+
#if !defined(__ANDROID__)
25+
#ifndef CAP_BLOCK_SUSPEND
26+
#define CAP_BLOCK_SUSPEND 36
27+
#endif
28+
#ifndef CAP_AUDIT_READ
29+
#define CAP_AUDIT_READ 37
30+
#endif
31+
#undef CAP_LAST_CAP
32+
#define CAP_LAST_CAP CAP_AUDIT_READ
33+
#endif
34+
2435
namespace android {
2536
namespace init {
2637

init/host_init_parser.cpp

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//
2+
// Copyright (C) 2018 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+
#include <pwd.h>
18+
19+
#include <android-base/logging.h>
20+
21+
#include "action.h"
22+
#include "action_manager.h"
23+
#include "action_parser.h"
24+
#include "parser.h"
25+
#include "result.h"
26+
#include "service.h"
27+
28+
// The host passwd file won't have the Android entries, so we fake success here.
29+
passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
30+
char dummy_buf[] = "dummy";
31+
static passwd dummy_passwd = {
32+
.pw_name = dummy_buf,
33+
.pw_dir = dummy_buf,
34+
.pw_shell = dummy_buf,
35+
.pw_uid = 123,
36+
.pw_gid = 123,
37+
};
38+
return &dummy_passwd;
39+
}
40+
41+
namespace android {
42+
namespace init {
43+
44+
static Result<Success> do_stub(const BuiltinArguments& args) {
45+
return Success();
46+
}
47+
48+
#include "generated_stub_builtin_function_map.h"
49+
50+
int main(int argc, char** argv) {
51+
android::base::InitLogging(argv, &android::base::StderrLogger);
52+
if (argc != 2) {
53+
LOG(ERROR) << "Usage: " << argv[0] << " <init file to parse>";
54+
return -1;
55+
}
56+
const BuiltinFunctionMap function_map;
57+
Action::set_function_map(&function_map);
58+
ActionManager& am = ActionManager::GetInstance();
59+
ServiceList& sl = ServiceList::GetInstance();
60+
Parser parser;
61+
parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sl, nullptr));
62+
parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
63+
64+
size_t num_errors = 0;
65+
if (!parser.ParseConfig(argv[1], &num_errors)) {
66+
LOG(ERROR) << "Failed to find script";
67+
return -1;
68+
}
69+
if (num_errors > 0) {
70+
LOG(ERROR) << "Parse failed with " << num_errors << " errors";
71+
return -1;
72+
}
73+
LOG(INFO) << "Parse success!";
74+
return 0;
75+
}
76+
77+
} // namespace init
78+
} // namespace android
79+
80+
int main(int argc, char** argv) {
81+
android::init::main(argc, argv);
82+
}

init/host_init_stubs.cpp

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (C) 2018 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+
#include "host_init_stubs.h"
18+
19+
// unistd.h
20+
int setgroups(size_t __size, const gid_t* __list) {
21+
return 0;
22+
}
23+
24+
namespace android {
25+
namespace base {
26+
27+
std::string GetProperty(const std::string&, const std::string& default_value) {
28+
return default_value;
29+
}
30+
31+
bool GetBoolProperty(const std::string&, bool default_value) {
32+
return default_value;
33+
}
34+
35+
} // namespace base
36+
} // namespace android
37+
38+
namespace android {
39+
namespace init {
40+
41+
// init.h
42+
std::string default_console = "/dev/console";
43+
44+
// property_service.h
45+
uint32_t (*property_set)(const std::string& name, const std::string& value) = nullptr;
46+
uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&,
47+
const ucred&) {
48+
return 0;
49+
}
50+
51+
// selinux.h
52+
void SelabelInitialize() {}
53+
54+
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
55+
return false;
56+
}
57+
58+
} // namespace init
59+
} // namespace android

init/host_init_stubs.h

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (C) 2018 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+
#ifndef _INIT_HOST_INIT_STUBS_H
18+
#define _INIT_HOST_INIT_STUBS_H
19+
20+
#include <stddef.h>
21+
#include <sys/socket.h>
22+
#include <sys/types.h>
23+
24+
#include <string>
25+
26+
// sys/system_properties.h
27+
#define PROP_VALUE_MAX 92
28+
29+
// unistd.h
30+
int setgroups(size_t __size, const gid_t* __list);
31+
32+
// android-base/properties.h
33+
namespace android {
34+
namespace base {
35+
36+
std::string GetProperty(const std::string& key, const std::string& default_value);
37+
bool GetBoolProperty(const std::string& key, bool default_value);
38+
39+
} // namespace base
40+
} // namespace android
41+
42+
namespace android {
43+
namespace init {
44+
45+
// init.h
46+
extern std::string default_console;
47+
48+
// property_service.h
49+
extern uint32_t (*property_set)(const std::string& name, const std::string& value);
50+
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
51+
const std::string& source_context, const ucred& cr);
52+
53+
// selinux.h
54+
void SelabelInitialize();
55+
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
56+
57+
} // namespace init
58+
} // namespace android
59+
60+
#endif

0 commit comments

Comments
 (0)