summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deymo <deymo@google.com>2016-04-04 19:09:22 -0700
committerAlex Deymo <deymo@google.com>2016-04-05 08:32:58 -0700
commit20e3960e245f6dfa57fa5c9124b0fd33e679f723 (patch)
tree1e76cf3bc9913502f4a71a1fb6d0e810c963e8ac
parent0d29854cf5bb05a22cf161b50052539aa420a36e (diff)
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
-rw-r--r--Android.mk1
-rw-r--r--common/subprocess.cc26
-rw-r--r--common/subprocess.h1
-rw-r--r--common/subprocess_unittest.cc7
-rw-r--r--p2p_manager.cc5
-rw-r--r--payload_consumer/postinstall_runner_action.cc4
6 files changed, 34 insertions, 10 deletions
diff --git a/Android.mk b/Android.mk
index afb14a62..633baa2b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -149,6 +149,7 @@ ue_libpayload_consumer_exported_static_libraries := \
ue_libpayload_consumer_exported_shared_libraries := \
libcrypto-host \
libcurl-host \
+ libselinux \
libssl-host \
$(ue_update_metadata_protos_exported_shared_libraries)
diff --git a/common/subprocess.cc b/common/subprocess.cc
index 9738b1d1..9473f10c 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 chromeos_update_engine {
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 @@ bool SetupChild(const std::map<string, string>& env, uint32_t flags) {
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 SetupChild(const std::map<string, string>& env, uint32_t flags) {
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 @@ bool LaunchProcess(const vector<string>& cmd,
}
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 @@ void Subprocess::ChildExitedCallback(const siginfo_t& info) {
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 @@ bool Subprocess::SynchronousExecFlags(const vector<string>& cmd,
// 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;
}
diff --git a/common/subprocess.h b/common/subprocess.h
index b655fb74..6c99c8de 100644
--- a/common/subprocess.h
+++ b/common/subprocess.h
@@ -73,6 +73,7 @@ class Subprocess {
pid_t ExecFlags(const std::vector<std::string>& cmd,
uint32_t flags,
const std::vector<int>& output_pipes,
+ const char* se_domain,
const ExecCallback& callback);
// Kills the running process with SIGTERM and ignores the callback.
diff --git a/common/subprocess_unittest.cc b/common/subprocess_unittest.cc
index 5ca44e80..d5e33bba 100644
--- a/common/subprocess_unittest.cc
+++ b/common/subprocess_unittest.cc
@@ -148,6 +148,7 @@ TEST_F(SubprocessTest, StderrNotIncludedInOutputTest) {
{kBinPath "/sh", "-c", "echo on stdout; echo on stderr >&2"},
0,
{},
+ nullptr,
base::Bind(&ExpectedResults, 0, "on stdout\n")));
loop_.Run();
}
@@ -158,6 +159,7 @@ TEST_F(SubprocessTest, PipeRedirectFdTest) {
{kBinPath "/sh", "-c", "echo on pipe >&3"},
0,
{3},
+ nullptr,
base::Bind(&ExpectedDataOnPipe, &subprocess_, &pid, 3, "on pipe\n", 0));
EXPECT_NE(0, pid);
@@ -174,10 +176,7 @@ TEST_F(SubprocessTest, PipeClosedWhenNotRedirectedTest) {
const vector<string> cmd = {kBinPath "/sh", "-c",
base::StringPrintf("echo on pipe >/proc/self/fd/%d", pipe.writer)};
EXPECT_TRUE(subprocess_.ExecFlags(
- cmd,
- 0,
- {},
- base::Bind(&ExpectedResults, 1, "")));
+ cmd, 0, {}, nullptr, base::Bind(&ExpectedResults, 1, "")));
loop_.Run();
}
diff --git a/p2p_manager.cc b/p2p_manager.cc
index 127e5ff9..bcfe1561 100644
--- a/p2p_manager.cc
+++ b/p2p_manager.cc
@@ -396,7 +396,10 @@ class LookupData {
// We expect to run just "p2p-client" and find it in the path.
child_pid_ = Subprocess::Get().ExecFlags(
- cmd, Subprocess::kSearchPath, {},
+ cmd,
+ Subprocess::kSearchPath,
+ {},
+ nullptr,
Bind(&LookupData::OnLookupDone, base::Unretained(this)));
if (!child_pid_) {
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index db1ec3c8..dc4af713 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -43,6 +43,9 @@ namespace {
// sample_images.sh file.
const int kPostinstallStatusFd = 3;
+// The SELinux domain where the postinstall program runs.
+const char* kPostinstallDomain = "postinstall";
+
} // namespace
namespace chromeos_update_engine {
@@ -167,6 +170,7 @@ void PostinstallRunnerAction::PerformPartitionPostinstall() {
command,
Subprocess::kRedirectStderrToStdout,
{kPostinstallStatusFd},
+ kPostinstallDomain,
base::Bind(&PostinstallRunnerAction::CompletePartitionPostinstall,
base::Unretained(this)));
// Subprocess::Exec should never return a negative process id.