diff --git a/init/init_test.cpp b/init/init_test.cpp index caf3e0343..07b472455 100644 --- a/init/init_test.cpp +++ b/init/init_test.cpp @@ -239,6 +239,28 @@ TEST(init, EventTriggerOrderMultipleFiles) { EXPECT_EQ(6, num_executed); } +TEST(init, RejectsCriticalAndOneshotService) { + std::string init_script = + R"init( +service A something + class first + critical + oneshot +)init"; + + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd)); + + ServiceList service_list; + Parser parser; + parser.AddSectionParser("service", + std::make_unique(&service_list, nullptr, std::nullopt)); + + ASSERT_TRUE(parser.ParseConfig(tf.path)); + ASSERT_EQ(1u, parser.parse_error_count()); +} + } // namespace init } // namespace android diff --git a/init/service_parser.cpp b/init/service_parser.cpp index 560f693f9..c54ed71d4 100644 --- a/init/service_parser.cpp +++ b/init/service_parser.cpp @@ -598,6 +598,13 @@ Result ServiceParser::EndSection() { } } + if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) { + if ((service_->flags() & SVC_CRITICAL) != 0 && (service_->flags() & SVC_ONESHOT) != 0) { + return Error() << "service '" << service_->name() + << "' can't be both critical and oneshot"; + } + } + Service* old_service = service_list_->FindService(service_->name()); if (old_service) { if (!service_->is_override()) {