Exclusive exec() path, format after partition.

Sadly setexeccon() is process global, so we need to carefully ensure
that all exec() are mutually exclusive to avoid transitioning into
unwanted domains.  Also, because we have several threads floating
around, we need to guard all our FDs with O_CLOEXEC.

Format all newly created volumes immediately after partitioning,
but silence all events emitted from those volumes to prevent the
framework from getting all excited.  Unify all notify events under a
single codepath to make them easy to silence.

Sent SIGINT before escalating to SIGTERM when unmounting.

Bug: 19993667
Change-Id: Idc6c806afc7919a004a93e2240b42884f6b52d6b
diff --git a/Devmapper.cpp b/Devmapper.cpp
index 703902f..703eade 100644
--- a/Devmapper.cpp
+++ b/Devmapper.cpp
@@ -55,7 +55,7 @@
     }
 
     int fd;
-    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
+    if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
         SLOGE("Error opening devmapper (%s)", strerror(errno));
         free(buffer);
         free(buffer2);
@@ -138,7 +138,7 @@
     }
 
     int fd;
-    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
+    if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
         SLOGE("Error opening devmapper (%s)", strerror(errno));
         free(buffer);
         return -1;
@@ -172,7 +172,7 @@
     }
 
     int fd;
-    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
+    if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
         SLOGE("Error opening devmapper (%s)", strerror(errno));
         free(buffer);
         return -1;
@@ -269,7 +269,7 @@
     }
 
     int fd;
-    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
+    if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
         SLOGE("Error opening devmapper (%s)", strerror(errno));
         free(buffer);
         return -1;
diff --git a/Disk.cpp b/Disk.cpp
index 3bf9333..794e1dd 100644
--- a/Disk.cpp
+++ b/Disk.cpp
@@ -53,7 +53,7 @@
 
 static const char* kGptBasicData = "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7";
 static const char* kGptAndroidMeta = "19A710A2-B3CA-11E4-B026-10604B889DCF";
-static const char* kGptAndroidExt = "193D1EA4-B3CA-11E4-B075-10604B889DCF";
+static const char* kGptAndroidExpand = "193D1EA4-B3CA-11E4-B075-10604B889DCF";
 
 static const char* kKeyPath = "/data/misc/vold";
 
@@ -63,8 +63,10 @@
     kGpt,
 };
 
-Disk::Disk(const std::string& eventPath, dev_t device, const std::string& nickname, int flags) :
-        mDevice(device), mSize(-1), mNickname(nickname), mFlags(flags), mCreated(false) {
+Disk::Disk(const std::string& eventPath, dev_t device,
+        const std::string& nickname, int flags) :
+        mDevice(device), mSize(-1), mNickname(nickname), mFlags(flags), mCreated(
+                false), mJustPartitioned(false) {
     mId = StringPrintf("disk:%u,%u", major(device), minor(device));
     mEventPath = eventPath;
     mSysPath = StringPrintf("/sys/%s", eventPath.c_str());
@@ -93,9 +95,7 @@
 status_t Disk::create() {
     CHECK(!mCreated);
     mCreated = true;
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::DiskCreated,
-            StringPrintf("%s %d", getId().c_str(), mFlags).c_str(), false);
+    notifyEvent(ResponseCode::DiskCreated, StringPrintf("%d", mFlags));
     readMetadata();
     readPartitions();
     return OK;
@@ -105,23 +105,28 @@
     CHECK(mCreated);
     destroyAllVolumes();
     mCreated = false;
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::DiskDestroyed, getId().c_str(), false);
+    notifyEvent(ResponseCode::DiskDestroyed);
     return OK;
 }
 
 static std::string BuildKeyPath(const std::string& partGuid) {
-    return StringPrintf("%s/ext_%s.key", kKeyPath, partGuid.c_str());
+    return StringPrintf("%s/expand_%s.key", kKeyPath, partGuid.c_str());
 }
 
 void Disk::createPublicVolume(dev_t device) {
     auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device));
-    vol->create();
+    if (mJustPartitioned) {
+        LOG(DEBUG) << "Device just partitioned; silently formatting";
+        vol->setSilent(true);
+        vol->create();
+        vol->format();
+        vol->destroy();
+        vol->setSilent(false);
+    }
 
     mVolumes.push_back(vol);
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::DiskVolumeCreated,
-            StringPrintf("%s %s", getId().c_str(), vol->getId().c_str()).c_str(), false);
+    vol->create();
+    notifyEvent(ResponseCode::DiskVolumeCreated, vol->getId());
 }
 
 void Disk::createPrivateVolume(dev_t device, const std::string& partGuid) {
@@ -142,12 +147,18 @@
     LOG(DEBUG) << "Found key for GUID " << normalizedGuid;
 
     auto vol = std::shared_ptr<VolumeBase>(new PrivateVolume(device, keyRaw));
-    vol->create();
+    if (mJustPartitioned) {
+        LOG(DEBUG) << "Device just partitioned; silently formatting";
+        vol->setSilent(true);
+        vol->create();
+        vol->format();
+        vol->destroy();
+        vol->setSilent(false);
+    }
 
     mVolumes.push_back(vol);
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::DiskVolumeCreated,
-            StringPrintf("%s %s", getId().c_str(), vol->getId().c_str()).c_str(), false);
+    vol->create();
+    notifyEvent(ResponseCode::DiskVolumeCreated, vol->getId());
 }
 
 void Disk::destroyAllVolumes() {
@@ -161,7 +172,7 @@
     mSize = -1;
     mLabel.clear();
 
-    int fd = open(mDevPath.c_str(), O_RDONLY);
+    int fd = open(mDevPath.c_str(), O_RDONLY | O_CLOEXEC);
     if (fd != -1) {
         if (ioctl(fd, BLKGETSIZE64, &mSize)) {
             mSize = -1;
@@ -205,13 +216,8 @@
     }
     }
 
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::DiskSizeChanged,
-            StringPrintf("%s %" PRId64, getId().c_str(), mSize).c_str(), false);
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::DiskLabelChanged,
-            StringPrintf("%s %s", getId().c_str(), mLabel.c_str()).c_str(), false);
-
+    notifyEvent(ResponseCode::DiskSizeChanged, StringPrintf("%" PRId64, mSize));
+    notifyEvent(ResponseCode::DiskLabelChanged, mLabel);
     return OK;
 }
 
