Merge "libsnapshot: refactor CreateUpdateSnapshots"
diff --git a/adb/Android.bp b/adb/Android.bp
index 9ef82bf..3dc70b5 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -253,7 +253,7 @@
         "libbase",
         "libcutils",
         "libcrypto_utils",
-        "libcrypto",
+        "libcrypto_static",
         "libdiagnose_usb",
         "liblog",
         "libusb",
@@ -553,7 +553,7 @@
         "libbase",
         "libbootloader_message",
         "libcap",
-        "libcrypto",
+        "libcrypto_static",
         "libcrypto_utils",
         "libcutils",
         "libdiagnose_usb",
@@ -621,7 +621,7 @@
         "libbootloader_message",
         "libcutils",
         "libcrypto_utils",
-        "libcrypto",
+        "libcrypto_static",
         "libdiagnose_usb",
         "liblog",
         "libusb",
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index bbeb181..d09b8e8 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -100,7 +100,7 @@
 
   static CrashQueue* for_tombstones() {
     static CrashQueue queue("/data/tombstones", "tombstone_" /* file_name_prefix */,
-                            GetIntProperty("tombstoned.max_tombstone_count", 10),
+                            GetIntProperty("tombstoned.max_tombstone_count", 32),
                             1 /* max_concurrent_dumps */);
     return &queue;
   }
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index 7fee83c..178b343 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -17,7 +17,6 @@
 liblp_lib_deps = [
     "libbase",
     "liblog",
-    "libcrypto",
     "libcrypto_utils",
     "libsparse",
     "libext4_utils",
@@ -41,7 +40,9 @@
         "utility.cpp",
         "writer.cpp",
     ],
-    shared_libs: liblp_lib_deps,
+    shared_libs: [
+        "libcrypto",
+    ] + liblp_lib_deps,
     target: {
         windows: {
             enabled: true,
@@ -83,6 +84,7 @@
         "libgmock",
         "libfs_mgr",
         "liblp",
+        "libcrypto_static",
     ] + liblp_lib_deps,
     header_libs: [
         "libstorage_literals_headers",
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index a012099..834bf3b 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -102,7 +102,7 @@
     ],
     static_libs: [
         "libcutils",
-        "libcrypto",
+        "libcrypto_static",
         "libfs_mgr",
         "libgmock",
         "liblp",
diff --git a/init/Android.mk b/init/Android.mk
index 8f58437..62e452f 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -100,7 +100,7 @@
     libcutils \
     libbase \
     liblog \
-    libcrypto \
+    libcrypto_static \
     libdl \
     libz \
     libselinux \
@@ -108,7 +108,7 @@
     libgsi \
     libcom.android.sysprop.apex \
     liblzma \
-    libdexfile_support \
+    libdexfile_support_static \
     libunwindstack \
     libbacktrace \
     libmodprobe \
@@ -118,7 +118,6 @@
 LOCAL_SANITIZE := signed-integer-overflow
 # First stage init is weird: it may start without stdout/stderr, and no /proc.
 LOCAL_NOSANITIZE := hwaddress
-LOCAL_INJECT_BSSL_HASH := true
 include $(BUILD_EXECUTABLE)
 endif
 
diff --git a/init/devices.cpp b/init/devices.cpp
index f6e453a..9fbec64 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -441,6 +441,23 @@
     }
 }
 
