• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 <linux/input.h>
20 #include <stdlib.h>
21 #include <sys/socket.h>
22 
23 #include <algorithm>
24 #include <sstream>
25 
26 #include <android-base/logging.h>
27 #include <android-base/parseint.h>
28 #include <android-base/strings.h>
29 #include <hidl-util/FQName.h>
30 #include <processgroup/processgroup.h>
31 #include <system/thread_defs.h>
32 
33 #include "lmkd_service.h"
34 #include "rlimit_parser.h"
35 #include "service_utils.h"
36 #include "util.h"
37 
38 #ifdef INIT_FULL_SOURCES
39 #include <android/api-level.h>
40 #include <sys/system_properties.h>
41 
42 #include "selinux.h"
43 #else
44 #include "host_init_stubs.h"
45 #endif
46 
47 using android::base::ParseInt;
48 using android::base::Split;
49 using android::base::StartsWith;
50 
51 namespace android {
52 namespace init {
53 
ParseCapabilities(std::vector<std::string> && args)54 Result<void> ServiceParser::ParseCapabilities(std::vector<std::string>&& args) {
55     service_->capabilities_ = 0;
56 
57     if (!CapAmbientSupported()) {
58         return Error()
59                << "capabilities requested but the kernel does not support ambient capabilities";
60     }
61 
62     unsigned int last_valid_cap = GetLastValidCap();
63     if (last_valid_cap >= service_->capabilities_->size()) {
64         LOG(WARNING) << "last valid run-time capability is larger than CAP_LAST_CAP";
65     }
66 
67     for (size_t i = 1; i < args.size(); i++) {
68         const std::string& arg = args[i];
69         int res = LookupCap(arg);
70         if (res < 0) {
71             return Errorf("invalid capability '{}'", arg);
72         }
73         unsigned int cap = static_cast<unsigned int>(res);  // |res| is >= 0.
74         if (cap > last_valid_cap) {
75             return Errorf("capability '{}' not supported by the kernel", arg);
76         }
77         (*service_->capabilities_)[cap] = true;
78     }
79     return {};
80 }
81 
ParseClass(std::vector<std::string> && args)82 Result<void> ServiceParser::ParseClass(std::vector<std::string>&& args) {
83     service_->classnames_ = std::set<std::string>(args.begin() + 1, args.end());
84     return {};
85 }
86 
ParseConsole(std::vector<std::string> && args)87 Result<void> ServiceParser::ParseConsole(std::vector<std::string>&& args) {
88     if (service_->proc_attr_.stdio_to_kmsg) {
89         return Error() << "'console' and 'stdio_to_kmsg' are mutually exclusive";
90     }
91     service_->flags_ |= SVC_CONSOLE;
92     service_->proc_attr_.console = args.size() > 1 ? "/dev/" + args[1] : "";
93     return {};
94 }
95 
ParseCritical(std::vector<std::string> && args)96 Result<void> ServiceParser::ParseCritical(std::vector<std::string>&& args) {
97     std::optional<std::string> fatal_reboot_target;
98     std::optional<std::chrono::minutes> fatal_crash_window;
99 
100     for (auto it = args.begin() + 1; it != args.end(); ++it) {
101         auto arg = android::base::Split(*it, "=");
102         if (arg.size() != 2) {
103             return Error() << "critical: Argument '" << *it << "' is not supported";
104         } else if (arg[0] == "target") {
105             fatal_reboot_target = arg[1];
106         } else if (arg[0] == "window") {
107             int minutes;
108             auto window = ExpandProps(arg[1]);
109             if (!window.ok()) {
110                 return Error() << "critical: Could not expand argument ': " << arg[1];
111             }
112             if (*window == "off") {
113                 return {};
114             }
115             if (!ParseInt(*window, &minutes, 0)) {
116                 return Error() << "critical: 'fatal_crash_window' must be an integer > 0";
117             }
118             fatal_crash_window = std::chrono::minutes(minutes);
119         } else {
120             return Error() << "critical: Argument '" << *it << "' is not supported";
121         }
122     }
123 
124     if (fatal_reboot_target) {
125         service_->fatal_reboot_target_ = *fatal_reboot_target;
126     }
127     if (fatal_crash_window) {
128         service_->fatal_crash_window_ = *fatal_crash_window;
129     }
130     service_->flags_ |= SVC_CRITICAL;
131     return {};
132 }
133 
ParseDisabled(std::vector<std::string> && args)134 Result<void> ServiceParser::ParseDisabled(std::vector<std::string>&& args) {
135     service_->flags_ |= SVC_DISABLED;
136     service_->flags_ |= SVC_RC_DISABLED;
137     return {};
138 }
139 
ParseEnterNamespace(std::vector<std::string> && args)140 Result<void> ServiceParser::ParseEnterNamespace(std::vector<std::string>&& args) {
141     if (args[1] != "net") {
142         return Error() << "Init only supports entering network namespaces";
143     }
144     if (!service_->namespaces_.namespaces_to_enter.empty()) {
145         return Error() << "Only one network namespace may be entered";
146     }
147     // Network namespaces require that /sys is remounted, otherwise the old adapters will still be
148     // present. Therefore, they also require mount namespaces.
149     service_->namespaces_.flags |= CLONE_NEWNS;
150     service_->namespaces_.namespaces_to_enter.emplace_back(CLONE_NEWNET, std::move(args[2]));
151     return {};
152 }
153 
ParseGentleKill(std::vector<std::string> && args)154 Result<void> ServiceParser::ParseGentleKill(std::vector<std::string>&& args) {
155     service_->flags_ |= SVC_GENTLE_KILL;
156     return {};
157 }
158 
ParseGroup(std::vector<std::string> && args)159 Result<void> ServiceParser::ParseGroup(std::vector<std::string>&& args) {
160     auto gid = DecodeUid(args[1]);
161     if (!gid.ok()) {
162         return Error() << "Unable to decode GID for '" << args[1] << "': " << gid.error();
163     }
164     service_->proc_attr_.gid = *gid;
165 
166     for (std::size_t n = 2; n < args.size(); n++) {
167         gid = DecodeUid(args[n]);
168         if (!gid.ok()) {
169             return Error() << "Unable to decode GID for '" << args[n] << "': " << gid.error();
170         }
171         service_->proc_attr_.supp_gids.emplace_back(*gid);
172     }
173     return {};
174 }
175 
ParsePriority(std::vector<std::string> && args)176 Result<void> ServiceParser::ParsePriority(std::vector<std::string>&& args) {
177     service_->proc_attr_.priority = 0;
178     if (!ParseInt(args[1], &service_->proc_attr_.priority,
179                   static_cast<int>(ANDROID_PRIORITY_HIGHEST),  // highest is negative
180                   static_cast<int>(ANDROID_PRIORITY_LOWEST))) {
181         return Errorf("process priority value must be range {} - {}", ANDROID_PRIORITY_HIGHEST,
182                       ANDROID_PRIORITY_LOWEST);
183     }
184     return {};
185 }
186 
ParseInterface(std::vector<std::string> && args)187 Result<void> ServiceParser::ParseInterface(std::vector<std::string>&& args) {
188     const std::string& interface_name = args[1];
189     const std::string& instance_name = args[2];
190 
191     // AIDL services don't use fully qualified names and instead just use "interface aidl <name>"
192     if (interface_name != "aidl") {
193         FQName fq_name;
194         if (!FQName::parse(interface_name, &fq_name)) {
195             return Error() << "Invalid fully-qualified name for interface '" << interface_name
196                            << "'";
197         }
198 
199         if (!fq_name.isFullyQualified()) {
200             return Error() << "Interface name not fully-qualified '" << interface_name << "'";
201         }
202 
203         if (fq_name.isValidValueName()) {
204             return Error() << "Interface name must not be a value name '" << interface_name << "'";
205         }
206     }
207 
208     const std::string fullname = interface_name + "/" + instance_name;
209 
210     for (const auto& svc : *service_list_) {
211         if (svc->interfaces().count(fullname) > 0 && !service_->is_override()) {
212             return Error() << "Interface '" << fullname << "' redefined in " << service_->name()
213                            << " but is already defined by " << svc->name();
214         }
215     }
216 
217     service_->interfaces_.insert(fullname);
218 
219     return {};
220 }
221 
ParseIoprio(std::vector<std::string> && args)222 Result<void> ServiceParser::ParseIoprio(std::vector<std::string>&& args) {
223     if (!ParseInt(args[2], &service_->proc_attr_.ioprio_pri, 0, 7)) {
224         return Error() << "priority value must be range 0 - 7";
225     }
226 
227     if (args[1] == "rt") {
228         service_->proc_attr_.ioprio_class = IoSchedClass_RT;
229     } else if (args[1] == "be") {
230         service_->proc_attr_.ioprio_class = IoSchedClass_BE;
231     } else if (args[1] == "idle") {
232         service_->proc_attr_.ioprio_class = IoSchedClass_IDLE;
233     } else {
234         return Error() << "ioprio option usage: ioprio <rt|be|idle> <0-7>";
235     }
236 
237     return {};
238 }
239 
ParseKeycodes(std::vector<std::string> && args)240 Result<void> ServiceParser::ParseKeycodes(std::vector<std::string>&& args) {
241     auto it = args.begin() + 1;
242     if (args.size() == 2 && StartsWith(args[1], "$")) {
243         auto expanded = ExpandProps(args[1]);
244         if (!expanded.ok()) {
245             return expanded.error();
246         }
247 
248         // If the property is not set, it defaults to none, in which case there are no keycodes
249         // for this service.
250         if (*expanded == "none") {
251             return {};
252         }
253 
254         args = Split(*expanded, ",");
255         it = args.begin();
256     }
257 
258     for (; it != args.end(); ++it) {
259         int code;
260         if (ParseInt(*it, &code, 0, KEY_MAX)) {
261             for (auto& key : service_->keycodes_) {
262                 if (key == code) return Error() << "duplicate keycode: " << *it;
263             }
264             service_->keycodes_.insert(
265                     std::upper_bound(service_->keycodes_.begin(), service_->keycodes_.end(), code),
266                     code);
267         } else {
268             return Error() << "invalid keycode: " << *it;
269         }
270     }
271     return {};
272 }
273 
ParseOneshot(std::vector<std::string> && args)274 Result<void> ServiceParser::ParseOneshot(std::vector<std::string>&& args) {
275     service_->flags_ |= SVC_ONESHOT;
276     return {};
277 }
278 
ParseOnrestart(std::vector<std::string> && args)279 Result<void> ServiceParser::ParseOnrestart(std::vector<std::string>&& args) {
280     args.erase(args.begin());
281     int line = service_->onrestart_.NumCommands() + 1;
282     if (auto result = service_->onrestart_.AddCommand(std::move(args), line); !result.ok()) {
283         return Error() << "cannot add Onrestart command: " << result.error();
284     }
285     return {};
286 }
287 
ParseNamespace(std::vector<std::string> && args)288 Result<void> ServiceParser::ParseNamespace(std::vector<std::string>&& args) {
289     for (size_t i = 1; i < args.size(); i++) {
290         if (args[i] == "pid") {
291             service_->namespaces_.flags |= CLONE_NEWPID;
292             // PID namespaces require mount namespaces.
293             service_->namespaces_.flags |= CLONE_NEWNS;
294         } else if (args[i] == "mnt") {
295             service_->namespaces_.flags |= CLONE_NEWNS;
296         } else {
297             return Error() << "namespace must be 'pid' or 'mnt'";
298         }
299     }
300     return {};
301 }
302 
ParseOomScoreAdjust(std::vector<std::string> && args)303 Result<void> ServiceParser::ParseOomScoreAdjust(std::vector<std::string>&& args) {
304     if (!ParseInt(args[1], &service_->oom_score_adjust_, MIN_OOM_SCORE_ADJUST,
305                   MAX_OOM_SCORE_ADJUST)) {
306         return Error() << "oom_score_adjust value must be in range " << MIN_OOM_SCORE_ADJUST
307                        << " - +" << MAX_OOM_SCORE_ADJUST;
308     }
309     return {};
310 }
311 
ParseOverride(std::vector<std::string> && args)312 Result<void> ServiceParser::ParseOverride(std::vector<std::string>&& args) {
313     service_->override_ = true;
314     return {};
315 }
316 
ParseMemcgSwappiness(std::vector<std::string> && args)317 Result<void> ServiceParser::ParseMemcgSwappiness(std::vector<std::string>&& args) {
318     if (!ParseInt(args[1], &service_->swappiness_, 0)) {
319         return Error() << "swappiness value must be equal or greater than 0";
320     }
321     return {};
322 }
323 
ParseMemcgLimitInBytes(std::vector<std::string> && args)324 Result<void> ServiceParser::ParseMemcgLimitInBytes(std::vector<std::string>&& args) {
325     if (!ParseInt(args[1], &service_->limit_in_bytes_, 0)) {
326         return Error() << "limit_in_bytes value must be equal or greater than 0";
327     }
328     return {};
329 }
330 
ParseMemcgLimitPercent(std::vector<std::string> && args)331 Result<void> ServiceParser::ParseMemcgLimitPercent(std::vector<std::string>&& args) {
332     if (!ParseInt(args[1], &service_->limit_percent_, 0)) {
333         return Error() << "limit_percent value must be equal or greater than 0";
334     }
335     return {};
336 }
337 
ParseMemcgLimitProperty(std::vector<std::string> && args)338 Result<void> ServiceParser::ParseMemcgLimitProperty(std::vector<std::string>&& args) {
339     service_->limit_property_ = std::move(args[1]);
340     return {};
341 }
342 
ParseMemcgSoftLimitInBytes(std::vector<std::string> && args)343 Result<void> ServiceParser::ParseMemcgSoftLimitInBytes(std::vector<std::string>&& args) {
344     if (!ParseInt(args[1], &service_->soft_limit_in_bytes_, 0)) {
345         return Error() << "soft_limit_in_bytes value must be equal or greater than 0";
346     }
347     return {};
348 }
349 
ParseProcessRlimit(std::vector<std::string> && args)350 Result<void> ServiceParser::ParseProcessRlimit(std::vector<std::string>&& args) {
351     auto rlimit = ParseRlimit(args);
352     if (!rlimit.ok()) return rlimit.error();
353 
354     service_->proc_attr_.rlimits.emplace_back(*rlimit);
355     return {};
356 }
357 
ParseRebootOnFailure(std::vector<std::string> && args)358 Result<void> ServiceParser::ParseRebootOnFailure(std::vector<std::string>&& args) {
359     if (service_->on_failure_reboot_target_) {
360         return Error() << "Only one reboot_on_failure command may be specified";
361     }
362     if (!StartsWith(args[1], "shutdown") && !StartsWith(args[1], "reboot")) {
363         return Error()
364                << "reboot_on_failure commands must begin with either 'shutdown' or 'reboot'";
365     }
366     service_->on_failure_reboot_target_ = std::move(args[1]);
367     return {};
368 }
369 
ParseRestartPeriod(std::vector<std::string> && args)370 Result<void> ServiceParser::ParseRestartPeriod(std::vector<std::string>&& args) {
371     int period;
372     if (!ParseInt(args[1], &period, 5)) {
373         return Error() << "restart_period value must be an integer >= 5";
374     }
375     service_->restart_period_ = std::chrono::seconds(period);
376     return {};
377 }
378 
ParseSeclabel(std::vector<std::string> && args)379 Result<void> ServiceParser::ParseSeclabel(std::vector<std::string>&& args) {
380     service_->seclabel_ = std::move(args[1]);
381     return {};
382 }
383 
ParseSigstop(std::vector<std::string> && args)384 Result<void> ServiceParser::ParseSigstop(std::vector<std::string>&& args) {
385     service_->sigstop_ = true;
386     return {};
387 }
388 
ParseSetenv(std::vector<std::string> && args)389 Result<void> ServiceParser::ParseSetenv(std::vector<std::string>&& args) {
390     service_->environment_vars_.emplace_back(std::move(args[1]), std::move(args[2]));
391     return {};
392 }
393 
ParseShutdown(std::vector<std::string> && args)394 Result<void> ServiceParser::ParseShutdown(std::vector<std::string>&& args) {
395     if (args[1] == "critical") {
396         service_->flags_ |= SVC_SHUTDOWN_CRITICAL;
397         return {};
398     }
399     return Error() << "Invalid shutdown option";
400 }
401 
ParseTaskProfiles(std::vector<std::string> && args)402 Result<void> ServiceParser::ParseTaskProfiles(std::vector<std::string>&& args) {
403     args.erase(args.begin());
404     if (service_->task_profiles_.empty()) {
405         service_->task_profiles_ = std::move(args);
406     } else {
407         // Some task profiles might have been added during writepid conversions
408         service_->task_profiles_.insert(service_->task_profiles_.end(),
409                                         std::make_move_iterator(args.begin()),
410                                         std::make_move_iterator(args.end()));
411         args.clear();
412     }
413     return {};
414 }
415 
ParseTimeoutPeriod(std::vector<std::string> && args)416 Result<void> ServiceParser::ParseTimeoutPeriod(std::vector<std::string>&& args) {
417     int period;
418     if (!ParseInt(args[1], &period, 1)) {
419         return Error() << "timeout_period value must be an integer >= 1";
420     }
421     service_->timeout_period_ = std::chrono::seconds(period);
422     return {};
423 }
424 
425 // name type perm [ uid gid context ]
ParseSocket(std::vector<std::string> && args)426 Result<void> ServiceParser::ParseSocket(std::vector<std::string>&& args) {
427     SocketDescriptor socket;
428     socket.name = std::move(args[1]);
429 
430     auto types = Split(args[2], "+");
431     if (types[0] == "stream") {
432         socket.type = SOCK_STREAM;
433     } else if (types[0] == "dgram") {
434         socket.type = SOCK_DGRAM;
435     } else if (types[0] == "seqpacket") {
436         socket.type = SOCK_SEQPACKET;
437     } else {
438         return Error() << "socket type must be 'dgram', 'stream' or 'seqpacket', got '" << types[0]
439                        << "' instead.";
440     }
441 
442     for (size_t i = 1; i < types.size(); i++) {
443         if (types[i] == "passcred") {
444             socket.passcred = true;
445         } else if (types[i] == "listen") {
446             socket.listen = true;
447         } else {
448             return Error() << "Unknown socket type decoration '" << types[i]
449                            << "'. Known values are ['passcred', 'listen']";
450         }
451     }
452 
453     errno = 0;
454     char* end = nullptr;
455     socket.perm = strtol(args[3].c_str(), &end, 8);
456     if (errno != 0) {
457         return ErrnoError() << "Unable to parse permissions '" << args[3] << "'";
458     }
459     if (end == args[3].c_str() || *end != '\0') {
460         errno = EINVAL;
461         return ErrnoError() << "Unable to parse permissions '" << args[3] << "'";
462     }
463 
464     if (args.size() > 4) {
465         auto uid = DecodeUid(args[4]);
466         if (!uid.ok()) {
467             return Error() << "Unable to find UID for '" << args[4] << "': " << uid.error();
468         }
469         socket.uid = *uid;
470     }
471 
472     if (args.size() > 5) {
473         auto gid = DecodeUid(args[5]);
474         if (!gid.ok()) {
475             return Error() << "Unable to find GID for '" << args[5] << "': " << gid.error();
476         }
477         socket.gid = *gid;
478     }
479 
480     socket.context = args.size() > 6 ? args[6] : "";
481 
482     auto old = std::find_if(service_->sockets_.begin(), service_->sockets_.end(),
483                             [&socket](const auto& other) { return socket.name == other.name; });
484 
485     if (old != service_->sockets_.end()) {
486         return Error() << "duplicate socket descriptor '" << socket.name << "'";
487     }
488 
489     service_->sockets_.emplace_back(std::move(socket));
490 
491     return {};
492 }
493 
ParseStdioToKmsg(std::vector<std::string> && args)494 Result<void> ServiceParser::ParseStdioToKmsg(std::vector<std::string>&& args) {
495     if (service_->flags_ & SVC_CONSOLE) {
496         return Error() << "'stdio_to_kmsg' and 'console' are mutually exclusive";
497     }
498     service_->proc_attr_.stdio_to_kmsg = true;
499     return {};
500 }
501 
502 // name type
ParseFile(std::vector<std::string> && args)503 Result<void> ServiceParser::ParseFile(std::vector<std::string>&& args) {
504     if (args[2] != "r" && args[2] != "w" && args[2] != "rw") {
505         return Error() << "file type must be 'r', 'w' or 'rw'";
506     }
507 
508     FileDescriptor file;
509     file.type = args[2];
510 
511     auto file_name = ExpandProps(args[1]);
512     if (!file_name.ok()) {
513         return Error() << "Could not expand file path ': " << file_name.error();
514     }
515     file.name = *file_name;
516     if (file.name[0] != '/' || file.name.find("../") != std::string::npos) {
517         return Error() << "file name must not be relative";
518     }
519 
520     auto old = std::find_if(service_->files_.begin(), service_->files_.end(),
521                             [&file](const auto& other) { return other.name == file.name; });
522 
523     if (old != service_->files_.end()) {
524         return Error() << "duplicate file descriptor '" << file.name << "'";
525     }
526 
527     service_->files_.emplace_back(std::move(file));
528 
529     return {};
530 }
531 
ParseUser(std::vector<std::string> && args)532 Result<void> ServiceParser::ParseUser(std::vector<std::string>&& args) {
533     auto uid = DecodeUid(args[1]);
534     if (!uid.ok()) {
535         return Error() << "Unable to find UID for '" << args[1] << "': " << uid.error();
536     }
537     service_->proc_attr_.uid = *uid;
538     return {};
539 }
540 
541 // Convert legacy paths used to migrate processes between cgroups using writepid command.
542 // We can't get these paths from TaskProfiles because profile definitions are changing
543 // when we migrate to cgroups v2 while these hardcoded paths stay the same.
ConvertTaskFileToProfile(const std::string & file)544 static std::optional<const std::string> ConvertTaskFileToProfile(const std::string& file) {
545     static const std::map<const std::string, const std::string> map = {
546             {"/dev/stune/top-app/tasks", "MaxPerformance"},
547             {"/dev/stune/foreground/tasks", "HighPerformance"},
548             {"/dev/cpuset/camera-daemon/tasks", "CameraServiceCapacity"},
549             {"/dev/cpuset/foreground/tasks", "ProcessCapacityHigh"},
550             {"/dev/cpuset/system-background/tasks", "ServiceCapacityLow"},
551             {"/dev/stune/nnapi-hal/tasks", "NNApiHALPerformance"},
552             {"/dev/blkio/background/tasks", "LowIoPriority"},
553     };
554     auto iter = map.find(file);
555     return iter == map.end() ? std::nullopt : std::make_optional<const std::string>(iter->second);
556 }
557 
ParseWritepid(std::vector<std::string> && args)558 Result<void> ServiceParser::ParseWritepid(std::vector<std::string>&& args) {
559     args.erase(args.begin());
560     // Convert any cgroup writes into appropriate task_profiles
561     for (auto iter = args.begin(); iter != args.end();) {
562         auto task_profile = ConvertTaskFileToProfile(*iter);
563         if (task_profile) {
564             LOG(WARNING) << "'writepid " << *iter << "' is converted into 'task_profiles "
565                          << task_profile.value() << "' for service " << service_->name();
566             service_->task_profiles_.push_back(task_profile.value());
567             iter = args.erase(iter);
568         } else {
569             ++iter;
570         }
571     }
572     service_->writepid_files_ = std::move(args);
573     return {};
574 }
575 
ParseUpdatable(std::vector<std::string> && args)576 Result<void> ServiceParser::ParseUpdatable(std::vector<std::string>&& args) {
577     service_->updatable_ = true;
578     return {};
579 }
580 
GetParserMap() const581 const KeywordMap<ServiceParser::OptionParser>& ServiceParser::GetParserMap() const {
582     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
583     // clang-format off
584     static const KeywordMap<ServiceParser::OptionParser> parser_map = {
585         {"capabilities",            {0,     kMax, &ServiceParser::ParseCapabilities}},
586         {"class",                   {1,     kMax, &ServiceParser::ParseClass}},
587         {"console",                 {0,     1,    &ServiceParser::ParseConsole}},
588         {"critical",                {0,     2,    &ServiceParser::ParseCritical}},
589         {"disabled",                {0,     0,    &ServiceParser::ParseDisabled}},
590         {"enter_namespace",         {2,     2,    &ServiceParser::ParseEnterNamespace}},
591         {"file",                    {2,     2,    &ServiceParser::ParseFile}},
592         {"gentle_kill",             {0,     0,    &ServiceParser::ParseGentleKill}},
593         {"group",                   {1,     NR_SVC_SUPP_GIDS + 1, &ServiceParser::ParseGroup}},
594         {"interface",               {2,     2,    &ServiceParser::ParseInterface}},
595         {"ioprio",                  {2,     2,    &ServiceParser::ParseIoprio}},
596         {"keycodes",                {1,     kMax, &ServiceParser::ParseKeycodes}},
597         {"memcg.limit_in_bytes",    {1,     1,    &ServiceParser::ParseMemcgLimitInBytes}},
598         {"memcg.limit_percent",     {1,     1,    &ServiceParser::ParseMemcgLimitPercent}},
599         {"memcg.limit_property",    {1,     1,    &ServiceParser::ParseMemcgLimitProperty}},
600         {"memcg.soft_limit_in_bytes",
601                                     {1,     1,    &ServiceParser::ParseMemcgSoftLimitInBytes}},
602         {"memcg.swappiness",        {1,     1,    &ServiceParser::ParseMemcgSwappiness}},
603         {"namespace",               {1,     2,    &ServiceParser::ParseNamespace}},
604         {"oneshot",                 {0,     0,    &ServiceParser::ParseOneshot}},
605         {"onrestart",               {1,     kMax, &ServiceParser::ParseOnrestart}},
606         {"oom_score_adjust",        {1,     1,    &ServiceParser::ParseOomScoreAdjust}},
607         {"override",                {0,     0,    &ServiceParser::ParseOverride}},
608         {"priority",                {1,     1,    &ServiceParser::ParsePriority}},
609         {"reboot_on_failure",       {1,     1,    &ServiceParser::ParseRebootOnFailure}},
610         {"restart_period",          {1,     1,    &ServiceParser::ParseRestartPeriod}},
611         {"rlimit",                  {3,     3,    &ServiceParser::ParseProcessRlimit}},
612         {"seclabel",                {1,     1,    &ServiceParser::ParseSeclabel}},
613         {"setenv",                  {2,     2,    &ServiceParser::ParseSetenv}},
614         {"shutdown",                {1,     1,    &ServiceParser::ParseShutdown}},
615         {"sigstop",                 {0,     0,    &ServiceParser::ParseSigstop}},
616         {"socket",                  {3,     6,    &ServiceParser::ParseSocket}},
617         {"stdio_to_kmsg",           {0,     0,    &ServiceParser::ParseStdioToKmsg}},
618         {"task_profiles",           {1,     kMax, &ServiceParser::ParseTaskProfiles}},
619         {"timeout_period",          {1,     1,    &ServiceParser::ParseTimeoutPeriod}},
620         {"updatable",               {0,     0,    &ServiceParser::ParseUpdatable}},
621         {"user",                    {1,     1,    &ServiceParser::ParseUser}},
622         {"writepid",                {1,     kMax, &ServiceParser::ParseWritepid}},
623     };
624     // clang-format on
625     return parser_map;
626 }
627 
ParseSection(std::vector<std::string> && args,const std::string & filename,int line)628 Result<void> ServiceParser::ParseSection(std::vector<std::string>&& args,
629                                          const std::string& filename, int line) {
630     if (args.size() < 3) {
631         return Error() << "services must have a name and a program";
632     }
633 
634     const std::string& name = args[1];
635     if (!IsValidName(name)) {
636         return Error() << "invalid service name '" << name << "'";
637     }
638 
639     filename_ = filename;
640 
641     Subcontext* restart_action_subcontext = nullptr;
642     if (subcontext_ && subcontext_->PathMatchesSubcontext(filename)) {
643         restart_action_subcontext = subcontext_;
644     }
645 
646     std::vector<std::string> str_args(args.begin() + 2, args.end());
647 
648     if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_P__) {
649         if (str_args[0] == "/sbin/watchdogd") {
650             str_args[0] = "/system/bin/watchdogd";
651         }
652     }
653     if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
654         if (str_args[0] == "/charger") {
655             str_args[0] = "/system/bin/charger";
656         }
657     }
658 
659     service_ = std::make_unique<Service>(name, restart_action_subcontext, filename, str_args);
660     return {};
661 }
662 
ParseLineSection(std::vector<std::string> && args,int line)663 Result<void> ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line) {
664     if (!service_) {
665         return {};
666     }
667 
668     auto parser = GetParserMap().Find(args);
669 
670     if (!parser.ok()) return parser.error();
671 
672     return std::invoke(*parser, this, std::move(args));
673 }
674 
EndSection()675 Result<void> ServiceParser::EndSection() {
676     if (!service_) {
677         return {};
678     }
679 
680     if (interface_inheritance_hierarchy_) {
681         if (const auto& check_hierarchy_result = CheckInterfaceInheritanceHierarchy(
682                     service_->interfaces(), *interface_inheritance_hierarchy_);
683             !check_hierarchy_result.ok()) {
684             return Error() << check_hierarchy_result.error();
685         }
686     }
687 
688     if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
689         if ((service_->flags() & SVC_CRITICAL) != 0 && (service_->flags() & SVC_ONESHOT) != 0) {
690             return Error() << "service '" << service_->name()
691                            << "' can't be both critical and oneshot";
692         }
693     }
694 
695     Service* old_service = service_list_->FindService(service_->name());
696     if (old_service) {
697         if (!service_->is_override()) {
698             return Error() << "ignored duplicate definition of service '" << service_->name()
699                            << "'";
700         }
701 
702         if (StartsWith(filename_, "/apex/") && !old_service->is_updatable()) {
703             return Error() << "cannot update a non-updatable service '" << service_->name()
704                            << "' with a config in APEX";
705         }
706 
707         std::string context = service_->subcontext() ? service_->subcontext()->context() : "";
708         std::string old_context =
709                 old_service->subcontext() ? old_service->subcontext()->context() : "";
710         if (context != old_context) {
711             return Error() << "service '" << service_->name() << "' overrides another service "
712                            << "across the treble boundary.";
713         }
714 
715         service_list_->RemoveService(*old_service);
716         old_service = nullptr;
717     }
718 
719     service_list_->AddService(std::move(service_));
720 
721     return {};
722 }
723 
IsValidName(const std::string & name) const724 bool ServiceParser::IsValidName(const std::string& name) const {
725     // Property names can be any length, but may only contain certain characters.
726     // Property values can contain any characters, but may only be a certain length.
727     // (The latter restriction is needed because `start` and `stop` work by writing
728     // the service name to the "ctl.start" and "ctl.stop" properties.)
729     return IsLegalPropertyName("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
730 }
731 
732 }  // namespace init
733 }  // namespace android
734