@@ -224,22 +230,25 @@
     destroyAllVolumes();
 
     // Parse partition table
-    std::string path(kSgdiskPath);
-    path += " --android-dump ";
-    path += mDevPath;
-    FILE* fp = popen(path.c_str(), "r");
-    if (!fp) {
-        PLOG(ERROR) << "Failed to run " << path;
-        return -errno;
+
+    std::vector<std::string> cmd;
+    cmd.push_back(kSgdiskPath);
+    cmd.push_back("--android-dump");
+    cmd.push_back(mDevPath);
+
+    std::vector<std::string> output;
+    status_t res = ForkExecvp(cmd, output);
+    if (res != OK) {
+        LOG(WARNING) << "sgdisk failed to scan " << mDevPath;
+        mJustPartitioned = false;
+        return res;
     }
 
-    char line[1024];
     Table table = Table::kUnknown;
     bool foundParts = false;
-    while (fgets(line, sizeof(line), fp) != nullptr) {
-        LOG(DEBUG) << "sgdisk: " << line;
-
-        char* token = strtok(line, kSgdiskToken);
+    for (auto line : output) {
+        char* cline = (char*) line.c_str();
+        char* token = strtok(cline, kSgdiskToken);
         if (token == nullptr) continue;
 
         if (!strcmp(token, "DISK")) {
@@ -276,7 +285,7 @@
 
                 if (!strcasecmp(typeGuid, kGptBasicData)) {
                     createPublicVolume(partDevice);
-                } else if (!strcasecmp(typeGuid, kGptAndroidExt)) {
+                } else if (!strcasecmp(typeGuid, kGptAndroidExpand)) {
                     createPrivateVolume(partDevice, partGuid);
                 }
             }
@@ -289,7 +298,7 @@
         createPublicVolume(mDevice);
     }
 
-    pclose(fp);
+    mJustPartitioned = false;
     return OK;
 }
 
@@ -303,6 +312,7 @@
 status_t Disk::partitionPublic() {
     // TODO: improve this code
     destroyAllVolumes();
+    mJustPartitioned = true;
 
     struct disk_info dinfo;
     memset(&dinfo, 0, sizeof(dinfo));
@@ -346,9 +356,10 @@
 }
 
 status_t Disk::partitionMixed(int8_t ratio) {
-    int status = 0;
+    int res;
 
     destroyAllVolumes();
+    mJustPartitioned = true;
 
     // First nuke any existing partition table
     std::vector<std::string> cmd;
@@ -356,9 +367,9 @@
     cmd.push_back("--zap-all");
     cmd.push_back(mDevPath);
 
-    if (ForkExecvp(cmd, &status, false, true)) {
-        LOG(ERROR) << "Failed to zap; status " << status;
-        return -EIO;
+    if ((res = ForkExecvp(cmd)) != 0) {
+        LOG(ERROR) << "Failed to zap; status " << res;
+        return res;
     }
 
     // We've had some success above, so generate both the private partition
@@ -408,20 +419,30 @@
 
     // Define a single private partition filling the rest of disk.
     cmd.push_back("--new=0:0:-0");
-    cmd.push_back(StringPrintf("--typecode=0:%s", kGptAndroidExt));
+    cmd.push_back(StringPrintf("--typecode=0:%s", kGptAndroidExpand));
     cmd.push_back(StringPrintf("--partition-guid=0:%s", partGuid.c_str()));
-    cmd.push_back("--change-name=0:android_ext");
+    cmd.push_back("--change-name=0:android_expand");
 
     cmd.push_back(mDevPath);
 
-    if (ForkExecvp(cmd, &status, false, true)) {
-        LOG(ERROR) << "Failed to partition; status " << status;
-        return -EIO;
+    if ((res = ForkExecvp(cmd)) != 0) {
+        LOG(ERROR) << "Failed to partition; status " << res;
+        return res;
     }
 
     return OK;
 }
 
+void Disk::notifyEvent(int event) {
+    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
+            getId().c_str(), false);
+}
+
+void Disk::notifyEvent(int event, const std::string& value) {
+    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
+            StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false);
+}
+
 int Disk::getMaxMinors() {
     // Figure out maximum partition devices supported
     switch (major(mDevice)) {
diff --git a/Disk.h b/Disk.h
index 82ef1f5..a8461fb 100644
--- a/Disk.h
+++ b/Disk.h
@@ -74,6 +74,9 @@
     status_t partitionPrivate();
     status_t partitionMixed(int8_t ratio);
 
+    void notifyEvent(int msg);
+    void notifyEvent(int msg, const std::string& value);
+
 private:
     /* ID that uniquely references this disk */
     std::string mId;
@@ -97,6 +100,8 @@
     int mFlags;
     /* Flag indicating object is created */
     bool mCreated;
+    /* Flag that we just partitioned and should format all volumes */
+    bool mJustPartitioned;
 
     void createPublicVolume(dev_t device);
     void createPrivateVolume(dev_t device, const std::string& partGuid);
diff --git a/Ext4.cpp b/Ext4.cpp
index 7316234..a208eb5 100644
--- a/Ext4.cpp
+++ b/Ext4.cpp
@@ -48,14 +48,11 @@
 #include "Utils.h"
 #include "VoldUtil.h"
 
-#define RESIZE2FS_PATH "/system/bin/resize2fs"
-
 using android::base::StringPrintf;
 
+static const char* kResizefsPath = "/system/bin/resize2fs";
 static const char* kMkfsPath = "/system/bin/make_ext4fs";
-
 static const char* kFsckPath = "/system/bin/e2fsck";
-static const char* kFsckLogFile = "/dev/fscklogs/log";
 
 int Ext4::check(const char *fsPath, const char *mountPoint) {
     // The following is shamelessly borrowed from fs_mgr.c, so it should be
@@ -68,11 +65,6 @@
     int ret;
     long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
     char *tmpmnt_opts = (char*) "nomblk_io_submit,errors=remount-ro";
-    char *e2fsck_argv[] = {
-        (char*) kFsckPath,
-        (char*) "-y",
-        blk_device
-    };
 
     /*
      * First try to mount and unmount the filesystem.  We do this because
@@ -112,23 +104,13 @@
     } else {
         ALOGD("Running %s on %s\n", kFsckPath, blk_device);
 
-        // Ext4 devices are currently always trusted
-        if (setexeccon(android::vold::sFsckContext)) {
-            LOG(ERROR) << "Failed to setexeccon()";
-            errno = EPERM;
-            return -1;
-        }
-        ret = android_fork_execvp(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
-                                    &status, false, true);
-        if (setexeccon(NULL)) {
-            abort();
-        }
+        std::vector<std::string> cmd;
+        cmd.push_back(kFsckPath);
+        cmd.push_back("-y");
+        cmd.push_back(blk_device);
 
-        if (ret < 0) {
-            /* No need to check for error in fork, we can't really handle it now */
-            ALOGW("Failed trying to run %s\n", kFsckPath);
-            return -1;
-        }
+        // Ext4 devices are currently always trusted
+        return android::vold::ForkExecvp(cmd, android::vold::sFsckContext);
     }
 
     return 0;
@@ -157,51 +139,16 @@
 }
 
 int Ext4::resize(const char *fspath, unsigned int numSectors) {
-    const char *args[4];
-    char* size_str;
-    int rc;
-    int status;
+    std::vector<std::string> cmd;
+    cmd.push_back(kResizefsPath);
+    cmd.push_back("-f");
+    cmd.push_back(fspath);
+    cmd.push_back(StringPrintf("%u", numSectors));
 
-    args[0] = RESIZE2FS_PATH;
-    args[1] = "-f";
-    args[2] = fspath;
-    if (asprintf(&size_str, "%ds", numSectors) < 0)
-    {
-      SLOGE("Filesystem (ext4) resize failed to set size");
-      return -1;
-    }
-    args[3] = size_str;
-    rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false,
-            true);
-    free(size_str);
-    if (rc != 0) {
-        SLOGE("Filesystem (ext4) resize failed due to logwrap error");
-        errno = EIO;
-        return -1;
-    }
-
-    if (!WIFEXITED(status)) {
-        SLOGE("Filesystem (ext4) resize did not exit properly");
-        errno = EIO;
-        return -1;
-    }
-
-    status = WEXITSTATUS(status);
-
-    if (status == 0) {
-        SLOGI("Filesystem (ext4) resized OK");
-        return 0;
-    } else {
-        SLOGE("Resize (ext4) failed (unknown exit code %d)", status);
-        errno = EIO;
-        return -1;
-    }
-    return 0;
+    return android::vold::ForkExecvp(cmd);
 }
 
 int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountpoint) {
-    int status;
-
     std::vector<std::string> cmd;
     cmd.push_back(kMkfsPath);
     cmd.push_back("-J");
@@ -214,30 +161,9 @@
         cmd.push_back(StringPrintf("%u", numSectors * 512));
     }
 
