Merge "graphics.h: generate some of the enums from HIDL"
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 837902a..7a92d2e 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -198,11 +198,6 @@
         // Ignore the result of calling fchmod. It's not supported
         // by all filesystems, so we don't check for success. b/12441485
         fchmod(fd, mode);
-
-        if (!update_capabilities(path, capabilities)) {
-            SendSyncFailErrno(s, "update_capabilities failed");
-            goto fail;
-        }
     }
 
     while (true) {
@@ -232,6 +227,11 @@
 
     adb_close(fd);
 
+    if (!update_capabilities(path, capabilities)) {
+        SendSyncFailErrno(s, "update_capabilities failed");
+        goto fail;
+    }
+
     utimbuf u;
     u.actime = timestamp;
     u.modtime = timestamp;
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index f03b2dd..2434c78 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -72,6 +72,7 @@
     { "recoveryonly",MF_RECOVERYONLY },
     { "swapprio=",   MF_SWAPPRIO },
     { "zramsize=",   MF_ZRAMSIZE },
+    { "verifyatboot", MF_VERIFYATBOOT },
     { "verify",      MF_VERIFY },
     { "noemulatedsd", MF_NOEMULATEDSD },
     { "notrim",       MF_NOTRIM },
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 6d9492b..120ec5a 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -85,6 +85,7 @@
 #define MF_FORCEFDEORFBE 0x10000
 #define MF_LATEMOUNT    0x20000
 #define MF_NOFAIL       0x40000
+#define MF_VERIFYATBOOT 0x80000
 
 #define DM_BUF_SIZE 4096
 
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 031b042..af57a55 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -32,6 +32,7 @@
 #include <android-base/file.h>
 #include <android-base/strings.h>
 #include <crypto_utils/android_pubkey.h>
+#include <android-base/unique_fd.h>
 #include <cutils/properties.h>
 #include <logwrap/logwrap.h>
 #include <openssl/obj_mac.h>
@@ -73,6 +74,8 @@
 #define VERITY_KMSG_RESTART "dm-verity device corrupted"
 #define VERITY_KMSG_BUFSIZE 1024
 
+#define READ_BUF_SIZE 4096
+
 #define __STRINGIFY(x) #x
 #define STRINGIFY(x) __STRINGIFY(x)
 
@@ -205,6 +208,16 @@
     return 0;
 }
 