+void DeviceHandler::HandleAshmemUevent(const Uevent& uevent) {
+    if (uevent.device_name == "ashmem") {
+        static const std::string boot_id_path = "/proc/sys/kernel/random/boot_id";
+        std::string boot_id;
+        if (!ReadFileToString(boot_id_path, &boot_id)) {
+            PLOG(ERROR) << "Cannot duplicate ashmem device node. Failed to read " << boot_id_path;
+            return;
+        };
+        boot_id = Trim(boot_id);
+
+        Uevent dup_ashmem_uevent = uevent;
+        dup_ashmem_uevent.device_name += boot_id;
+        dup_ashmem_uevent.path += boot_id;
+        HandleUevent(dup_ashmem_uevent);
+    }
+}
+
 void DeviceHandler::HandleUevent(const Uevent& uevent) {
     if (uevent.action == "add" || uevent.action == "change" || uevent.action == "online") {
         FixupSysPermissions(uevent.path, uevent.subsystem);
@@ -485,6 +502,10 @@
     mkdir_recursive(Dirname(devpath), 0755);
 
     HandleDevice(uevent.action, devpath, block, uevent.major, uevent.minor, links);
+
+    // Duplicate /dev/ashmem device and name it /dev/ashmem<boot_id>.
+    // TODO(b/111903542): remove once all users of /dev/ashmem are migrated to libcutils API.
+    HandleAshmemUevent(uevent);
 }
 
 void DeviceHandler::ColdbootDone() {
diff --git a/init/devices.h b/init/devices.h
index 442c53f..05d64da 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -130,6 +130,7 @@
     void HandleDevice(const std::string& action, const std::string& devpath, bool block, int major,
                       int minor, const std::vector<std::string>& links) const;
     void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
+    void HandleAshmemUevent(const Uevent& uevent);
 
     std::vector<Permissions> dev_permissions_;
     std::vector<SysfsPermissions> sysfs_permissions_;
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index e67b458..340572c 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -23,9 +23,6 @@
  */
 #define LOG_TAG "ashmem"
 
-#ifndef __ANDROID_VNDK__
-#include <dlfcn.h>
-#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/ashmem.h>
@@ -42,11 +39,11 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <android-base/file.h>
 #include <android-base/properties.h>
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 
-#define ASHMEM_DEVICE "/dev/ashmem"
-
 /* Will be added to UAPI once upstream change is merged */
 #define F_SEAL_FUTURE_WRITE 0x0010
 
@@ -66,32 +63,6 @@
 static pthread_mutex_t __ashmem_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /*
- * We use ashmemd to enforce that apps don't open /dev/ashmem directly. Vendor
- * code can't access system aidl services per Treble requirements. So we limit
- * ashmemd access to the system variant of libcutils.
- */
-#ifndef __ANDROID_VNDK__
-using openFdType = int (*)();
-
-static openFdType openFd;
-
-openFdType initOpenAshmemFd() {
-    openFdType openFd = nullptr;
-    void* handle = dlopen("libashmemd_client.so", RTLD_NOW);
-    if (!handle) {
-        ALOGE("Failed to dlopen() libashmemd_client.so: %s", dlerror());
-        return openFd;
-    }
-
-    openFd = reinterpret_cast<openFdType>(dlsym(handle, "openAshmemdFd"));
-    if (!openFd) {
-        ALOGE("Failed to dlsym() openAshmemdFd() function: %s", dlerror());
-    }
-    return openFd;
-}
-#endif
-
-/*
  * has_memfd_support() determines if the device can use memfd. memfd support
  * has been there for long time, but certain things in it may be missing.  We
  * check for needed support in it. Also we check if the VNDK version of
@@ -215,25 +186,31 @@
     return memfd_supported;
 }
 
+static std::string get_ashmem_device_path() {
+    static const std::string boot_id_path = "/proc/sys/kernel/random/boot_id";
+    std::string boot_id;
+    if (!android::base::ReadFileToString(boot_id_path, &boot_id)) {
+        ALOGE("Failed to read %s: %s.\n", boot_id_path.c_str(), strerror(errno));
+        return "";
+    };
+    boot_id = android::base::Trim(boot_id);
+
+    return "/dev/ashmem" + boot_id;
+}
+
 /* logistics of getting file descriptor for ashmem */
 static int __ashmem_open_locked()
 {
+    static const std::string ashmem_device_path = get_ashmem_device_path();
+
     int ret;
     struct stat st;
 
-    int fd = -1;
-#ifndef __ANDROID_VNDK__
-    if (!openFd) {
-        openFd = initOpenAshmemFd();
+    if (ashmem_device_path.empty()) {
+        return -1;
     }
 
-    if (openFd) {
-        fd = openFd();
-    }
-#endif
-    if (fd < 0) {
-        fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC));
-    }
+    int fd = TEMP_FAILURE_RETRY(open(ashmem_device_path.c_str(), O_RDWR | O_CLOEXEC));
     if (fd < 0) {
         return fd;
     }
@@ -485,11 +462,3 @@
 
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)));
 }
