blob: 97254580cd279266ff2afa954f2ab8a5fb5e0abd [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 Salyzynffa52e92020-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>
Jooyung Han39e8be42024-02-16 17:23:34 +090031#include <property_info_parser/property_info_parser.h>
Tom Cherry4772f1d2019-07-30 09:34:41 -070032
33#include "builtin_arguments.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;
Jooyung Han39e8be42024-02-16 17:23:34 +090042using android::properties::BuildTrie;
43using android::properties::PropertyInfoArea;
44using android::properties::PropertyInfoEntry;
Tom Cherry4772f1d2019-07-30 09:34:41 -070045
46#define ReturnIfAnyArgsEmpty() \
47 for (const auto& arg : args) { \
48 if (arg.empty()) { \
49 return {}; \
50 } \
51 }
52
53namespace android {
54namespace init {
55
Jooyung Han39e8be42024-02-16 17:23:34 +090056const PropertyInfoArea* property_info_area;
57
58Result<void> InitializeHostPropertyInfoArea(const std::vector<PropertyInfoEntry>& property_infos) {
59 static std::string serialized_contexts;
60 std::string trie_error;
61 if (!BuildTrie(property_infos, "u:object_r:default_prop:s0", "string", &serialized_contexts,
62 &trie_error)) {
63 return Error() << "Unable to serialize property contexts: " << trie_error;
64 }
65
66 property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_contexts.c_str());
67 return {};
68}
69
70static Result<void> check_stub(const BuiltinArguments& args) {
71 return {};
72}
73
74#include "generated_stub_builtin_function_map.h"
75
Tom Cherry4772f1d2019-07-30 09:34:41 -070076Result<void> check_chown(const BuiltinArguments& args) {
77 if (!args[1].empty()) {
78 auto uid = DecodeUid(args[1]);
Bernie Innocenticecebbb2020-02-06 03:49:33 +090079 if (!uid.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -070080 return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
81 }
82 }
83
84 // GID is optional and pushes the index of path out by one if specified.
85 if (args.size() == 4 && !args[2].empty()) {
86 auto gid = DecodeUid(args[2]);
Bernie Innocenticecebbb2020-02-06 03:49:33 +090087 if (!gid.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -070088 return Error() << "Unable to decode GID for '" << args[2] << "': " << gid.error();
89 }
90 }
91
92 return {};
93}
94
95Result<void> check_exec(const BuiltinArguments& args) {
96 ReturnIfAnyArgsEmpty();
97
98 auto result = Service::MakeTemporaryOneshotService(args.args);
Bernie Innocenticecebbb2020-02-06 03:49:33 +090099 if (!result.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -0700100 return result.error();
101 }
102
103 return {};
104}
105
106Result<void> check_exec_background(const BuiltinArguments& args) {
107 return check_exec(std::move(args));
108}
109
Tom Cherry7896e7a2019-09-04 15:26:52 -0700110Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args) {
Bart Van Assche3dfb8bc2023-02-22 10:01:33 -0800111 BuiltinArguments remaining_args{.context = args.context};
Tom Cherry7896e7a2019-09-04 15:26:52 -0700112
113 remaining_args.args = std::vector<std::string>(args.begin() + 1, args.end());
114 remaining_args.args[0] = args[0];
115
116 return check_exec(remaining_args);
117}
118
Daniel Normand2533c32019-08-02 15:13:50 -0700119Result<void> check_interface_restart(const BuiltinArguments& args) {
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900120 if (auto result = IsKnownInterface(args[1]); !result.ok()) {
Daniel Normand2533c32019-08-02 15:13:50 -0700121 return result.error();
122 }
123 return {};
124}
125
126Result<void> check_interface_start(const BuiltinArguments& args) {
127 return check_interface_restart(std::move(args));
128}
129
130Result<void> check_interface_stop(const BuiltinArguments& args) {
131 return check_interface_restart(std::move(args));
132}
133
Tom Cherry4772f1d2019-07-30 09:34:41 -0700134Result<void> check_load_system_props(const BuiltinArguments& args) {
135 return Error() << "'load_system_props' is deprecated";
136}
137
138Result<void> check_loglevel(const BuiltinArguments& args) {
139 ReturnIfAnyArgsEmpty();
140
141 int log_level = -1;
142 ParseInt(args[1], &log_level);
143 if (log_level < 0 || log_level > 7) {
144 return Error() << "loglevel must be in the range of 0-7";
145 }
146 return {};
147}
148
Alistair Delvaa2cc1eb2020-05-20 16:24:00 -0700149Result<void> check_mount_all(const BuiltinArguments& args) {
150 auto options = ParseMountAll(args.args);
151 if (!options.ok()) {
152 return options.error();
153 }
154 return {};
155}
156
Tom Cherry4772f1d2019-07-30 09:34:41 -0700157Result<void> check_mkdir(const BuiltinArguments& args) {
Paul Crowley68258e82019-10-28 07:55:03 -0700158 auto options = ParseMkdir(args.args);
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900159 if (!options.ok()) {
Paul Crowley68258e82019-10-28 07:55:03 -0700160 return options.error();
Tom Cherry4772f1d2019-07-30 09:34:41 -0700161 }
Tom Cherry4772f1d2019-07-30 09:34:41 -0700162 return {};
163}
164
165Result<void> check_restorecon(const BuiltinArguments& args) {
166 ReturnIfAnyArgsEmpty();
167
168 auto restorecon_info = ParseRestorecon(args.args);
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900169 if (!restorecon_info.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -0700170 return restorecon_info.error();
171 }
172
173 return {};
174}
175
176Result<void> check_restorecon_recursive(const BuiltinArguments& args) {
177 return check_restorecon(std::move(args));
178}
179
180Result<void> check_setprop(const BuiltinArguments& args) {
181 const std::string& name = args[1];
182 if (name.empty()) {
183 return {};
184 }
185 const std::string& value = args[2];
186
187 if (!IsLegalPropertyName(name)) {
188 return Error() << "'" << name << "' is not a legal property name";
189 }
190
191 if (!value.empty()) {
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900192 if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {
Tom Cherry4772f1d2019-07-30 09:34:41 -0700193 return result.error();
194 }
195 }
196
197 if (StartsWith(name, "ctl.")) {
198 return Error()
199 << "Do not set ctl. properties from init; call the Service functions directly";
200 }
201
202 static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive";
203 if (name == kRestoreconProperty) {
204 return Error() << "Do not set '" << kRestoreconProperty
205 << "' from init; use the restorecon builtin directly";
206 }
207
Tom Cherryb5f2ec02019-11-08 17:54:27 -0800208 const char* target_context = nullptr;
209 const char* type = nullptr;
210 property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
211
212 if (!CheckType(type, value)) {
213 return Error() << "Property type check failed, value doesn't match expected type '"
214 << (type ?: "(null)") << "'";
215 }
216
Tom Cherry4772f1d2019-07-30 09:34:41 -0700217 return {};
218}
219
220Result<void> check_setrlimit(const BuiltinArguments& args) {
221 ReturnIfAnyArgsEmpty();
222
223 auto rlimit = ParseRlimit(args.args);
Bernie Innocenticecebbb2020-02-06 03:49:33 +0900224 if (!rlimit.ok()) return rlimit.error();
Tom Cherry4772f1d2019-07-30 09:34:41 -0700225 return {};
226}
227
Alistair Delvade28a862020-06-08 11:04:53 -0700228Result<void> check_swapon_all(const BuiltinArguments& args) {
229 auto options = ParseSwaponAll(args.args);
230 if (!options.ok()) {
231 return options.error();
232 }
233 return {};
234}
235
Tom Cherry4772f1d2019-07-30 09:34:41 -0700236Result<void> check_sysclktz(const BuiltinArguments& args) {
237 ReturnIfAnyArgsEmpty();
238
239 struct timezone tz = {};
240 if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
241 return Error() << "Unable to parse mins_west_of_gmt";
242 }
243 return {};
244}
245
Alistair Delvaa2cc1eb2020-05-20 16:24:00 -0700246Result<void> check_umount_all(const BuiltinArguments& args) {
247 auto options = ParseUmountAll(args.args);
248 if (!options.ok()) {
249 return options.error();
250 }
251 return {};
252}
253
Tom Cherry4772f1d2019-07-30 09:34:41 -0700254Result<void> check_wait(const BuiltinArguments& args) {
255 if (args.size() == 3 && !args[2].empty()) {
Mark Salyzynffa52e92020-05-14 09:20:30 -0700256 double timeout_double;
257 if (!android::base::ParseDouble(args[2], &timeout_double, 0)) {
Tom Cherry4772f1d2019-07-30 09:34:41 -0700258 return Error() << "failed to parse timeout";
259 }
260 }
261 return {};
262}
263
264Result<void> check_wait_for_prop(const BuiltinArguments& args) {
265 return check_setprop(std::move(args));
266}
267
268} // namespace init
269} // namespace android