+static int destroy_verity_device(struct dm_ioctl *io, char *name, int fd)
+{
+    verity_ioctl_init(io, name, 0);
+    if (ioctl(fd, DM_DEV_REMOVE, io)) {
+        ERROR("Error removing device mapping (%s)", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
 static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name)
 {
     verity_ioctl_init(io, name, 0);
@@ -606,6 +619,30 @@
     return rc;
 }
 
+static int read_partition(const char *path, uint64_t size)
+{
+    char buf[READ_BUF_SIZE];
+    ssize_t size_read;
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)));
+
+    if (fd == -1) {
+        ERROR("Failed to open %s: %s\n", path, strerror(errno));
+        return -errno;
+    }
+
+    while (size) {
+        size_read = TEMP_FAILURE_RETRY(read(fd, buf, READ_BUF_SIZE));
+        if (size_read == -1) {
+            ERROR("Error in reading partition %s: %s\n", path,
+                  strerror(errno));
+            return -errno;
+        }
+        size -= size_read;
+    }
+
+    return 0;
+}
+
 static int compare_last_signature(struct fstab_rec *fstab, int *match)
 {
     char tag[METADATA_TAG_MAX_LENGTH + 1];
@@ -900,6 +937,7 @@
     struct fec_handle *f = NULL;
     struct fec_verity_metadata verity;
     struct verity_table_params params = { .table = NULL };
+    bool verified_at_boot = false;
 
     alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
     struct dm_ioctl *io = (struct dm_ioctl *) buffer;
@@ -1037,10 +1075,26 @@
     // mark the underlying block device as read-only
     fs_mgr_set_blk_ro(fstab->blk_device);
 
+    // Verify the entire partition in one go
+    // If there is an error, allow it to mount as a normal verity partition.
+    if (fstab->fs_mgr_flags & MF_VERIFYATBOOT) {
+        INFO("Verifying partition %s at boot\n", fstab->blk_device);
+        int err = read_partition(verity_blk_name, verity.data_size);
+        if (!err) {
+            INFO("Verified verity partition %s at boot\n", fstab->blk_device);
+            verified_at_boot = true;
+        }
+    }
+
     // assign the new verity block device as the block device
-    free(fstab->blk_device);
-    fstab->blk_device = verity_blk_name;
-    verity_blk_name = 0;
+    if (!verified_at_boot) {
+        free(fstab->blk_device);
+        fstab->blk_device = verity_blk_name;
+        verity_blk_name = 0;
+    } else if (destroy_verity_device(io, mount_point, fd) < 0) {
+        ERROR("Failed to remove verity device %s\n", mount_point);
+        goto out;
+    }
 
     // make sure we've set everything up properly
     if (test_access(fstab->blk_device) < 0) {
diff --git a/init/Android.mk b/init/Android.mk
index 1be064c..4bfd743 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -45,6 +45,7 @@
 LOCAL_CPPFLAGS := $(init_cflags)
 LOCAL_SRC_FILES:= \
     action.cpp \
+    capabilities.cpp \
     import_parser.cpp \
     init_parser.cpp \
     log.cpp \
@@ -53,6 +54,7 @@
     util.cpp \
 
 LOCAL_STATIC_LIBRARIES := libbase libselinux liblog libprocessgroup
+LOCAL_WHOLE_STATIC_LIBRARIES := libcap
 LOCAL_MODULE := libinit
 LOCAL_SANITIZE := integer
 LOCAL_CLANG := true
@@ -102,7 +104,7 @@
     libz \
     libprocessgroup
 
-# Create symlinks
+# Create symlinks.
 LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
     ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
     ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdogd
@@ -112,8 +114,8 @@
 include $(BUILD_EXECUTABLE)
 
 
-
-
+# Unit tests.
+# =========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := init_tests
 LOCAL_SRC_FILES := \
diff --git a/init/capabilities.cpp b/init/capabilities.cpp
new file mode 100644
index 0000000..4592adc
--- /dev/null
+++ b/init/capabilities.cpp
@@ -0,0 +1,166 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "capabilities.h"
+
+#include <sys/capability.h>
+#include <sys/prctl.h>
+
+#include <map>
+#include <memory>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+
+#define CAP_MAP_ENTRY(cap) { #cap, CAP_##cap }
+
+namespace {
+const std::map<std::string, int> cap_map = {
+    CAP_MAP_ENTRY(CHOWN),
+    CAP_MAP_ENTRY(DAC_OVERRIDE),
+    CAP_MAP_ENTRY(DAC_READ_SEARCH),
+    CAP_MAP_ENTRY(FOWNER),
+    CAP_MAP_ENTRY(FSETID),
+    CAP_MAP_ENTRY(KILL),
+    CAP_MAP_ENTRY(SETGID),
+    CAP_MAP_ENTRY(SETUID),
+    CAP_MAP_ENTRY(SETPCAP),
+    CAP_MAP_ENTRY(LINUX_IMMUTABLE),
+    CAP_MAP_ENTRY(NET_BIND_SERVICE),
+    CAP_MAP_ENTRY(NET_BROADCAST),
+    CAP_MAP_ENTRY(NET_ADMIN),
+    CAP_MAP_ENTRY(NET_RAW),
+    CAP_MAP_ENTRY(IPC_LOCK),
+    CAP_MAP_ENTRY(IPC_OWNER),
+    CAP_MAP_ENTRY(SYS_MODULE),
+    CAP_MAP_ENTRY(SYS_RAWIO),
+    CAP_MAP_ENTRY(SYS_CHROOT),
+    CAP_MAP_ENTRY(SYS_PTRACE),
+    CAP_MAP_ENTRY(SYS_PACCT),
+    CAP_MAP_ENTRY(SYS_ADMIN),
+    CAP_MAP_ENTRY(SYS_BOOT),
+    CAP_MAP_ENTRY(SYS_NICE),
+    CAP_MAP_ENTRY(SYS_RESOURCE),
+    CAP_MAP_ENTRY(SYS_TIME),
+    CAP_MAP_ENTRY(SYS_TTY_CONFIG),
+    CAP_MAP_ENTRY(MKNOD),
+    CAP_MAP_ENTRY(LEASE),
+    CAP_MAP_ENTRY(AUDIT_WRITE),
+    CAP_MAP_ENTRY(AUDIT_CONTROL),
+    CAP_MAP_ENTRY(SETFCAP),
+    CAP_MAP_ENTRY(MAC_OVERRIDE),
+    CAP_MAP_ENTRY(MAC_ADMIN),
+    CAP_MAP_ENTRY(SYSLOG),
+    CAP_MAP_ENTRY(WAKE_ALARM),
+    CAP_MAP_ENTRY(BLOCK_SUSPEND),
+    CAP_MAP_ENTRY(AUDIT_READ),
+};
+
+static_assert(CAP_LAST_CAP == CAP_AUDIT_READ, "CAP_LAST_CAP is not CAP_AUDIT_READ");
+
+bool DropBoundingSet(const CapSet& to_keep) {
+    for (size_t cap = 0; cap < to_keep.size(); ++cap) {
+        if (to_keep.test(cap)) {
+            // No need to drop this capability.
+            continue;
+        }
+        if (cap_drop_bound(cap) == -1) {
+            PLOG(ERROR) << "cap_drop_bound(" << cap << ") failed";
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SetProcCaps(const CapSet& to_keep, bool add_setpcap) {
+    cap_t caps = cap_init();
+    auto deleter = [](cap_t* p) { cap_free(*p); };
+    std::unique_ptr<cap_t, decltype(deleter)> ptr_caps(&caps, deleter);
+
+    cap_clear(caps);
+    cap_value_t value[1];
+    for (size_t cap = 0; cap <= to_keep.size(); ++cap) {
+        if (to_keep.test(cap)) {
+            value[0] = cap;
+            if (cap_set_flag(caps, CAP_INHERITABLE, arraysize(value), value, CAP_SET) != 0 ||
+                cap_set_flag(caps, CAP_PERMITTED, arraysize(value), value, CAP_SET) != 0) {
+                PLOG(ERROR) << "cap_set_flag(INHERITABLE|PERMITTED, " << cap << ") failed";
+                return false;
+            }
+        }
+    }
+
+    if (add_setpcap) {
+        value[0] = CAP_SETPCAP;
+        if (cap_set_flag(caps, CAP_PERMITTED, arraysize(value), value, CAP_SET) != 0 ||
+            cap_set_flag(caps, CAP_EFFECTIVE, arraysize(value), value, CAP_SET) != 0) {
+            PLOG(ERROR) << "cap_set_flag(PERMITTED|EFFECTIVE, " << CAP_SETPCAP << ") failed";
+            return false;
+        }
+    }
+
+    if (cap_set_proc(caps) != 0) {
+        PLOG(ERROR) << "cap_set_proc(" << to_keep.to_ulong() << ") failed";
+        return false;
+    }
+    return true;
+}
+
+bool SetAmbientCaps(const CapSet& to_raise) {
+    for (size_t cap = 0; cap < to_raise.size(); ++cap) {
+        if (to_raise.test(cap)) {
+            if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) != 0) {
+                PLOG(ERROR) << "prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, " << cap << ") failed";
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+}  // namespace anonymous
+
+int LookupCap(const std::string& cap_name) {
+    auto e = cap_map.find(cap_name);
+    if (e != cap_map.end()) {
+        return e->second;
+    } else {
+        return -1;
+    }
+}
+
+bool SetCapsForExec(const CapSet& to_keep) {
+    // Need to keep SETPCAP to drop bounding set below.
+    bool add_setpcap = true;
+    if (!SetProcCaps(to_keep, add_setpcap)) {
+        LOG(ERROR) << "failed to apply initial capset";
+        return false;
+    }
+
+    if (!DropBoundingSet(to_keep)) {
+        return false;
+    }
+
+    // If SETPCAP wasn't specifically requested, drop it now.
+    add_setpcap = false;
+    if (!SetProcCaps(to_keep, add_setpcap)) {
+        LOG(ERROR) << "failed to apply final capset";
+        return false;
+    }
+
+    // Add the capabilities to the ambient set so that they are preserved across
+    // execve(2).
+    // See http://man7.org/linux/man-pages/man7/capabilities.7.html.
+    return SetAmbientCaps(to_keep);
+}
diff --git a/init/capabilities.h b/init/capabilities.h
new file mode 100644
index 0000000..368178d
--- /dev/null
+++ b/init/capabilities.h
@@ -0,0 +1,23 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <linux/capability.h>
+
+#include <bitset>
+#include <string>
+
+using CapSet = std::bitset<CAP_LAST_CAP + 1>;
+
+int LookupCap(const std::string& cap_name);
+bool SetCapsForExec(const CapSet& to_keep);
diff --git a/init/readme.txt b/init/readme.txt
index 77e5de2..e01faa9 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -149,25 +149,33 @@
   computed based on the service executable file security context.
 
 user <username>
-  Change to username before exec'ing this service.
+  Change to 'username' before exec'ing this service.
   Currently defaults to root.  (??? probably should default to nobody)
   As of Android M, processes should use this option even if they
-  require linux capabilities.  Previously, to acquire linux
+  require Linux capabilities.  Previously, to acquire Linux
   capabilities, a process would need to run as root, request the
   capabilities, then drop to its desired uid.  There is a new
   mechanism through fs_config that allows device manufacturers to add
-  linux capabilities to specific binaries on a file system that should
+  Linux capabilities to specific binaries on a file system that should
   be used instead. This mechanism is described on
   http://source.android.com/devices/tech/config/filesystem.html.  When
   using this new mechanism, processes can use the user option to
   select their desired uid without ever running as root.
+  As of Android O, processes can also request capabilities directly in their .rc
+  files. See the "capabilities" option below.
 
 group <groupname> [ <groupname> ]*
-  Change to groupname before exec'ing this service.  Additional
+  Change to 'groupname' before exec'ing this service.  Additional
   groupnames beyond the (required) first one are used to set the
   supplemental groups of the process (via setgroups()).
   Currently defaults to root.  (??? probably should default to nobody)
 
+capabilities <capability> [ <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.
+
 seclabel <seclabel>
   Change to 'seclabel' before exec'ing this service.
   Primarily for use by services run from the rootfs, e.g. ueventd, adbd.
diff --git a/init/service.cpp b/init/service.cpp
index 92f1615..e052b45 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -17,6 +17,7 @@
 #include "service.h"
 
 #include <fcntl.h>
+#include <linux/securebits.h>
 #include <sched.h>
 #include <sys/mount.h>
 #include <sys/prctl.h>
@@ -171,14 +172,16 @@
 
 Service::Service(const std::string& name, const std::string& classname,
                  unsigned flags, uid_t uid, gid_t gid,
-                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+                 const std::vector<gid_t>& supp_gids,
+                 const CapSet& capabilities, unsigned namespace_flags,
                  const std::string& seclabel,
                  const std::vector<std::string>& args)
     : name_(name), classname_(classname), flags_(flags), pid_(0),
       time_started_(0), time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid),
-      supp_gids_(supp_gids), namespace_flags_(namespace_flags),
-      seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
-      priority_(0), oom_score_adjust_(-1000), args_(args) {
+      supp_gids_(supp_gids), capabilities_(capabilities),
+      namespace_flags_(namespace_flags), seclabel_(seclabel),
+      ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0),
+      oom_score_adjust_(-1000), args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
@@ -225,6 +228,13 @@
 }
 
 void Service::SetProcessAttributes() {
+    // Keep capabilites on uid change.
+    if (capabilities_.any() && uid_) {
+        if (prctl(PR_SET_SECUREBITS, SECBIT_KEEP_CAPS | SECBIT_KEEP_CAPS_LOCKED) != 0) {
+            PLOG(FATAL) << "prtcl(PR_SET_KEEPCAPS) failed for " << name_;
+        }
+    }
+
     // TODO: work out why this fails for `console` then upgrade to FATAL.
     if (setpgid(0, getpid()) == -1) PLOG(ERROR) << "setpgid failed for " << name_;
 
@@ -251,6 +261,11 @@
             PLOG(FATAL) << "setpriority failed for " << name_;
         }
     }
+    if (capabilities_.any()) {
+        if (!SetCapsForExec(capabilities_)) {
+            LOG(FATAL) << "cannot set capabilities for " << name_;
+        }
+    }
 }
 
 bool Service::Reap() {
@@ -320,6 +335,21 @@
     }
 }
 
+bool Service::ParseCapabilities(const std::vector<std::string>& args, std::string* err) {
+    capabilities_ = 0;
+
+    for (size_t i = 1; i < args.size(); i++) {
+        const std::string& arg = args[i];
+        int cap = LookupCap(arg);
+        if (cap == -1) {
+            *err = StringPrintf("invalid capability '%s'", arg.c_str());
+            return false;
+        }
+        capabilities_[cap] = true;
+    }
+    return true;
+}
+
 bool Service::ParseClass(const std::vector<std::string>& args, std::string* err) {
     classname_ = args[1];
     return true;
@@ -476,6 +506,8 @@
 Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
     static const Map option_parsers = {
+        {"capabilities",
+                        {1,     kMax, &Service::ParseCapabilities}},
         {"class",       {1,     1,    &Service::ParseClass}},
         {"console",     {0,     1,    &Service::ParseConsole}},
         {"critical",    {0,     0,    &Service::ParseCritical}},
@@ -807,6 +839,7 @@
     exec_count_++;
     std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str());
     unsigned flags = SVC_EXEC | SVC_ONESHOT;
+    CapSet no_capabilities;
     unsigned namespace_flags = 0;
 
     std::string seclabel = "";
@@ -827,9 +860,9 @@
         }
     }
 
-    std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid,
-                                               supp_gids, namespace_flags,
-                                               seclabel, str_args));
+    std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid, supp_gids,
+                                               no_capabilities, namespace_flags, seclabel,
+                                               str_args));
     if (!svc_p) {
         LOG(ERROR) << "Couldn't allocate service for exec of '" << str_args[0] << "'";
         return nullptr;
diff --git a/init/service.h b/init/service.h
index 4a3412c..7f035ef 100644
--- a/init/service.h
+++ b/init/service.h
@@ -26,6 +26,7 @@
 #include <vector>
 
 #include "action.h"
+#include "capabilities.h"
 #include "init_parser.h"
 #include "keyword_map.h"
 
@@ -73,8 +74,9 @@
 
     Service(const std::string& name, const std::string& classname,
             unsigned flags, uid_t uid, gid_t gid,
-            const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
-            const std::string& seclabel, const std::vector<std::string>& args);
+            const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
+            unsigned namespace_flags, const std::string& seclabel,
+            const std::vector<std::string>& args);
 
     bool ParseLine(const std::vector<std::string>& args, std::string* err);
     bool Start();