-
-void ashmem_init() {
-#ifndef __ANDROID_VNDK__
-    pthread_mutex_lock(&__ashmem_lock);
-    openFd = initOpenAshmemFd();
-    pthread_mutex_unlock(&__ashmem_lock);
-#endif  //__ANDROID_VNDK__
-}
diff --git a/libcutils/ashmem-host.cpp b/libcutils/ashmem-host.cpp
index 6c7655a..2ba1eb0 100644
--- a/libcutils/ashmem-host.cpp
+++ b/libcutils/ashmem-host.cpp
@@ -94,5 +94,3 @@
 
     return buf.st_size;
 }
-
-void ashmem_init() {}
diff --git a/libcutils/include/cutils/ashmem.h b/libcutils/include/cutils/ashmem.h
index abc5068..d80caa6 100644
--- a/libcutils/include/cutils/ashmem.h
+++ b/libcutils/include/cutils/ashmem.h
@@ -26,7 +26,6 @@
 int ashmem_pin_region(int fd, size_t offset, size_t len);
 int ashmem_unpin_region(int fd, size_t offset, size_t len);
 int ashmem_get_size_region(int fd);
-void ashmem_init();
 
 #ifdef __cplusplus
 }
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 2ec4754..88146e9 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -82,3 +82,15 @@
         },
     },
 }
+
+cc_fuzz {
+    name: "sparse_fuzzer",
+    host_supported: false,
+    srcs: [
+        "sparse_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libsparse",
+        "liblog",
+    ],
+}
diff --git a/libsparse/sparse_fuzzer.cpp b/libsparse/sparse_fuzzer.cpp
new file mode 100644
index 0000000..42f331f
--- /dev/null
+++ b/libsparse/sparse_fuzzer.cpp
@@ -0,0 +1,16 @@
+#include "include/sparse/sparse.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  if (size < 2 * sizeof(wchar_t)) return 0;
+
+  int64_t blocksize = 4096;
+  struct sparse_file* file = sparse_file_new(size, blocksize);
+  if (!file) {
+    return 0;
+  }
+
+  unsigned int block = 1;
+  sparse_file_add_data(file, &data, size, block);
+  sparse_file_destroy(file);
+  return 0;
+}
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index b6c33d7..80625a7 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -349,86 +349,6 @@
 }
 #endif
 
-TEST(logd, both) {
-#ifdef __ANDROID__
-    log_msg msg;
-
-    // check if we can read any logs from logd
-    bool user_logger_available = false;
-    bool user_logger_content = false;
-
-    int fd = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED,
-                                 SOCK_SEQPACKET);
-    if (fd >= 0) {
-        struct sigaction ignore, old_sigaction;
-        memset(&ignore, 0, sizeof(ignore));
-        ignore.sa_handler = caught_signal;
-        sigemptyset(&ignore.sa_mask);
-        sigaction(SIGALRM, &ignore, &old_sigaction);
-        unsigned int old_alarm = alarm(10);
-
-        static const char ask[] = "dumpAndClose lids=0,1,2,3";
-        user_logger_available = write(fd, ask, sizeof(ask)) == sizeof(ask);
-
-        user_logger_content = recv(fd, msg.buf, sizeof(msg), 0) > 0;
-
-        if (user_logger_content) {
-            dump_log_msg("user", &msg, 3, -1);
-        }
-
-        alarm(old_alarm);
-        sigaction(SIGALRM, &old_sigaction, nullptr);
-
-        close(fd);
-    }
-
-    // check if we can read any logs from kernel logger
-    bool kernel_logger_available = false;
-    bool kernel_logger_content = false;
-
-    static const char* loggers[] = {
-        "/dev/log/main",   "/dev/log_main",   "/dev/log/radio",
-        "/dev/log_radio",  "/dev/log/events", "/dev/log_events",
-        "/dev/log/system", "/dev/log_system",
-    };
-
-    for (unsigned int i = 0; i < arraysize(loggers); ++i) {
-        fd = open(loggers[i], O_RDONLY);
-        if (fd < 0) {
-            continue;
-        }
-        kernel_logger_available = true;
-        fcntl(fd, F_SETFL, O_RDONLY | O_NONBLOCK);
-        int result = TEMP_FAILURE_RETRY(read(fd, msg.buf, sizeof(msg)));
-        if (result > 0) {
-            kernel_logger_content = true;
-            dump_log_msg("kernel", &msg, 0, i / 2);
-        }
-        close(fd);
-    }
-
-    static const char yes[] = "\xE2\x9C\x93";
-    static const char no[] = "\xE2\x9c\x98";
-    fprintf(stderr,
-            "LOGGER  Available  Content\n"
-            "user    %-13s%s\n"
-            "kernel  %-13s%s\n"
-            " status %-11s%s\n",
-            (user_logger_available) ? yes : no, (user_logger_content) ? yes : no,
-            (kernel_logger_available) ? yes : no,
-            (kernel_logger_content) ? yes : no,
-            (user_logger_available && kernel_logger_available) ? "ERROR" : "ok",
-            (user_logger_content && kernel_logger_content) ? "ERROR" : "ok");
-
-    EXPECT_EQ(0, user_logger_available && kernel_logger_available);
-    EXPECT_EQ(0, !user_logger_available && !kernel_logger_available);
-    EXPECT_EQ(0, user_logger_content && kernel_logger_content);
-    EXPECT_EQ(0, !user_logger_content && !kernel_logger_content);
-#else
-    GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
 #ifdef __ANDROID__
 // BAD ROBOT
 //   Benchmark threshold are generally considered bad form unless there is
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
index d3538b3..b1f6410 100644
--- a/logwrapper/include/logwrap/logwrap.h
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -15,8 +15,7 @@
  * limitations under the License.
  */
 
