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