@@ -116,6 +118,7 @@
     void CreateSockets(const std::string& scon);
     void SetProcessAttributes();
 
+    bool ParseCapabilities(const std::vector<std::string>& args, std::string *err);
     bool ParseClass(const std::vector<std::string>& args, std::string* err);
     bool ParseConsole(const std::vector<std::string>& args, std::string* err);
     bool ParseCritical(const std::vector<std::string>& args, std::string* err);
@@ -147,6 +150,7 @@
     uid_t uid_;
     gid_t gid_;
     std::vector<gid_t> supp_gids_;
+    CapSet capabilities_;
     unsigned namespace_flags_;
 
     std::string seclabel_;
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 293e78a..966eafc 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -153,6 +153,14 @@
     /* Support wifi_hal_legacy administering a network interface. */
     { 00755, AID_WIFI,      AID_WIFI,     CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_NET_RAW),    "system/bin/hw/android.hardware.wifi@1.0-service" },
 
+    /* A non-privileged zygote that spawns isolated processes for web rendering. */
+    { 0750,  AID_ROOT,      AID_ROOT,      CAP_MASK_LONG(CAP_SETUID) |
+                                           CAP_MASK_LONG(CAP_SETGID) |
+                                           CAP_MASK_LONG(CAP_SETPCAP), "system/bin/webview_zygote32" },
+    { 0750,  AID_ROOT,      AID_ROOT,      CAP_MASK_LONG(CAP_SETUID) |
+                                           CAP_MASK_LONG(CAP_SETGID) |
+                                           CAP_MASK_LONG(CAP_SETPCAP), "system/bin/webview_zygote64" },
+
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
index 3d58147..f05a955 100644
--- a/liblog/tests/libc_test.cpp
+++ b/liblog/tests/libc_test.cpp
@@ -16,6 +16,7 @@
 
 #include <gtest/gtest.h>
 