-#ifndef __LIBS_LOGWRAP_H
-#define __LIBS_LOGWRAP_H
+#pragma once
 
 #include <stdbool.h>
 #include <stdint.h>
@@ -26,12 +25,6 @@
 /*
  * Run a command while logging its stdout and stderr
  *
- * WARNING: while this function is running it will clear all SIGCHLD handlers
- * if you rely on SIGCHLD in the caller there is a chance zombies will be
- * created if you're not calling waitpid after calling this. This function will
- * log a warning when it clears SIGCHLD for processes other than the child it
- * created.
- *
  * Arguments:
  *   argc:   the number of elements in argv
  *   argv:   an array of strings containing the command to be executed and its
@@ -40,10 +33,10 @@
  *   status: the equivalent child status as populated by wait(status). This
  *           value is only valid when logwrap successfully completes. If NULL
  *           the return value of the child will be the function's return value.
- *   ignore_int_quit: set to true if you want to completely ignore SIGINT and
- *           SIGQUIT while logwrap is running. This may force the end-user to
- *           send a signal twice to signal the caller (once for the child, and
- *           once for the caller)
+ *   forward_signals: set to true if you want to forward SIGINT, SIGQUIT, and
+ *           SIGHUP to the child process, while it is running.  You likely do
+ *           not need to use this; it is primarily for the logwrapper
+ *           executable itself.
  *   log_target: Specify where to log the output of the child, either LOG_NONE,
  *           LOG_ALOG (for the Android system log), LOG_KLOG (for the kernel
  *           log), or LOG_FILE (and you need to specify a pathname in the
@@ -54,8 +47,6 @@
  *           the specified log until the child has exited.
  *   file_path: if log_target has the LOG_FILE bit set, then this parameter
  *           must be set to the pathname of the file to log to.
- *   unused_opts: currently unused.
- *   unused_opts_len: currently unused.
  *
  * Return value:
  *   0 when logwrap successfully run the child process and captured its status
@@ -71,10 +62,18 @@
 #define LOG_KLOG        2
 #define LOG_FILE        4
 
-// TODO: Remove unused_opts / unused_opts_len in a followup change.
-int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
-        int log_target, bool abbreviated, char *file_path, void* unused_opts,
-        int unused_opts_len);
+int android_fork_execvp_ext2(int argc, char* argv[], int* status, bool forward_signals,
+                             int log_target, bool abbreviated, char* file_path);
+
+// TODO: Actually deprecate this and the below.
+static inline int android_fork_execvp_ext(int argc, char* argv[], int* status, bool ignore_int_quit,
+                                          int log_target, bool abbreviated, char* file_path,
+                                          void* unused_opts, int unused_opts_len) {
+    (void)ignore_int_quit;
+    (void)unused_opts;
+    (void)unused_opts_len;
+    return android_fork_execvp_ext2(argc, argv, status, false, log_target, abbreviated, file_path);
+}
 
 /* Similar to above, except abbreviated logging is not available, and if logwrap
  * is true, logging is to the Android system log, and if false, there is no
@@ -89,5 +88,3 @@
 }
 
 __END_DECLS
-
-#endif /* __LIBS_LOGWRAP_H */
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 8621993..0314f37 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -36,6 +36,11 @@
 #define MIN(a,b) (((a)<(b))?(a):(b))
 
 static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER;
