blob: 9d23921a174d5d027f75aa71fc95d3f623903fa8 [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>
28#include <android-base/parseint.h>
29#include <android-base/strings.h>
30
31#include "builtin_arguments.h"
Daniel Normand2533c32019-08-02 15:13:50 -070032#include "interface_utils.h"
Tom Cherry4772f1d2019-07-30 09:34:41 -070033#include "rlimit_parser.h"
34#include "service.h"
35#include "util.h"
36
37using android::base::ParseInt;
38using android::base::StartsWith;
39
40#define ReturnIfAnyArgsEmpty() \
41 for (const auto& arg : args) { \
42 if (arg.empty()) { \
43 return {}; \
44 } \
45 }
46
47namespace android {
48namespace init {
49
50Result<void> check_chown(const BuiltinArguments& args) {
51 if (!args[1].empty()) {
52 auto uid = DecodeUid(args[1]);
53 if (!uid) {
54 return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
55 }
56 }
57
58 // GID is optional and pushes the index of path out by one if specified.
59 if (args.size() == 4 && !args[2].empty()) {
60 auto gid = DecodeUid(args[2]);
61 if (!gid) {
62 return Error() << "Unable to decode GID for '" << args[2] << "': " << gid.error();
63 }
64 }
65
66 return {};
67}
68
69Result<void> check_exec(const BuiltinArguments& args) {
70 ReturnIfAnyArgsEmpty();
71
72 auto result = Service::MakeTemporaryOneshotService(args.args);
73 if (!result) {
74 return result.error();
75 }
76
77 return {};
78}
79
80Result<void> check_exec_background(const BuiltinArguments& args) {
81 return check_exec(std::move(args));
82}
83
Tom Cherry7896e7a2019-09-04 15:26:52 -070084Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args) {
85 BuiltinArguments remaining_args(args.context);
86
87 remaining_args.args = std::vector<std::string>(args.begin() + 1, args.end());
88 remaining_args.args[0] = args[0];
89
90 return check_exec(remaining_args);
91}
92
Daniel Normand2533c32019-08-02 15:13:50 -070093Result<void> check_interface_restart(const BuiltinArguments& args) {
94 if (auto result = IsKnownInterface(args[1]); !result) {
95 return result.error();
96 }
97 return {};
98}
99
100Result<void> check_interface_start(const BuiltinArguments& args) {
101 return check_interface_restart(std::move(args));
102}
103
104Result<void> check_interface_stop(const BuiltinArguments& args) {
105 return check_interface_restart(std::move(args));
106}
107
Tom Cherry4772f1d2019-07-30 09:34:41 -0700108Result<void> check_load_system_props(const BuiltinArguments& args) {
109 return Error() << "'load_system_props' is deprecated";
110}
111
112Result<void> check_loglevel(const BuiltinArguments& args) {
113 ReturnIfAnyArgsEmpty();
114
115 int log_level = -1;
116 ParseInt(args[1], &log_level);
117 if (log_level < 0 || log_level > 7) {
118 return Error() << "loglevel must be in the range of 0-7";
119 }
120 return {};
121}
122
123Result<void> check_mkdir(const BuiltinArguments& args) {
Paul Crowley68258e82019-10-28 07:55:03 -0700124 auto options = ParseMkdir(args.args);
125 if (!options) {
126 return options.error();
Tom Cherry4772f1d2019-07-30 09:34:41 -0700127 }
Tom Cherry4772f1d2019-07-30 09:34:41 -0700128 return {};
129}
130
131Result<void> check_restorecon(const BuiltinArguments& args) {
132 ReturnIfAnyArgsEmpty();
133
134 auto restorecon_info = ParseRestorecon(args.args);
135 if (!restorecon_info) {
136 return restorecon_info.error();
137 }
138
139 return {};
140}
141
142Result<void> check_restorecon_recursive(const BuiltinArguments& args) {
143 return check_restorecon(std::move(args));
144}
145
146Result<void> check_setprop(const BuiltinArguments& args) {
147 const std::string& name = args[1];
148 if (name.empty()) {
149 return {};
150 }
151 const std::string& value = args[2];
152
153 if (!IsLegalPropertyName(name)) {
154 return Error() << "'" << name << "' is not a legal property name";
155 }
156
157 if (!value.empty()) {
158 if (auto result = IsLegalPropertyValue(name, value); !result) {
159 return result.error();
160 }
161 }
162
163 if (StartsWith(name, "ctl.")) {
164 return Error()
165 << "Do not set ctl. properties from init; call the Service functions directly";
166 }
167
168 static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive";
169 if (name == kRestoreconProperty) {
170 return Error() << "Do not set '" << kRestoreconProperty
171 << "' from init; use the restorecon builtin directly";
172 }
173
174 return {};
175}
176
177Result<void> check_setrlimit(const BuiltinArguments& args) {
178 ReturnIfAnyArgsEmpty();
179
180 auto rlimit = ParseRlimit(args.args);
181 if (!rlimit) return rlimit.error();
182 return {};
183}
184
185Result<void> check_sysclktz(const BuiltinArguments& args) {
186 ReturnIfAnyArgsEmpty();
187
188 struct timezone tz = {};
189 if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
190 return Error() << "Unable to parse mins_west_of_gmt";
191 }
192 return {};
193}
194
195Result<void> check_wait(const BuiltinArguments& args) {
196 if (args.size() == 3 && !args[2].empty()) {
197 int timeout_int;
198 if (!android::base::ParseInt(args[2], &timeout_int)) {
199 return Error() << "failed to parse timeout";
200 }
201 }
202 return {};
203}
204
205Result<void> check_wait_for_prop(const BuiltinArguments& args) {
206 return check_setprop(std::move(args));
207}
208
209} // namespace init
210} // namespace android