+#include <errno.h>
 #include <stdio.h>
 
 TEST(libc, __pstore_append) {
@@ -23,6 +24,22 @@
     ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "a")));
     static const char message[] = "libc.__pstore_append\n";
     ASSERT_EQ((size_t)1, fwrite(message, sizeof(message), 1, fp));
-    ASSERT_EQ(0, fclose(fp));
-    fprintf(stderr, "Reboot, ensure string libc.__pstore_append is in /sys/fs/pstore/pmsg-ramoops-0\n");
+    int fflushReturn = fflush(fp);
+    int fflushErrno = fflushReturn ? errno : 0;
+    ASSERT_EQ(0, fflushReturn);
+    ASSERT_EQ(0, fflushErrno);
+    int fcloseReturn = fclose(fp);
+    int fcloseErrno = fcloseReturn ? errno : 0;
+    ASSERT_EQ(0, fcloseReturn);
+    ASSERT_EQ(0, fcloseErrno);
+    if ((fcloseErrno == ENOMEM) || (fflushErrno == ENOMEM)) {
+        fprintf(stderr,
+                "Kernel does not have space allocated to pmsg pstore driver configured\n"
+               );
+    }
+    if (!fcloseReturn && !fcloseErrno && !fflushReturn && !fflushReturn) {
+        fprintf(stderr,
+                "Reboot, ensure string libc.__pstore_append is in /sys/fs/pstore/pmsg-ramoops-0\n"
+               );
+    }
 }
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index fd38849..9c09523 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -16,6 +16,7 @@
 
 #include <ctype.h>
 #include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <semaphore.h>