+// Protected by fd_mutex.  These signals must be blocked while modifying as well.
+static pid_t child_pid;
+static struct sigaction old_int;
+static struct sigaction old_quit;
+static struct sigaction old_hup;
 
 #define ERROR(fmt, args...)                                                   \
 do {                                                                          \
@@ -289,8 +294,47 @@
     }
 }
 
-static int parent(const char *tag, int parent_read, pid_t pid,
-        int *chld_sts, int log_target, bool abbreviated, char *file_path) {
+static void signal_handler(int signal_num);
+
+static void block_signals(sigset_t* oldset) {
+    sigset_t blockset;
+
+    sigemptyset(&blockset);
+    sigaddset(&blockset, SIGINT);
+    sigaddset(&blockset, SIGQUIT);
+    sigaddset(&blockset, SIGHUP);
+    pthread_sigmask(SIG_BLOCK, &blockset, oldset);
+}
+
+static void unblock_signals(sigset_t* oldset) {
+    pthread_sigmask(SIG_SETMASK, oldset, NULL);
+}
+
+static void setup_signal_handlers(pid_t pid) {
+    struct sigaction handler = {.sa_handler = signal_handler};
+
+    child_pid = pid;
+    sigaction(SIGINT, &handler, &old_int);
+    sigaction(SIGQUIT, &handler, &old_quit);
+    sigaction(SIGHUP, &handler, &old_hup);
+}
+
+static void restore_signal_handlers() {
+    sigaction(SIGINT, &old_int, NULL);
+    sigaction(SIGQUIT, &old_quit, NULL);
+    sigaction(SIGHUP, &old_hup, NULL);
+    child_pid = 0;
+}
+
+static void signal_handler(int signal_num) {
+    if (child_pid == 0 || kill(child_pid, signal_num) != 0) {
+        restore_signal_handlers();
+        raise(signal_num);
+    }
+}
+
+static int parent(const char* tag, int parent_read, pid_t pid, int* chld_sts, int log_target,
+                  bool abbreviated, char* file_path, bool forward_signals) {
     int status = 0;
     char buffer[4096];
     struct pollfd poll_fds[] = {
@@ -308,6 +352,11 @@
     int b = 0;  // end index of unprocessed data
     int sz;
     bool found_child = false;
+    // There is a very small chance that opening child_ptty in the child will fail, but in this case
+    // POLLHUP will not be generated below.  Therefore, we use a 1 second timeout for poll() until
+    // we receive a message from child_ptty.  If this times out, we call waitpid() with WNOHANG to
+    // check the status of the child process and exit appropriately if it has terminated.
+    bool received_messages = false;
     char tmpbuf[256];
 
     log_info.btag = basename(tag);
@@ -347,13 +396,15 @@
     log_info.abbreviated = abbreviated;
 
     while (!found_child) {
-        if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) {
+        int timeout = received_messages ? -1 : 1000;
+        if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), timeout)) < 0) {
             ERROR("poll failed\n");
             rc = -1;
             goto err_poll;
         }
 
         if (poll_fds[0].revents & POLLIN) {
+            received_messages = true;
             sz = TEMP_FAILURE_RETRY(
                 read(parent_read, &buffer[b], sizeof(buffer) - 1 - b));
 
@@ -396,10 +447,20 @@
             }
         }
 
-        if (poll_fds[0].revents & POLLHUP) {
+        if (!received_messages || (poll_fds[0].revents & POLLHUP)) {
             int ret;
+            sigset_t oldset;
 
-            ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+            if (forward_signals) {
+                // Our signal handlers forward these signals to 'child_pid', but waitpid() may reap
+                // the child, so we must block these signals until we either 1) conclude that the
+                // child is still running or 2) determine the child has been reaped and we have
+                // reset the signals to their original disposition.
+                block_signals(&oldset);
+            }
+
+            int flags = (poll_fds[0].revents & POLLHUP) ? 0 : WNOHANG;
+            ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, flags));
             if (ret < 0) {
                 rc = errno;
                 ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
@@ -408,6 +469,13 @@
             if (ret > 0) {
                 found_child = true;
             }
+
+            if (forward_signals) {
+                if (found_child) {
+                    restore_signal_handlers();
+                }
+                unblock_signals(&oldset);
+            }
         }
     }
 