+    // Always generate a real UUID
+    cmd.push_back("-u");
     cmd.push_back(fsPath);
 
-    int rc = android::vold::ForkExecvp(cmd, &status, false, true);
-    if (rc != 0) {
-        SLOGE("Filesystem (ext4) format failed due to logwrap error");
-        errno = EIO;
-        return -1;
-    }
-
-    if (!WIFEXITED(status)) {
-        SLOGE("Filesystem (ext4) format did not exit properly");
-        errno = EIO;
-        return -1;
-    }
-
-    status = WEXITSTATUS(status);
-
-    if (status == 0) {
-        SLOGI("Filesystem (ext4) formatted OK");
-        return 0;
-    } else {
-        SLOGE("Format (ext4) failed (unknown exit code %d)", status);
-        errno = EIO;
-        return -1;
-    }
-    return 0;
+    return android::vold::ForkExecvp(cmd);
 }
diff --git a/Fat.cpp b/Fat.cpp
index 29b8598..873088d 100644
--- a/Fat.cpp
+++ b/Fat.cpp
@@ -38,6 +38,7 @@
 #define LOG_TAG "Vold"
 
 #include <base/logging.h>
+#include <base/stringprintf.h>
 #include <cutils/log.h>
 #include <cutils/properties.h>
 #include <selinux/selinux.h>
@@ -48,12 +49,13 @@
 #include "Utils.h"
 #include "VoldUtil.h"
 
