blob: 481fa31e5eb1047c77f3f54f01f2e76320d533eb [file] [log] [blame]
Tom Cherry4772f1d2019-07-30 09:34:41 -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// Note that these check functions cannot check expanded arguments from properties, since they will
18// not know what those properties would be at runtime. They will be passed an empty string in the
19// situation that the input line had a property expansion without a default value, since an empty
20// string is otherwise an impossible value. They should therefore disregard checking empty
21// arguments.
22
23#include "check_builtins.h"
24
25#include <sys/time.h>
26
27#include <android-base/logging.h>
Mark Salyzyn61de0d22020-05-14 09:20:30 -070028#include <android-base/parsedouble.h>
Tom Cherry4772f1d2019-07-30 09:34:41 -070029#include <android-base/parseint.h>
30#include <android-base/strings.h>
31
32#include "builtin_arguments.h"
Tom Cherryb5f2ec02019-11-08 17:54:27 -080033#include "host_init_verifier.h"
Daniel Normand2533c32019-08-02 15:13:50 -070034#include "interface_utils.h"
Tom Cherryb5f2ec02019-11-08 17:54:27 -080035#include "property_type.h"
Tom Cherry4772f1d2019-07-30 09:34:41 -070036#include "rlimit_parser.h"
37#include "service.h"
38#include "util.h"
39
40using android::base::ParseInt;
41using android::base::StartsWith;
42
43#define ReturnIfAnyArgsEmpty() \
44 for (const auto& arg : args) { \
45 if (arg.empty()) { \
46 return {}; \
47 } \
48 }
49
50namespace android {
51namespace init {
52
53Result<void> check_chown(const BuiltinArguments& args) {
54 if (!args[1].empty()) {
55 auto uid = DecodeUid(args[1]);
Bernie Innocenticecebbb2020-02-06 03:49:33 +090056 if (!uid.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -070057 return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
58 }
59 }
60
61 // GID is optional and pushes the index of path out by one if specified.
62 if (args.size() == 4 && !args[2].empty()) {
63 auto gid = DecodeUid(args[2]);
Bernie Innocenticecebbb2020-02-06 03:49:33 +090064 if (!gid.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -070065 return Error() << "Unable to decode GID for '" << args[2] << "': " << gid.error();
66 }
67 }
68
69 return {};
70}
71
72Result<void> check_exec(const BuiltinArguments& args) {
73 ReturnIfAnyArgsEmpty();
74
75 auto result = Service::MakeTemporaryOneshotService(args.args);
Bernie Innocenticecebbb2020-02-06 03:49:33 +090076 if (!result.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -070077 return result.error();
78 }
79
80 return {};
81}
82
83Result<void> check_exec_background(const BuiltinArguments& args) {
84 return check_exec(std::move(args));
85}
86
Tom Cherry7896e7a2019-09-04 15:26:52 -070087Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args) {
88 BuiltinArguments remaining_args(args.context);
89
90 remaining_args.args = std::vector<std::string>(args.begin() + 1, args.end());
91 remaining_args.args[0] = args[0];
92
93 return check_exec(remaining_args);
94}
95
Daniel Normand2533c32019-08-02 15:13:50 -070096Result<void> check_interface_restart(const BuiltinArguments& args) {
Bernie Innocenticecebbb2020-02-06 03:49:33 +090097 if (auto result = IsKnownInterface(args[1]); !result.ok()) {
Daniel Normand2533c32019-08-02 15:13:50 -070098 return result.error();
99 }
100 return {};
101}
102
103Result<void> check_interface_start(const BuiltinArguments& args) {
104 return check_interface_restart(std::move(args));
105}
106
107Result<void> check_interface_stop(const BuiltinArguments& args) {
108 return check_interface_restart(std::move(args));
109}
110
Tom Cherry4772f1d2019-07-30 09:34:41 -0700111Result<void> check_load_system_props(const BuiltinArguments& args) {
112 return Error() << "'load_system_props' is deprecated";
113}
114
115Result<void> check_loglevel(const BuiltinArguments& args) {
116 ReturnIfAnyArgsEmpty();
117
118 int log_level = -1;
119 ParseInt(args[1], &log_level);
120 if (log_level < 0 || log_level > 7) {
121 return Error() << "loglevel must be in the range of 0-7";
122 }
123 return {};
124}
125
Alistair Delvac631f942020-05-20 16:24:00 -0700126Result<void> check_mount_all(const BuiltinArguments& args) {
127 auto options = ParseMountAll(args.args);
128 if (!options.ok()) {
129 return options.error();
130 }
131 return {};
132}
133
Tom Cherry4772f1d2019-07-30 09:34:41 -0700134Result<void> check_mkdir(const BuiltinArguments& args) {
Paul Crowley68258e82019-10-28 07:55:03 -0700135 auto options = ParseMkdir(args.args);
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900136 if (!options.ok()) {
Paul Crowley68258e82019-10-28 07:55:03 -0700137 return options.error();
Tom Cherry4772f1d2019-07-30 09:34:41 -0700138 }
Tom Cherry4772f1d2019-07-30 09:34:41 -0700139 return {};
140}
141
142Result<void> check_restorecon(const BuiltinArguments& args) {
143 ReturnIfAnyArgsEmpty();
144
145 auto restorecon_info = ParseRestorecon(args.args);
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900146 if (!restorecon_info.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -0700147 return restorecon_info.error();
148 }
149
150 return {};
151}
152
153Result<void> check_restorecon_recursive(const BuiltinArguments& args) {
154 return check_restorecon(std::move(args));
155}
156
157Result<void> check_setprop(const BuiltinArguments& args) {
158 const std::string& name = args[1];
159 if (name.empty()) {
160 return {};
161 }
162 const std::string& value = args[2];
163
164 if (!IsLegalPropertyName(name)) {
165 return Error() << "'" << name << "' is not a legal property name";
166 }
167
168 if (!value.empty()) {
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900169 if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -0700170 return result.error();
171 }
172 }
173
174 if (StartsWith(name, "ctl.")) {
175 return Error()
176 << "Do not set ctl. properties from init; call the Service functions directly";
177 }
178
179 static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive";
180 if (name == kRestoreconProperty) {
181 return Error() << "Do not set '" << kRestoreconProperty
182 << "' from init; use the restorecon builtin directly";
183 }
184
Tom Cherryb5f2ec02019-11-08 17:54:27 -0800185 const char* target_context = nullptr;
186 const char* type = nullptr;
187 property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
188
189 if (!CheckType(type, value)) {
190 return Error() << "Property type check failed, value doesn't match expected type '"
191 << (type ?: "(null)") << "'";
192 }
193
Tom Cherry4772f1d2019-07-30 09:34:41 -0700194 return {};
195}
196
197Result<void> check_setrlimit(const BuiltinArguments& args) {
198 ReturnIfAnyArgsEmpty();
199
200 auto rlimit = ParseRlimit(args.args);
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900201 if (!rlimit.ok()) return rlimit.error();
Tom Cherry4772f1d2019-07-30 09:34:41 -0700202 return {};
203}
204
Alistair Delvaafaa5fb2020-06-08 11:04:53 -0700205Result<void> check_swapon_all(const BuiltinArguments& args) {
206 auto options = ParseSwaponAll(args.args);
207 if (!options.ok()) {
208 return options.error();
209 }
210 return {};
211}
212
Tom Cherry4772f1d2019-07-30 09:34:41 -0700213Result<void> check_sysclktz(const BuiltinArguments& args) {
214 ReturnIfAnyArgsEmpty();
215
216 struct timezone tz = {};
217 if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
218 return Error() << "Unable to parse mins_west_of_gmt";
219 }
220 return {};
221}
222
Alistair Delvac631f942020-05-20 16:24:00 -0700223Result<void> check_umount_all(const BuiltinArguments& args) {
224 auto options = ParseUmountAll(args.args);
225 if (!options.ok()) {
226 return options.error();
227 }
228 return {};
229}
230
Tom Cherry4772f1d2019-07-30 09:34:41 -0700231Result<void> check_wait(const BuiltinArguments& args) {
232 if (args.size() == 3 && !args[2].empty()) {
Mark Salyzyn61de0d22020-05-14 09:20:30 -0700233 double timeout_double;
234 if (!android::base::ParseDouble(args[2], &timeout_double, 0)) {
Tom Cherry4772f1d2019-07-30 09:34:41 -0700235 return Error() << "failed to parse timeout";
236 }
237 }
238 return {};
239}
240
241Result<void> check_wait_for_prop(const BuiltinArguments& args) {
242 return check_setprop(std::move(args));
243}
244
245} // namespace init
246} // namespace android