@@ -472,21 +540,14 @@
     }
 }
 
-int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
-        int log_target, bool abbreviated, char *file_path,
-        void *unused_opts, int unused_opts_len) {
+int android_fork_execvp_ext2(int argc, char* argv[], int* status, bool forward_signals,
+                             int log_target, bool abbreviated, char* file_path) {
     pid_t pid;
     int parent_ptty;
-    int child_ptty;
-    struct sigaction intact;
-    struct sigaction quitact;
     sigset_t blockset;
     sigset_t oldset;
     int rc = 0;
 
-    LOG_ALWAYS_FATAL_IF(unused_opts != NULL);
-    LOG_ALWAYS_FATAL_IF(unused_opts_len != 0);
-
     rc = pthread_mutex_lock(&fd_mutex);
     if (rc) {
         ERROR("failed to lock signal_fd mutex\n");
@@ -494,7 +555,7 @@
     }
 
     /* Use ptty instead of socketpair so that STDOUT is not buffered */
-    parent_ptty = TEMP_FAILURE_RETRY(open("/dev/ptmx", O_RDWR));
+    parent_ptty = TEMP_FAILURE_RETRY(posix_openpt(O_RDWR | O_CLOEXEC));
     if (parent_ptty < 0) {
         ERROR("Cannot create parent ptty\n");
         rc = -1;
@@ -509,27 +570,26 @@
         goto err_ptty;
     }
 
-    child_ptty = TEMP_FAILURE_RETRY(open(child_devname, O_RDWR));
-    if (child_ptty < 0) {
-        ERROR("Cannot open child_ptty\n");
-        rc = -1;
-        goto err_child_ptty;
+    if (forward_signals) {
+        // Block these signals until we have the child pid and our signal handlers set up.
+        block_signals(&oldset);
     }
 
-    sigemptyset(&blockset);
-    sigaddset(&blockset, SIGINT);
-    sigaddset(&blockset, SIGQUIT);
-    pthread_sigmask(SIG_BLOCK, &blockset, &oldset);
-
     pid = fork();
     if (pid < 0) {
-        close(child_ptty);
         ERROR("Failed to fork\n");
         rc = -1;
         goto err_fork;
     } else if (pid == 0) {
         pthread_mutex_unlock(&fd_mutex);
-        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+        unblock_signals(&oldset);
+
+        setsid();
+
+        int child_ptty = TEMP_FAILURE_RETRY(open(child_devname, O_RDWR | O_CLOEXEC));
+        if (child_ptty < 0) {
+            FATAL_CHILD("Cannot open child_ptty: %s\n", strerror(errno));
+        }
         close(parent_ptty);
 
         dup2(child_ptty, 1);
@@ -538,27 +598,23 @@
 
         child(argc, argv);
     } else {
-        close(child_ptty);
-        if (ignore_int_quit) {
-            struct sigaction ignact;
-
-            memset(&ignact, 0, sizeof(ignact));
-            ignact.sa_handler = SIG_IGN;
-            sigaction(SIGINT, &ignact, &intact);
-            sigaction(SIGQUIT, &ignact, &quitact);
+        if (forward_signals) {
+            setup_signal_handlers(pid);
+            unblock_signals(&oldset);
         }
 
-        rc = parent(argv[0], parent_ptty, pid, status, log_target,
-                    abbreviated, file_path);
+        rc = parent(argv[0], parent_ptty, pid, status, log_target, abbreviated, file_path,
+                    forward_signals);
+
+        if (forward_signals) {
+            restore_signal_handlers();
+        }
     }
 
-    if (ignore_int_quit) {
-        sigaction(SIGINT, &intact, NULL);
-        sigaction(SIGQUIT, &quitact, NULL);
-    }
 err_fork:
-    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
-err_child_ptty:
+    if (forward_signals) {
+        unblock_signals(&oldset);
+    }
 err_ptty:
     close(parent_ptty);
 err_open:
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index 33454c6..e786609 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -79,8 +79,7 @@
         usage();
     }
 
-    rc = android_fork_execvp_ext(argc, &argv[0], &status, true,
-                                 log_target, abbreviated, NULL, NULL, 0);
+    rc = android_fork_execvp_ext2(argc, &argv[0], &status, true, log_target, abbreviated, NULL);
     if (!rc) {
         if (WIFEXITED(status))
             rc = WEXITSTATUS(status);
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index df1d929..7097a12 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -334,6 +334,15 @@
 LOCAL_MODULE_STEM := ld.config.txt
 include $(BUILD_PREBUILT)
 
+# Returns the unique installed basenames of a module, or module.so if there are
+# none.  The guess is to handle cases like libc, where the module itself is
+# marked uninstallable but a symlink is installed with the name libc.so.
+# $(1): list of libraries
+# $(2): suffix to to add to each library (not used for guess)
+define module-installed-files-or-guess
+$(foreach lib,$(1),$(or $(strip $(sort $(notdir $(call module-installed-files,$(lib)$(2))))),$(lib).so))
+endef
+
 #######################################
 # llndk.libraries.txt
 include $(CLEAR_VARS)
@@ -342,13 +351,13 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_LLNDK_LIBRARIES := $(LLNDK_LIBRARIES)
+$(LOCAL_BUILT_MODULE): PRIVATE_LLNDK_LIBRARIES := $(call module-installed-files-or-guess,$(LLNDK_LIBRARIES),)
 $(LOCAL_BUILT_MODULE):
 	@echo "Generate: $@"
 	@mkdir -p $(dir $@)
 	$(hide) echo -n > $@
 	$(hide) $(foreach lib,$(PRIVATE_LLNDK_LIBRARIES), \
-		echo $(lib).so >> $@;)
+		echo $(lib) >> $@;)
 
 #######################################
 # vndksp.libraries.txt
@@ -358,13 +367,13 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SAMEPROCESS_LIBRARIES := $(VNDK_SAMEPROCESS_LIBRARIES)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SAMEPROCESS_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_SAMEPROCESS_LIBRARIES),.vendor)
 $(LOCAL_BUILT_MODULE):
 	@echo "Generate: $@"
 	@mkdir -p $(dir $@)
 	$(hide) echo -n > $@
 	$(hide) $(foreach lib,$(PRIVATE_VNDK_SAMEPROCESS_LIBRARIES), \
-		echo $(lib).so >> $@;)
+		echo $(lib) >> $@;)
 
 #######################################
 # vndkcore.libraries.txt
