Different blkid and fsck execution domains.

vold works with two broad classes of block devices: untrusted devices
that come in from the wild, and trusted devices like PrivateVolume
which are encrypted.

When running blkid and fsck, we pick which SELinux execution domain
to use based on which class the device belongs to.

Bug: 19993667
Change-Id: I2695f028710a4863f0c3b2ed6da437f466401272
diff --git a/Utils.cpp b/Utils.cpp
index 7d32590..2b02f91 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -41,6 +41,11 @@
 namespace android {
 namespace vold {
 
+security_context_t sBlkidContext = nullptr;
+security_context_t sBlkidUntrustedContext = nullptr;
+security_context_t sFsckContext = nullptr;
+security_context_t sFsckUntrustedContext = nullptr;
+
 static const char* kBlkidPath = "/system/bin/blkid";
 
 status_t CreateDeviceNode(const std::string& path, dev_t dev) {
@@ -111,14 +116,21 @@
     return OK;
 }
 
-status_t ReadMetadata(const std::string& path, std::string& fsType,
-        std::string& fsUuid, std::string& fsLabel) {
+static status_t readMetadata(const std::string& path, std::string& fsType,
+        std::string& fsUuid, std::string& fsLabel, bool untrusted) {
     fsType.clear();
     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;
@@ -154,6 +166,16 @@
     return res;
 }
 
+status_t ReadMetadata(const std::string& path, std::string& fsType,
+        std::string& fsUuid, std::string& fsLabel) {
+    return readMetadata(path, fsType, fsUuid, fsLabel, false);
+}
+
+status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType,
+        std::string& fsUuid, std::string& fsLabel) {
+    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();