@@ -2655,12 +2656,19 @@
     bool logdwActiveAfter__android_log_close = isLogdwActive();
     EXPECT_FALSE(pmsgActiveAfter__android_log_close);
     EXPECT_FALSE(logdwActiveAfter__android_log_close);
-    EXPECT_LT(0, __android_log_pmsg_file_write(
+    int return__android_log_pmsg_file_write = __android_log_pmsg_file_write(
             LOG_ID_CRASH, ANDROID_LOG_VERBOSE,
-            __pmsg_file, max_payload_buf, sizeof(max_payload_buf)));
-    fprintf(stderr, "Reboot, ensure file %s matches\n"
-                    "with liblog.__android_log_msg_file_read test\n",
-                    __pmsg_file);
+            __pmsg_file, max_payload_buf, sizeof(max_payload_buf));
+    EXPECT_LT(0, return__android_log_pmsg_file_write);
+    if (return__android_log_pmsg_file_write == -ENOMEM) {
+        fprintf(stderr,
+                "Kernel does not have space allocated to pmsg pstore driver configured\n"
+               );
+    } else if (!return__android_log_pmsg_file_write) {
+        fprintf(stderr, "Reboot, ensure file %s matches\n"
+                        "with liblog.__android_log_msg_file_read test\n",
+                        __pmsg_file);
+    }
     bool pmsgActiveAfter__android_pmsg_file_write = isPmsgActive();
     bool logdwActiveAfter__android_pmsg_file_write = isLogdwActive();
     EXPECT_FALSE(pmsgActiveAfter__android_pmsg_file_write);
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index fb95cb6..e09cce3 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -473,14 +473,14 @@
 }
 
 #if defined(__ANDROID__)
