Make transition to "postinstall" domain explicit.

When running the postinstall program, we were relying on the automatic
transition between update_engine domain and postinstall, which required
postinstall_file to be an entrypoint for such domain. This patch makes
the transition explicit by calling setexeccon(3).

Bug: 28008031
TEST=make dist; Deployed an update to edison-eng: postinstall runs as "postinstall" domain.

Change-Id: I27d404886841e0bd39589f0274eaaf98929eeac9
diff --git a/common/subprocess.cc b/common/subprocess.cc
index 9738b1d..9473f10 100644
--- a/common/subprocess.cc
+++ b/common/subprocess.cc
@@ -32,6 +32,9 @@
 #include <base/strings/stringprintf.h>
 #include <brillo/process.h>
 #include <brillo/secure_blob.h>
+#ifdef __ANDROID__
+#include <selinux/selinux.h>
+#endif  // __ANDROID__
 
 #include "update_engine/common/utils.h"
 
@@ -44,7 +47,9 @@
 
 namespace {
 
-bool SetupChild(const std::map<string, string>& env, uint32_t flags) {
+bool SetupChild(const std::map<string, string>& env,
+                uint32_t flags,
+                const char* se_domain) {
   // Setup the environment variables.
   clearenv();
   for (const auto& key_value : env) {
@@ -63,6 +68,15 @@
     return false;
   IGNORE_EINTR(close(fd));
 
+#ifdef __ANDROID__
+  // setexeccon(3) accepts a nullptr to indicate the default context policy.
+  if (setexeccon(se_domain) < 0) {
+    PLOG(ERROR) << "Error setting the SELinux domain to "
+                << (se_domain ? se_domain : "<nullptr>");
+    return false;
+  }
+#endif  // __ANDROID__
+
   return true;
 }
 
@@ -74,6 +88,7 @@
 bool LaunchProcess(const vector<string>& cmd,
                    uint32_t flags,
                    const vector<int>& output_pipes,
+                   const char* se_domain,
                    brillo::Process* proc) {
   for (const string& arg : cmd)
     proc->AddArg(arg);
@@ -92,7 +107,7 @@
   }
   proc->SetCloseUnusedFileDescriptors(true);
   proc->RedirectUsingPipe(STDOUT_FILENO, false);
-  proc->SetPreExecCallback(base::Bind(&SetupChild, env, flags));
+  proc->SetPreExecCallback(base::Bind(&SetupChild, env, flags, se_domain));
 
   return proc->Start();
 }
@@ -170,16 +185,17 @@
 
 pid_t Subprocess::Exec(const vector<string>& cmd,
                        const ExecCallback& callback) {
-  return ExecFlags(cmd, kRedirectStderrToStdout, {}, callback);
+  return ExecFlags(cmd, kRedirectStderrToStdout, {}, nullptr, callback);
 }
 
 pid_t Subprocess::ExecFlags(const vector<string>& cmd,
                             uint32_t flags,
                             const vector<int>& output_pipes,
+                            const char* se_domain,
                             const ExecCallback& callback) {
   unique_ptr<SubprocessRecord> record(new SubprocessRecord(callback));
 
-  if (!LaunchProcess(cmd, flags, output_pipes, &record->proc)) {
+  if (!LaunchProcess(cmd, flags, output_pipes, se_domain, &record->proc)) {
     LOG(ERROR) << "Failed to launch subprocess";
     return 0;
   }
@@ -248,7 +264,7 @@
   // It doesn't make sense to redirect some pipes in the synchronous case
   // because we won't be reading on our end, so we don't expose the output_pipes
   // in this case.
-  if (!LaunchProcess(cmd, flags, {}, &proc)) {
+  if (!LaunchProcess(cmd, flags, {}, nullptr, &proc)) {
     LOG(ERROR) << "Failed to launch subprocess";
     return false;
   }