-static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos";
-static char MKDOSFS_PATH[] = "/system/bin/newfs_msdos";
-extern "C" int mount(const char *, const char *, const char *, unsigned long, const void *);
+using android::base::StringPrintf;
+
+static const char* kMkfsPath = "/system/bin/newfs_msdos";
+static const char* kFsckPath = "/system/bin/fsck_msdos";
 
 int Fat::check(const char *fsPath) {
-    if (access(FSCK_MSDOS_PATH, X_OK)) {
+    if (access(kFsckPath, X_OK)) {
         SLOGW("Skipping fs checks\n");
         return 0;
     }
@@ -61,40 +63,22 @@
     int pass = 1;
     int rc = 0;
     do {
-        const char *args[4];
-        int status;
-        args[0] = FSCK_MSDOS_PATH;
-        args[1] = "-p";
-        args[2] = "-f";
-        args[3] = fsPath;
+        std::vector<std::string> cmd;
+        cmd.push_back(kFsckPath);
+        cmd.push_back("-p");
+        cmd.push_back("-f");
+        cmd.push_back(fsPath);
 
         // Fat devices are currently always untrusted
-        if (setexeccon(android::vold::sFsckUntrustedContext)) {
-            LOG(ERROR) << "Failed to setexeccon()";
-            errno = EPERM;
-            return -1;
-        }
-        rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status,
-                false, true);
-        if (setexeccon(NULL)) {
-            abort();
-        }
+        rc = android::vold::ForkExecvp(cmd, android::vold::sFsckUntrustedContext);
 
-        if (rc != 0) {
+        if (rc < 0) {
             SLOGE("Filesystem check failed due to logwrap error");
             errno = EIO;
             return -1;
         }
 
-        if (!WIFEXITED(status)) {
-            SLOGE("Filesystem check did not exit properly");
-            errno = EIO;
-            return -1;
-        }
-
-        status = WEXITSTATUS(status);
-
-        switch(status) {
+        switch(rc) {
         case 0:
             SLOGI("Filesystem check completed OK");
             return 0;
@@ -115,7 +99,7 @@
             return -1;
 
         default:
-            SLOGE("Filesystem check failed (unknown exit code %d)", status);
+            SLOGE("Filesystem check failed (unknown exit code %d)", rc);
             errno = EIO;
             return -1;
         }
@@ -182,57 +166,39 @@
 }
 
 int Fat::format(const char *fsPath, unsigned int numSectors, bool wipe) {
-    const char *args[11];
-    int rc;
-    int status;
-
     if (wipe) {
         Fat::wipe(fsPath, numSectors);
     }
 
-    args[0] = MKDOSFS_PATH;
-    args[1] = "-F";
-    args[2] = "32";
-    args[3] = "-O";
-    args[4] = "android";
-    args[5] = "-c";
-    args[6] = "64";
-    args[7] = "-A";
+    std::vector<std::string> cmd;
+    cmd.push_back(kMkfsPath);
+    cmd.push_back("-F");
+    cmd.push_back("32");
+    cmd.push_back("-O");
+    cmd.push_back("android");
+    cmd.push_back("-c");
+    cmd.push_back("64");
+    cmd.push_back("-A");
 
     if (numSectors) {
-        char tmp[32];
-        snprintf(tmp, sizeof(tmp), "%u", numSectors);
-        const char *size = tmp;
-        args[8] = "-s";
-        args[9] = size;
-        args[10] = fsPath;
-        rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status,
-                false, true);
-    } else {
-        args[8] = fsPath;
-        rc = android_fork_execvp(9, (char **)args, &status, false,
-                true);
+        cmd.push_back("-s");
+        cmd.push_back(StringPrintf("%u", numSectors));
     }
 
-    if (rc != 0) {
+    cmd.push_back(fsPath);
+
+    int rc = android::vold::ForkExecvp(cmd);
+    if (rc < 0) {
         SLOGE("Filesystem format failed due to logwrap error");
         errno = EIO;
         return -1;
     }
 
-    if (!WIFEXITED(status)) {
-        SLOGE("Filesystem format did not exit properly");
-        errno = EIO;
-        return -1;
-    }
-
-    status = WEXITSTATUS(status);
-
-    if (status == 0) {
+    if (rc == 0) {
         SLOGI("Filesystem formatted OK");
         return 0;
     } else {
-        SLOGE("Format failed (unknown exit code %d)", status);
+        SLOGE("Format failed (unknown exit code %d)", rc);
         errno = EIO;
         return -1;
     }
@@ -242,7 +208,7 @@
 void Fat::wipe(const char *fsPath, unsigned int numSectors) {
     unsigned long long range[2];
 
-    int fd = open(fsPath, O_RDWR);
+    int fd = open(fsPath, O_RDWR | O_CLOEXEC);
     if (fd == -1) {
         SLOGE("Fat wipe failed to open device %s", fsPath);
         return;
diff --git a/Loop.cpp b/Loop.cpp
index b1e9f6a..8872d7a 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -49,7 +49,7 @@
 
         sprintf(filename, "/dev/block/loop%d", i);
 
-        if ((fd = open(filename, O_RDWR)) < 0) {
+        if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
             if (errno != ENOENT) {
                 SLOGE("Unable to open %s (%s)", filename, strerror(errno));
             } else {
@@ -93,7 +93,7 @@
 
         sprintf(filename, "/dev/block/loop%d", i);
 
-        if ((fd = open(filename, O_RDWR)) < 0) {
+        if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
             if (errno != ENOENT) {
                 SLOGE("Unable to open %s (%s)", filename, strerror(errno));
             } else {
@@ -168,7 +168,7 @@
             setfscreatecon(NULL);
         }
 
-        if ((fd = open(filename, O_RDWR)) < 0) {
+        if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
             SLOGE("Unable to open %s (%s)", filename, strerror(errno));
             return -1;
         }
@@ -196,7 +196,7 @@
 
     int file_fd;
 
-    if ((file_fd = open(loopFile, O_RDWR)) < 0) {
+    if ((file_fd = open(loopFile, O_RDWR | O_CLOEXEC)) < 0) {
         SLOGE("Unable to open %s (%s)", loopFile, strerror(errno));
         close(fd);
         return -1;
@@ -231,7 +231,7 @@
 int Loop::destroyByDevice(const char *loopDevice) {
     int device_fd;
 
-    device_fd = open(loopDevice, O_RDONLY);
+    device_fd = open(loopDevice, O_RDONLY | O_CLOEXEC);
     if (device_fd < 0) {
         SLOGE("Failed to open loop (%d)", errno);
         return -1;
@@ -272,7 +272,7 @@
 int Loop::resizeImageFile(const char *file, unsigned int numSectors) {
     int fd;
 
-    if ((fd = open(file, O_RDWR)) < 0) {
+    if ((fd = open(file, O_RDWR | O_CLOEXEC)) < 0) {
         SLOGE("Error opening imagefile (%s)", strerror(errno));
         return -1;
     }
@@ -301,7 +301,7 @@
     int fd;
     struct asec_superblock buffer;
 
-    if ((fd = open(loopDevice, O_RDONLY)) < 0) {
+    if ((fd = open(loopDevice, O_RDONLY | O_CLOEXEC)) < 0) {
         SLOGE("Failed to open loopdevice (%s)", strerror(errno));
         destroyByDevice(loopDevice);
         return -1;
diff --git a/PrivateVolume.cpp b/PrivateVolume.cpp
index f652c6b..6ca5480 100644
--- a/PrivateVolume.cpp
+++ b/PrivateVolume.cpp
@@ -50,17 +50,9 @@
 
 status_t PrivateVolume::readMetadata() {
     status_t res = ReadMetadata(mDmDevPath, mFsType, mFsUuid, mFsLabel);
-
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeFsTypeChanged,
-            StringPrintf("%s %s", getId().c_str(), mFsType.c_str()).c_str(), false);
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeFsUuidChanged,
-            StringPrintf("%s %s", getId().c_str(), mFsUuid.c_str()).c_str(), false);
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeFsLabelChanged,
-            StringPrintf("%s %s", getId().c_str(), mFsLabel.c_str()).c_str(), false);
-
+    notifyEvent(ResponseCode::VolumeFsTypeChanged, mFsType);
+    notifyEvent(ResponseCode::VolumeFsUuidChanged, mFsUuid);
+    notifyEvent(ResponseCode::VolumeFsLabelChanged, mFsLabel);
     return res;
 }
 
diff --git a/Process.cpp b/Process.cpp
index f01fa31..a6f0cc6 100644
--- a/Process.cpp
+++ b/Process.cpp
@@ -66,7 +66,7 @@
 void Process::getProcessName(int pid, char *buffer, size_t max) {
     int fd;
     snprintf(buffer, max, "/proc/%d/cmdline", pid);
-    fd = open(buffer, O_RDONLY);
+    fd = open(buffer, O_RDONLY | O_CLOEXEC);
     if (fd < 0) {
         strcpy(buffer, "???");
     } else {
diff --git a/PublicVolume.cpp b/PublicVolume.cpp
index 6192e7a..9a68f50 100644
--- a/PublicVolume.cpp
+++ b/PublicVolume.cpp
@@ -52,17 +52,9 @@
 
 status_t PublicVolume::readMetadata() {
     status_t res = ReadMetadataUntrusted(mDevPath, mFsType, mFsUuid, mFsLabel);
-
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeFsTypeChanged,
-            StringPrintf("%s %s", getId().c_str(), mFsType.c_str()).c_str(), false);
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeFsUuidChanged,
-            StringPrintf("%s %s", getId().c_str(), mFsUuid.c_str()).c_str(), false);
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeFsLabelChanged,
-            StringPrintf("%s %s", getId().c_str(), mFsLabel.c_str()).c_str(), false);
-
+    notifyEvent(ResponseCode::VolumeFsTypeChanged, mFsType);
+    notifyEvent(ResponseCode::VolumeFsUuidChanged, mFsUuid);
+    notifyEvent(ResponseCode::VolumeFsLabelChanged, mFsLabel);
     return res;
 }
 
diff --git a/Utils.cpp b/Utils.cpp
index 1937c28..d23e182 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -24,6 +24,7 @@
 #include <private/android_filesystem_config.h>
 #include <logwrap/logwrap.h>
 
+#include <mutex>
 #include <fcntl.h>
 #include <linux/fs.h>
 #include <stdlib.h>
@@ -41,6 +42,10 @@
 namespace android {
 namespace vold {
 
+/* Since we use setexeccon(), we need to carefully lock around any
+ * code that calls exec() to avoid crossing the streams. */
+static std::mutex sExecLock;
+
 security_context_t sBlkidContext = nullptr;
 security_context_t sBlkidUntrustedContext = nullptr;
 security_context_t sFsckContext = nullptr;
@@ -117,6 +122,14 @@
     PLOG(WARNING) << "Failed to unmount " << path;
 
     sleep(5);
+    Process::killProcessesWithOpenFiles(cpath, SIGINT);
+
+    if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
+        return OK;
+    }
+    PLOG(WARNING) << "Failed to unmount " << path;
+
+    sleep(5);
     Process::killProcessesWithOpenFiles(cpath, SIGTERM);
 
     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
@@ -149,48 +162,40 @@
     fsUuid.clear();
     fsLabel.clear();
 
-    std::string cmd(StringPrintf("%s -c /dev/null %s", kBlkidPath, path.c_str()));
-    if (setexeccon(untrusted ? sBlkidUntrustedContext : sBlkidContext)) {
-        LOG(ERROR) << "Failed to setexeccon()";
-        return -EPERM;
-    }
-    FILE* fp = popen(cmd.c_str(), "r");
-    if (setexeccon(NULL)) {
-        abort();
-    }
-    if (!fp) {
-        PLOG(ERROR) << "Failed to run " << cmd;
-        return -errno;
+    std::vector<std::string> cmd;
+    cmd.push_back(kBlkidPath);
+    cmd.push_back("-c");
+    cmd.push_back("/dev/null");
+    cmd.push_back(path);
+
+    std::vector<std::string> output;
+    status_t res = ForkExecvp(cmd, output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
+    if (res != OK) {
+        LOG(WARNING) << "blkid failed to identify " << path;
+        return res;
     }
 
-    status_t res = OK;
-    char line[1024];
     char value[128];
-    if (fgets(line, sizeof(line), fp) != nullptr) {
-        LOG(DEBUG) << "blkid identified " << path << " as " << line;
-
+    for (auto line : output) {
         // Extract values from blkid output, if defined
-        char* start = strstr(line, "TYPE=");
+        const char* cline = line.c_str();
+        char* start = strstr(cline, "TYPE=");
         if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
             fsType = value;
         }
 
-        start = strstr(line, "UUID=");
+        start = strstr(cline, "UUID=");
         if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
             fsUuid = value;
         }
 
-        start = strstr(line, "LABEL=");
+        start = strstr(cline, "LABEL=");
         if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
             fsLabel = value;
         }
-    } else {
-        LOG(WARNING) << "blkid failed to identify " << path;
-        res = -ENODATA;
     }
 
-    pclose(fp);
-    return res;
+    return OK;
 }
 
 status_t ReadMetadata(const std::string& path, std::string& fsType,
@@ -203,11 +208,14 @@
     return readMetadata(path, fsType, fsUuid, fsLabel, true);
 }
 
-status_t ForkExecvp(const std::vector<std::string>& args, int* status,
-        bool ignore_int_quit, bool logwrap) {
-    int argc = args.size();
+status_t ForkExecvp(const std::vector<std::string>& args) {
+    return ForkExecvp(args, nullptr);
+}
+
+status_t ForkExecvp(const std::vector<std::string>& args, security_context_t context) {
+    size_t argc = args.size();
     char** argv = (char**) calloc(argc, sizeof(char*));
-    for (int i = 0; i < argc; i++) {
+    for (size_t i = 0; i < argc; i++) {
         argv[i] = (char*) args[i].c_str();
         if (i == 0) {
             LOG(VERBOSE) << args[i];
@@ -215,11 +223,73 @@
             LOG(VERBOSE) << "    " << args[i];
         }
     }
-    int res = android_fork_execvp(argc, argv, status, ignore_int_quit, logwrap);
+
+    status_t res = OK;
+    {
+        std::lock_guard<std::mutex> lock(sExecLock);
+        if (setexeccon(context)) {
+            LOG(ERROR) << "Failed to setexeccon";
+            abort();
+        }
+        res = android_fork_execvp(argc, argv, NULL, false, true);
+        if (setexeccon(nullptr)) {
+            LOG(ERROR) << "Failed to setexeccon";
+            abort();
+        }
+    }
     free(argv);
     return res;
 }
 
+status_t ForkExecvp(const std::vector<std::string>& args,
+        std::vector<std::string>& output) {
+    return ForkExecvp(args, output, nullptr);
+}
+
+status_t ForkExecvp(const std::vector<std::string>& args,
+        std::vector<std::string>& output, security_context_t context) {
+    std::string cmd;
+    for (size_t i = 0; i < args.size(); i++) {
+        cmd += args[i] + " ";
+        if (i == 0) {
+            LOG(VERBOSE) << args[i];
+        } else {
+            LOG(VERBOSE) << "    " << args[i];
+        }
+    }
+    output.clear();
+
+    FILE* fp = nullptr;
+    {
+        std::lock_guard<std::mutex> lock(sExecLock);
+        if (setexeccon(context)) {
+            LOG(ERROR) << "Failed to setexeccon";
+            abort();
+        }
+        fp = popen(cmd.c_str(), "r");
+        if (setexeccon(nullptr)) {
+            LOG(ERROR) << "Failed to setexeccon";
+            abort();
+        }
+    }
+
+    if (!fp) {
+        PLOG(ERROR) << "Failed to popen " << cmd;
+        return -errno;
+    }
+    char line[1024];
+    while (fgets(line, sizeof(line), fp) != nullptr) {
+        LOG(VERBOSE) << line;
+        output.push_back(std::string(line));
+    }
+    if (pclose(fp) != 0) {
+        PLOG(ERROR) << "Failed to pclose " << cmd;
+        return -errno;
+    }
+
+    return OK;
+}
+
 status_t ReadRandomBytes(size_t bytes, std::string& out) {
     out.clear();
 
diff --git a/Utils.h b/Utils.h
index a6e1747..7e083f6 100644
--- a/Utils.h
+++ b/Utils.h
@@ -60,8 +60,14 @@
 status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType,
         std::string& fsUuid, std::string& fsLabel);
 
-status_t ForkExecvp(const std::vector<std::string>& args, int* status,
-        bool ignore_int_quit, bool logwrap);
+/* Returns either WEXITSTATUS() status, or a negative errno */
+status_t ForkExecvp(const std::vector<std::string>& args);
+status_t ForkExecvp(const std::vector<std::string>& args, security_context_t context);
+
+status_t ForkExecvp(const std::vector<std::string>& args,
+        std::vector<std::string>& output);
+status_t ForkExecvp(const std::vector<std::string>& args,
+        std::vector<std::string>& output, security_context_t context);
 
 status_t ReadRandomBytes(size_t bytes, std::string& out);
 
diff --git a/VolumeBase.cpp b/VolumeBase.cpp
index 2590ecf..de5b072 100644
--- a/VolumeBase.cpp
+++ b/VolumeBase.cpp
@@ -36,7 +36,8 @@
 namespace vold {
 
 VolumeBase::VolumeBase(Type type) :
-        mType(type), mFlags(0), mUser(-1), mCreated(false), mState(State::kUnmounted) {
+        mType(type), mFlags(0), mUser(-1), mCreated(false), mState(
+                State::kUnmounted), mSilent(false) {
 }
 
 VolumeBase::~VolumeBase() {
@@ -45,10 +46,7 @@
 
 void VolumeBase::setState(State state) {
     mState = state;
-
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeStateChanged,
-            StringPrintf("%s %d", getId().c_str(), mState).c_str(), false);
+    notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState));
 }
 
 status_t VolumeBase::setFlags(int flags) {
@@ -71,6 +69,16 @@
     return OK;
 }
 
+status_t VolumeBase::setSilent(bool silent) {
+    if (mCreated) {
+        LOG(WARNING) << getId() << " silence change requires destroyed";
+        return -EBUSY;
+    }
+
+    mSilent = silent;
+    return OK;
+}
+
 status_t VolumeBase::setId(const std::string& id) {
     if (mCreated) {
         LOG(WARNING) << getId() << " id change requires not created";
@@ -88,12 +96,22 @@
     }
 
     mPath = path;
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumePathChanged,
-            StringPrintf("%s %s", getId().c_str(), mPath.c_str()).c_str(), false);
+    notifyEvent(ResponseCode::VolumePathChanged, mPath);
     return OK;
 }
 
+void VolumeBase::notifyEvent(int event) {
+    if (mSilent) return;
+    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
+            getId().c_str(), false);
+}
+
+void VolumeBase::notifyEvent(int event, const std::string& value) {
+    if (mSilent) return;
+    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
+            StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false);
+}
+
 void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
     mVolumes.push_back(volume);
 }
@@ -116,9 +134,7 @@
 
     mCreated = true;
     status_t res = doCreate();
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeCreated,
-            StringPrintf("%s %d", getId().c_str(), mType).c_str(), false);
+    notifyEvent(ResponseCode::VolumeCreated, StringPrintf("%d", mType));
     return res;
 }
 
@@ -133,8 +149,7 @@
         unmount();
     }
 
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::VolumeDestroyed, getId().c_str(), false);
+    notifyEvent(ResponseCode::VolumeDestroyed);
     status_t res = doDestroy();
     mCreated = false;
     return res;
diff --git a/VolumeBase.h b/VolumeBase.h
index 465fc61..1494c2c 100644
--- a/VolumeBase.h
+++ b/VolumeBase.h
@@ -86,6 +86,7 @@
 
     status_t setFlags(int flags);
     status_t setUser(userid_t user);
+    status_t setSilent(bool silent);
 
     void addVolume(const std::shared_ptr<VolumeBase>& volume);
     void removeVolume(const std::shared_ptr<VolumeBase>& volume);
@@ -110,6 +111,9 @@
     status_t setId(const std::string& id);
     status_t setPath(const std::string& path);
 
+    void notifyEvent(int msg);
+    void notifyEvent(int msg, const std::string& value);
+
 private:
     /* ID that uniquely references volume while alive */
     std::string mId;
@@ -125,6 +129,8 @@
     State mState;
     /* Path to mounted volume */
     std::string mPath;
+    /* Flag indicating that volume should emit no events */
+    bool mSilent;
 
     /* Volumes stacked on top of this volume */
     std::list<std::shared_ptr<VolumeBase>> mVolumes;
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index b61bafb..5b7ce22 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -95,7 +95,7 @@
 
 /* writes superblock at end of file or device given by name */
 static int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) {
-    int sbfd = open(name, O_RDWR);
+    int sbfd = open(name, O_RDWR | O_CLOEXEC);
     if (sbfd < 0) {
         SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno));
         return -1;
@@ -726,7 +726,7 @@
         }
 
         if (usingExt4) {
-            int dirfd = open(mountPoint, O_DIRECTORY);
+            int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
             if (dirfd >= 0) {
                 if (fchown(dirfd, ownerUid, AID_SYSTEM)
                         || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) {
@@ -775,7 +775,7 @@
     int fd;
     unsigned int oldNumSec = 0;
 
-    if ((fd = open(asecFileName, O_RDONLY)) < 0) {
+    if ((fd = open(asecFileName, O_RDONLY | O_CLOEXEC)) < 0) {
         SLOGE("Failed to open ASEC file (%s)", strerror(errno));
         return -1;
     }
@@ -1021,7 +1021,7 @@
              */
             const bool privateFile = !strcmp(ftsent->fts_name, filename);
 
-            int fd = open(ftsent->fts_accpath, O_NOFOLLOW);
+            int fd = open(ftsent->fts_accpath, O_NOFOLLOW | O_CLOEXEC);
             if (fd < 0) {
                 SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno));
                 result = -1;
@@ -1046,7 +1046,7 @@
         fts_close(fts);
 
         // Finally make the directory readable by everyone.
-        int dirfd = open(mountPoint, O_DIRECTORY);
+        int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
         if (dirfd < 0 || fchmod(dirfd, 0755)) {
             SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno));
             result |= -1;
@@ -1354,7 +1354,7 @@
 }
 
 bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const {
-    int dirfd = open(dir, O_DIRECTORY);
+    int dirfd = open(dir, O_DIRECTORY | O_CLOEXEC);
     if (dirfd < 0) {
         SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno));
         return false;
@@ -1546,7 +1546,7 @@
     int fd;
     unsigned long nr_sec = 0;
 
-    if ((fd = open(loopDevice, O_RDWR)) < 0) {
+    if ((fd = open(loopDevice, O_RDWR | O_CLOEXEC)) < 0) {
         SLOGE("Failed to open loopdevice (%s)", strerror(errno));
         Loop::destroyByDevice(loopDevice);
         return -1;
@@ -1612,7 +1612,7 @@
     mntent* mentry;
     while ((mentry = getmntent(fp)) != NULL) {
         if (!strncmp(mentry->mnt_dir, loopDir, loopDirLen)) {
-            int fd = open(mentry->mnt_fsname, O_RDONLY);
+            int fd = open(mentry->mnt_fsname, O_RDONLY | O_CLOEXEC);
             if (fd >= 0) {
                 struct loop_info64 li;
                 if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
diff --git a/cryptfs.c b/cryptfs.c
index ebce6e8..f6bad74 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -380,7 +380,7 @@
     struct ext4_super_block sb;
     off64_t len;
 
-    if ((fd = open(dev, O_RDONLY)) < 0) {
+    if ((fd = open(dev, O_RDONLY|O_CLOEXEC)) < 0) {
         SLOGE("Cannot open device to get filesystem size ");
         return 0;
     }
@@ -423,7 +423,7 @@
     fs_mgr_get_crypt_info(fstab, key_loc, real_blkdev, sizeof(key_loc));
 
     if (!strcmp(key_loc, KEY_IN_FOOTER)) {
-      if ( (fd = open(real_blkdev, O_RDWR)) < 0) {
+      if ( (fd = open(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) {
         SLOGE("Cannot open real block device %s\n", real_blkdev);
         return -1;
       }
@@ -485,7 +485,7 @@
     SLOGE("Unexpected value for crypto key location\n");
     return -1;
   }
-  if ( (fd = open(fname, O_RDWR | O_CREAT, 0600)) < 0) {
+  if ( (fd = open(fname, O_RDWR | O_CREAT|O_CLOEXEC, 0600)) < 0) {
     SLOGE("Cannot open footer file %s for put\n", fname);
     return -1;
   }
@@ -623,7 +623,7 @@
     SLOGE("Unexpected value for crypto key location\n");
     return -1;
   }
-  if ( (fd = open(fname, O_RDWR)) < 0) {
+  if ( (fd = open(fname, O_RDWR|O_CLOEXEC)) < 0) {
     SLOGE("Cannot open footer file %s for get\n", fname);
     return -1;
   }
@@ -748,7 +748,7 @@
         return -1;
     }
 
-    fd = open(fname, O_RDONLY);
+    fd = open(fname, O_RDONLY|O_CLOEXEC);
     if (fd < 0) {
         SLOGE("Cannot open %s metadata file", fname);
         return -1;
@@ -829,7 +829,7 @@
         return -1;
     }
 
-    fd = open(fname, O_RDWR);
+    fd = open(fname, O_RDWR|O_CLOEXEC);
     if (fd < 0) {
         SLOGE("Cannot open %s metadata file", fname);
         return -1;
@@ -1067,7 +1067,7 @@
   char *extra_params;
   int load_count;
 
-  if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) {
+  if ((fd = open("/dev/device-mapper", O_RDWR|O_CLOEXEC)) < 0 ) {
     SLOGE("Cannot open device-mapper\n");
     goto errout;
   }
@@ -1132,7 +1132,7 @@
   struct dm_ioctl *io;
   int retval = -1;
 
-  if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) {
+  if ((fd = open("/dev/device-mapper", O_RDWR|O_CLOEXEC)) < 0 ) {
     SLOGE("Cannot open device-mapper\n");
     goto errout;
   }
@@ -1416,7 +1416,7 @@
     unsigned char key_buf[KEY_LEN_BYTES];
 
     /* Get some random bits for a key */
-    fd = open("/dev/urandom", O_RDONLY);
+    fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC);
     read(fd, key_buf, sizeof(key_buf));
     read(fd, salt, SALT_LEN);
     close(fd);
@@ -1892,7 +1892,7 @@
  */
 int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev,
         const unsigned char* key, int keysize, char* out_crypto_blkdev) {
-    int fd = open(real_blkdev, O_RDONLY);
+    int fd = open(real_blkdev, O_RDONLY|O_CLOEXEC);
     if (fd == -1) {
         SLOGE("Failed to open %s: %s", real_blkdev, strerror(errno));
         return -1;
@@ -2453,14 +2453,14 @@
     data.real_blkdev = real_blkdev;
     data.crypto_blkdev = crypto_blkdev;
 
-    if ( (data.realfd = open(real_blkdev, O_RDWR)) < 0) {
+    if ( (data.realfd = open(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) {
         SLOGE("Error opening real_blkdev %s for inplace encrypt. err=%d(%s)\n",
               real_blkdev, errno, strerror(errno));
         rc = -1;
         goto errout;
     }
 
-    if ( (data.cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) {
+    if ( (data.cryptofd = open(crypto_blkdev, O_WRONLY|O_CLOEXEC)) < 0) {
         SLOGE("Error opening crypto_blkdev %s for ext4 inplace encrypt. err=%d(%s)\n",
               crypto_blkdev, errno, strerror(errno));
         rc = ENABLE_INPLACE_ERR_DEV;
@@ -2584,12 +2584,12 @@
     data.crypto_blkdev = crypto_blkdev;
     data.realfd = -1;
     data.cryptofd = -1;
-    if ( (data.realfd = open64(real_blkdev, O_RDWR)) < 0) {
+    if ( (data.realfd = open64(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) {
         SLOGE("Error opening real_blkdev %s for f2fs inplace encrypt\n",
               real_blkdev);
         goto errout;
     }
-    if ( (data.cryptofd = open64(crypto_blkdev, O_WRONLY)) < 0) {
+    if ( (data.cryptofd = open64(crypto_blkdev, O_WRONLY|O_CLOEXEC)) < 0) {
         SLOGE("Error opening crypto_blkdev %s for f2fs inplace encrypt. err=%d(%s)\n",
               crypto_blkdev, errno, strerror(errno));
         rc = ENABLE_INPLACE_ERR_DEV;
@@ -2656,12 +2656,12 @@
     off64_t one_pct, cur_pct, new_pct;
     off64_t blocks_already_done, tot_numblocks;
 
-    if ( (realfd = open(real_blkdev, O_RDONLY)) < 0) { 
+    if ( (realfd = open(real_blkdev, O_RDONLY|O_CLOEXEC)) < 0) {
         SLOGE("Error opening real_blkdev %s for inplace encrypt\n", real_blkdev);
         return ENABLE_INPLACE_ERR_OTHER;
     }
 
-    if ( (cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) { 
+    if ( (cryptofd = open(crypto_blkdev, O_WRONLY|O_CLOEXEC)) < 0) {
         SLOGE("Error opening crypto_blkdev %s for inplace encrypt. err=%d(%s)\n",
               crypto_blkdev, errno, strerror(errno));
         close(realfd);
@@ -2819,7 +2819,7 @@
 
 static int cryptfs_SHA256_fileblock(const char* filename, __le8* buf)
 {
-    int fd = open(filename, O_RDONLY);
+    int fd = open(filename, O_RDONLY|O_CLOEXEC);
     if (fd == -1) {
         SLOGE("Error opening file %s", filename);
         return -1;
@@ -2959,7 +2959,7 @@
     fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
 
     /* Get the size of the real block device */
-    int fd = open(real_blkdev, O_RDONLY);
+    int fd = open(real_blkdev, O_RDONLY|O_CLOEXEC);
     if (fd == -1) {
         SLOGE("Cannot open block device %s\n", real_blkdev);
         goto error_unencrypted;
@@ -3190,7 +3190,7 @@
             /* wipe data if encryption failed */
             SLOGE("encryption failed - rebooting into recovery to wipe data\n");
             mkdir("/cache/recovery", 0700);
-            int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC, 0600);
+            int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0600);
             if (fd >= 0) {
                 write(fd, "--wipe_data\n", strlen("--wipe_data\n") + 1);
                 write(fd, "--reason=cryptfs_enable_internal\n", strlen("--reason=cryptfs_enable_internal\n") + 1);