+// native_bridge_namespaces are not supported for callers of this function.
+// This function will return nullptr in the case when application is running
+// on native bridge.
 android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-  // native_bridge_namespaces are not supported for callers of this function.
-  // At the moment this is libwebviewchromium_loader and vulkan.
   NativeLoaderNamespace ns;
   if (g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
-    CHECK(ns.is_android_namespace());
-    return ns.get_android_ns();
+    return ns.is_android_namespace() ? ns.get_android_ns() : nullptr;
   }
 
   return nullptr;
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 3811daa..c3ccd84 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -25,6 +25,7 @@
 #include <sys/uio.h>
 #include <syslog.h>
 
+#include <android-base/macros.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
@@ -143,7 +144,7 @@
                     iov[2].iov_len = strlen(newline);
                 }
 
-                writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+                writev(fdDmesg, iov, arraysize(iov));
                 free(last_str);
                 last_str = NULL;
             }
@@ -165,7 +166,7 @@
             iov[2].iov_base = const_cast<char *>(newline);
             iov[2].iov_len = strlen(newline);
 
-            writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+            writev(fdDmesg, iov, arraysize(iov));
         }
     }
 
diff --git a/logd/main.cpp b/logd/main.cpp
index 0cb26dc..1ac1415 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -106,6 +106,11 @@
         return -1;
     }
 
