diff options
author | Alex Deymo <deymo@google.com> | 2016-04-04 19:09:22 -0700 |
---|---|---|
committer | Alex Deymo <deymo@google.com> | 2016-04-05 08:32:58 -0700 |
commit | 20e3960e245f6dfa57fa5c9124b0fd33e679f723 (patch) | |
tree | 1e76cf3bc9913502f4a71a1fb6d0e810c963e8ac | |
parent | 0d29854cf5bb05a22cf161b50052539aa420a36e (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.mk | 1 | ||||
-rw-r--r-- | common/subprocess.cc | 26 | ||||
-rw-r--r-- | common/subprocess.h | 1 | ||||
-rw-r--r-- | common/subprocess_unittest.cc | 7 | ||||
-rw-r--r-- | p2p_manager.cc | 5 | ||||
-rw-r--r-- | payload_consumer/postinstall_runner_action.cc | 4 |
6 files changed, 34 insertions, 10 deletions
@@ -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. |