blob: cdfaff3c59df28bee49f37ea0de3f26efe7c80a9 [file] [log] [blame]
Tom Cherry2aeb1ad2019-06-26 10:46:20 -07001/*
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#include "service_parser.h"
18
19#include <android-base/strings.h>
20
21#include "util.h"
22
23#if defined(__ANDROID__)
24#include <sys/system_properties.h>
25
26#include "selinux.h"
27#else
28#include "host_init_stubs.h"
29#endif
30
31using android::base::StartsWith;
32
33namespace android {
34namespace init {
35
36Result<void> ServiceParser::ParseSection(std::vector<std::string>&& args,
37 const std::string& filename, int line) {
38 if (args.size() < 3) {
39 return Error() << "services must have a name and a program";
40 }
41
42 const std::string& name = args[1];
43 if (!IsValidName(name)) {
44 return Error() << "invalid service name '" << name << "'";
45 }
46
47 filename_ = filename;
48
49 Subcontext* restart_action_subcontext = nullptr;
50 if (subcontexts_) {
51 for (auto& subcontext : *subcontexts_) {
52 if (StartsWith(filename, subcontext.path_prefix())) {
53 restart_action_subcontext = &subcontext;
54 break;
55 }
56 }
57 }
58
59 std::vector<std::string> str_args(args.begin() + 2, args.end());
60
61 if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_P__) {
62 if (str_args[0] == "/sbin/watchdogd") {
63 str_args[0] = "/system/bin/watchdogd";
64 }
65 }
66
67 service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
68 return {};
69}
70
71Result<void> ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line) {
72 return service_ ? service_->ParseLine(std::move(args)) : Result<void>{};
73}
74
75Result<void> ServiceParser::EndSection() {
76 if (service_) {
77 Service* old_service = service_list_->FindService(service_->name());
78 if (old_service) {
79 if (!service_->is_override()) {
80 return Error() << "ignored duplicate definition of service '" << service_->name()
81 << "'";
82 }
83
84 if (StartsWith(filename_, "/apex/") && !old_service->is_updatable()) {
85 return Error() << "cannot update a non-updatable service '" << service_->name()
86 << "' with a config in APEX";
87 }
88
89 service_list_->RemoveService(*old_service);
90 old_service = nullptr;
91 }
92
93 service_list_->AddService(std::move(service_));
94 }
95
96 return {};
97}
98
99bool ServiceParser::IsValidName(const std::string& name) const {
100 // Property names can be any length, but may only contain certain characters.
101 // Property values can contain any characters, but may only be a certain length.
102 // (The latter restriction is needed because `start` and `stop` work by writing
103 // the service name to the "ctl.start" and "ctl.stop" properties.)
104 return IsLegalPropertyName("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
105}
106
107} // namespace init
108} // namespace android