+    if (prctl(PR_SET_DUMPABLE, 0) < 0) {
+        android::prdebug("failed to clear PR_SET_DUMPABLE");
+        return -1;
+    }
+
     gid_t groups[] = { AID_READPROC };
     ScopedMinijail j(minijail_new());
     minijail_set_supplementary_gids(j.get(), arraysize(groups), groups);
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index e0a4cc3..254a3f8 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -23,6 +23,7 @@
 
 #include <string>
 
+#include <android-base/macros.h>
 #include <android-base/stringprintf.h>
 #include <cutils/sockets.h>
 #include <gtest/gtest.h>
@@ -351,7 +352,7 @@
         "/dev/log/system", "/dev/log_system",
     };
 
-    for (unsigned int i = 0; i < (sizeof(loggers) / sizeof(loggers[0])); ++i) {
+    for (unsigned int i = 0; i < arraysize(loggers); ++i) {
         fd = open(loggers[i], O_RDONLY);
         if (fd < 0) {
             continue;
@@ -434,12 +435,12 @@
     static const unsigned int log_latency = 4;
     static const unsigned int log_delay = 5;
 
-    unsigned long ns[sizeof(benchmarks) / sizeof(benchmarks[0])];
+    unsigned long ns[arraysize(benchmarks)];
 
     memset(ns, 0, sizeof(ns));
 
     while (fgets(buffer, sizeof(buffer), fp)) {
-        for (unsigned i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) {
+        for (unsigned i = 0; i < arraysize(ns); ++i) {
             char *cp = strstr(buffer, benchmarks[i]);
             if (!cp) {
                 continue;
@@ -470,7 +471,7 @@
 
     EXPECT_GE(20000000UL, ns[log_delay]); // 10500289 user
 
-    for (unsigned i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) {
+    for (unsigned i = 0; i < arraysize(ns); ++i) {
         EXPECT_NE(0UL, ns[i]);
     }
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 31b1821..8f0b932 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -669,13 +669,3 @@
 service flash_recovery /system/bin/install-recovery.sh
     class main
     oneshot
-
-service hwservicemanager /system/bin/hwservicemanager
-    user system
-    disabled
-    group system readproc
-    critical
-    writepid /dev/cpuset/system-background/tasks
-
-on property:hwservicemanager.ready=true
-    class_start hal
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index 2d7d5c2..eedeba8 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -1,6 +1,8 @@
 service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 4156847..84a907f 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -1,6 +1,8 @@
 service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
@@ -13,6 +15,8 @@
 service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 8584cbb..76e2b79 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -1,6 +1,8 @@
 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 27eaa66..e918b67 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -1,6 +1,8 @@
 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
@@ -13,6 +15,8 @@
 service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks