init: allow services to have no capabilities set

In particular, this allows services running as the root user to have
capabilities removed instead of always having full capabilities.

Test: boot device with a root service with an empty capabilities
      option in init showing no capabilities in /proc/<pid>/status
Change-Id: I569a5573ed4bc5fab0eb37ce9224ab708e980451
diff --git a/init/README.md b/init/README.md
index 3a7c71c..f0e5d55 100644
--- a/init/README.md
+++ b/init/README.md
@@ -161,11 +161,13 @@
 Options are modifiers to services.  They affect how and when init
 runs the service.
 
-`capabilities <capability> [ <capability>\* ]`
+`capabilities [ <capability>\* ]`
 > Set capabilities when exec'ing this service. 'capability' should be a Linux
   capability without the "CAP\_" prefix, like "NET\_ADMIN" or "SETPCAP". See
   http://man7.org/linux/man-pages/man7/capabilities.7.html for a list of Linux
   capabilities.
+  If no capabilities are provided, then all capabilities are removed from this service, even if it
+  runs as root.
 
 `class <name> [ <name>\* ]`
 > Specify class names for the service.  All services in a
diff --git a/init/service.cpp b/init/service.cpp
index d64f2f3..2186a85 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -218,12 +218,12 @@
 
 Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
                  const std::vector<std::string>& args)
-    : Service(name, 0, 0, 0, {}, 0, 0, "", subcontext_for_restart_commands, args) {}
+    : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args) {}
 
 Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-                 const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
-                 unsigned namespace_flags, const std::string& seclabel,
-                 Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args)
+                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+                 const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+                 const std::vector<std::string>& args)
     : name_(name),
       classnames_({"default"}),
       flags_(flags),
@@ -232,7 +232,6 @@
       uid_(uid),
       gid_(gid),
       supp_gids_(supp_gids),
-      capabilities_(capabilities),
       namespace_flags_(namespace_flags),
       seclabel_(seclabel),
       onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
@@ -289,7 +288,7 @@
         }
     }
     // Keep capabilites on uid change.
-    if (capabilities_.any() && uid_) {
+    if (capabilities_ && uid_) {
         // If Android is running in a container, some securebits might already
         // be locked, so don't change those.
         unsigned long securebits = prctl(PR_GET_SECUREBITS);
@@ -328,8 +327,8 @@
             PLOG(FATAL) << "setpriority failed for " << name_;
         }
     }
-    if (capabilities_.any()) {
-        if (!SetCapsForExec(capabilities_)) {
+    if (capabilities_) {
+        if (!SetCapsForExec(*capabilities_)) {
             LOG(FATAL) << "cannot set capabilities for " << name_;
         }
     } else if (uid_) {
@@ -420,7 +419,7 @@
     }
 
     unsigned int last_valid_cap = GetLastValidCap();
-    if (last_valid_cap >= capabilities_.size()) {
+    if (last_valid_cap >= capabilities_->size()) {
         LOG(WARNING) << "last valid run-time capability is larger than CAP_LAST_CAP";
     }
 
@@ -435,7 +434,7 @@
             return Error() << StringPrintf("capability '%s' not supported by the kernel",
                                            arg.c_str());
         }
-        capabilities_[cap] = true;
+        (*capabilities_)[cap] = true;
     }
     return Success();
 }
@@ -796,7 +795,7 @@
     // clang-format off
     static const Map option_parsers = {
         {"capabilities",
-                        {1,     kMax, &Service::ParseCapabilities}},
+                        {0,     kMax, &Service::ParseCapabilities}},
         {"class",       {1,     kMax, &Service::ParseClass}},
         {"console",     {0,     1,    &Service::ParseConsole}},
         {"critical",    {0,     0,    &Service::ParseCritical}},
@@ -1268,7 +1267,6 @@
     std::string name = "exec " + std::to_string(exec_count) + " (" + Join(str_args, " ") + ")";
 
     unsigned flags = SVC_ONESHOT | SVC_TEMPORARY;
-    CapSet no_capabilities;
     unsigned namespace_flags = 0;
 
     std::string seclabel = "";
@@ -1303,8 +1301,8 @@
         }
     }
 
-    return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, no_capabilities,
-                                     namespace_flags, seclabel, nullptr, str_args);
+    return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, namespace_flags, seclabel,
+                                     nullptr, str_args);
 }
 
 // Shutdown services in the opposite order that they were started.
diff --git a/init/service.h b/init/service.h
index c29723a..c42a5a3 100644
--- a/init/service.h
+++ b/init/service.h
@@ -68,9 +68,9 @@
             const std::vector<std::string>& args);
 
     Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-            const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
-            unsigned namespace_flags, const std::string& seclabel,
-            Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
+            const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+            const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+            const std::vector<std::string>& args);
 
     static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
 
@@ -192,7 +192,7 @@
     uid_t uid_;
     gid_t gid_;
     std::vector<gid_t> supp_gids_;
-    CapSet capabilities_;
+    std::optional<CapSet> capabilities_;
     unsigned namespace_flags_;
     // Pair of namespace type, path to namespace.
     std::vector<std::pair<int, std::string>> namespaces_to_enter_;
diff --git a/init/service_test.cpp b/init/service_test.cpp
index 194aa2b..4bfaa6b 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -57,7 +57,7 @@
     }
 
     Service* service_in_old_memory2 = new (old_memory) Service(
-        "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), CapSet(), 0U, "", nullptr, dummy_args);
+            "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), 0U, "", nullptr, dummy_args);
 
     EXPECT_EQ(0U, service_in_old_memory2->flags());
     EXPECT_EQ(0, service_in_old_memory2->pid());