blob: 771f1d773310e18ee1992aa2586d974933a06043 [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
Daniel Normand2533c32019-08-02 15:13:50 -070084Result<void> check_interface_restart(const BuiltinArguments& args) {
85 if (auto result = IsKnownInterface(args[1]); !result) {
86 return result.error();
87 }
88 return {};
89}
90
91Result<void> check_interface_start(const BuiltinArguments& args) {
92 return check_interface_restart(std::move(args));
93}
94
95Result<void> check_interface_stop(const BuiltinArguments& args) {
96 return check_interface_restart(std::move(args));
97}
98
Tom Cherry4772f1d2019-07-30 09:34:41 -070099Result<void> check_load_system_props(const BuiltinArguments& args) {
100 return Error() << "'load_system_props' is deprecated";
101}
102
103Result<void> check_loglevel(const BuiltinArguments& args) {
104 ReturnIfAnyArgsEmpty();
105
106 int log_level = -1;
107 ParseInt(args[1], &log_level);
108 if (log_level < 0 || log_level > 7) {
109 return Error() << "loglevel must be in the range of 0-7";
110 }
111 return {};
112}
113
114Result<void> check_mkdir(const BuiltinArguments& args) {
115 if (args.size() >= 4) {
116 if (!args[3].empty()) {
117 auto uid = DecodeUid(args[3]);
118 if (!uid) {
119 return Error() << "Unable to decode UID for '" << args[3] << "': " << uid.error();
120 }
121 }
122
123 if (args.size() == 5 && !args[4].empty()) {
124 auto gid = DecodeUid(args[4]);
125 if (!gid) {
126 return Error() << "Unable to decode GID for '" << args[4] << "': " << gid.error();
127 }
128 }
129 }
130
131 return {};
132}
133
134Result<void> check_restorecon(const BuiltinArguments& args) {
135 ReturnIfAnyArgsEmpty();
136
137 auto restorecon_info = ParseRestorecon(args.args);
138 if (!restorecon_info) {
139 return restorecon_info.error();
140 }
141
142 return {};
143}
144
145Result<void> check_restorecon_recursive(const BuiltinArguments& args) {
146 return check_restorecon(std::move(args));
147}
148
149Result<void> check_setprop(const BuiltinArguments& args) {
150 const std::string& name = args[1];
151 if (name.empty()) {
152 return {};
153 }
154 const std::string& value = args[2];
155
156 if (!IsLegalPropertyName(name)) {
157 return Error() << "'" << name << "' is not a legal property name";
158 }
159
160 if (!value.empty()) {
161 if (auto result = IsLegalPropertyValue(name, value); !result) {
162 return result.error();
163 }
164 }
165
166 if (StartsWith(name, "ctl.")) {
167 return Error()
168 << "Do not set ctl. properties from init; call the Service functions directly";
169 }
170
171 static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive";
172 if (name == kRestoreconProperty) {
173 return Error() << "Do not set '" << kRestoreconProperty
174 << "' from init; use the restorecon builtin directly";
175 }
176
177 return {};
178}
179
180Result<void> check_setrlimit(const BuiltinArguments& args) {
181 ReturnIfAnyArgsEmpty();
182
183 auto rlimit = ParseRlimit(args.args);
184 if (!rlimit) return rlimit.error();
185 return {};
186}
187
188Result<void> check_sysclktz(const BuiltinArguments& args) {
189 ReturnIfAnyArgsEmpty();
190
191 struct timezone tz = {};
192 if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
193 return Error() << "Unable to parse mins_west_of_gmt";
194 }
195 return {};
196}
197
198Result<void> check_wait(const BuiltinArguments& args) {
199 if (args.size() == 3 && !args[2].empty()) {
200 int timeout_int;
201 if (!android::base::ParseInt(args[2], &timeout_int)) {
202 return Error() << "failed to parse timeout";
203 }
204 }
205 return {};
206}
207
208Result<void> check_wait_for_prop(const BuiltinArguments& args) {
209 return check_setprop(std::move(args));
210}
211
212} // namespace init
213} // namespace android