@@ -374,13 +383,13 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_CORE_LIBRARIES := $(VNDK_CORE_LIBRARIES)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_CORE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_CORE_LIBRARIES),.vendor)
 $(LOCAL_BUILT_MODULE):
 	@echo "Generate: $@"
 	@mkdir -p $(dir $@)
 	$(hide) echo -n > $@
 	$(hide) $(foreach lib,$(PRIVATE_VNDK_CORE_LIBRARIES), \
-		echo $(lib).so >> $@;)
+		echo $(lib) >> $@;)
 
 #######################################
 # vndkprivate.libraries.txt
@@ -390,13 +399,13 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_PRIVATE_LIBRARIES := $(VNDK_PRIVATE_LIBRARIES)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_PRIVATE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_PRIVATE_LIBRARIES),.vendor)
 $(LOCAL_BUILT_MODULE):
 	@echo "Generate: $@"
 	@mkdir -p $(dir $@)
 	$(hide) echo -n > $@
 	$(hide) $(foreach lib,$(PRIVATE_VNDK_PRIVATE_LIBRARIES), \
-		echo $(lib).so >> $@;)
+		echo $(lib) >> $@;)
 
 #######################################
 # sanitizer.libraries.txt
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 451f5ad..9c2cdf2 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -33,7 +33,7 @@
 /dev/urandom              0666   root       root
 # Make HW RNG readable by group system to let EntropyMixer read it.
 /dev/hw_random            0440   root       system
-/dev/ashmem               0666   root       root
+/dev/ashmem*              0666   root       root
 /dev/binder               0666   root       root
 /dev/hwbinder             0666   root       root
 /dev/vndbinder            0666   root       root