| // Copyright 2017 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "imageloader/imageloader.h" |
| |
| #include <libminijail.h> |
| #include <scoped_minijail.h> |
| #include <sysexits.h> |
| |
| #include <string> |
| #include <utility> |
| |
| #include <base/files/file_path.h> |
| #include <base/threading/thread_task_runner_handle.h> |
| #include <chromeos/dbus/service_constants.h> |
| |
| namespace imageloader { |
| |
| namespace { |
| constexpr char kSeccompFilterPath[] = |
| "/usr/share/policy/imageloader-seccomp.policy"; |
| } // namespace |
| |
| // static |
| const char ImageLoader::kImageLoaderGroupName[] = "imageloaderd"; |
| const char ImageLoader::kImageLoaderUserName[] = "imageloaderd"; |
| const int ImageLoader::kShutdownTimeoutMilliseconds = 20000; |
| const char ImageLoader::kLoadedMountsBase[] = "/run/imageloader"; |
| |
| ImageLoader::ImageLoader(ImageLoaderConfig config, |
| std::unique_ptr<HelperProcessProxy> proxy) |
| : DBusServiceDaemon(kImageLoaderServiceName), |
| impl_(std::move(config)), |
| helper_process_proxy_(std::move(proxy)) {} |
| |
| ImageLoader::~ImageLoader() = default; |
| |
| // static |
| void ImageLoader::EnterSandbox() { |
| ScopedMinijail jail(minijail_new()); |
| minijail_no_new_privs(jail.get()); |
| minijail_use_seccomp_filter(jail.get()); |
| minijail_parse_seccomp_filters(jail.get(), kSeccompFilterPath); |
| minijail_reset_signal_mask(jail.get()); |
| minijail_namespace_ipc(jail.get()); |
| minijail_namespace_net(jail.get()); |
| minijail_remount_proc_readonly(jail.get()); |
| CHECK_EQ(0, minijail_change_user(jail.get(), kImageLoaderUserName)); |
| CHECK_EQ(0, minijail_change_group(jail.get(), kImageLoaderGroupName)); |
| minijail_enter(jail.get()); |
| } |
| |
| int ImageLoader::OnInit() { |
| // Run with minimal privileges. |
| EnterSandbox(); |
| |
| int return_code = brillo::DBusServiceDaemon::OnInit(); |
| if (return_code != EX_OK) |
| return return_code; |
| |
| process_reaper_.Register(this); |
| process_reaper_.WatchForChild( |
| FROM_HERE, helper_process_proxy_->pid(), |
| base::Bind(&ImageLoader::OnSubprocessExited, weak_factory_.GetWeakPtr(), |
| helper_process_proxy_->pid())); |
| |
| PostponeShutdown(); |
| |
| return EX_OK; |
| } |
| |
| void ImageLoader::RegisterDBusObjectsAsync( |
| brillo::dbus_utils::AsyncEventSequencer* sequencer) { |
| dbus_object_.reset(new brillo::dbus_utils::DBusObject( |
| nullptr, bus_, |
| org::chromium::ImageLoaderInterfaceAdaptor::GetObjectPath())); |
| dbus_adaptor_.RegisterWithDBusObject(dbus_object_.get()); |
| dbus_object_->RegisterAsync( |
| sequencer->GetHandler("ImageLoader.RegisterAsync() failed.", true)); |
| } |
| |
| void ImageLoader::OnShutdown(int* return_code) { |
| brillo::DBusServiceDaemon::OnShutdown(return_code); |
| } |
| |
| void ImageLoader::OnSubprocessExited(pid_t pid, const siginfo_t& info) { |
| LOG(FATAL) << "Subprocess " << pid << " exited unexpectedly."; |
| } |
| |
| void ImageLoader::PostponeShutdown() { |
| shutdown_callback_.Reset( |
| base::Bind(&brillo::Daemon::Quit, base::Unretained(this))); |
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| FROM_HERE, shutdown_callback_.callback(), |
| base::TimeDelta::FromMilliseconds(kShutdownTimeoutMilliseconds)); |
| } |
| |
| bool ImageLoader::RegisterComponent( |
| brillo::ErrorPtr* err, |
| const std::string& name, |
| const std::string& version, |
| const std::string& component_folder_abs_path, |
| bool* out_success) { |
| *out_success = |
| impl_.RegisterComponent(name, version, component_folder_abs_path); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| bool ImageLoader::GetComponentVersion(brillo::ErrorPtr* err, |
| const std::string& name, |
| std::string* out_version) { |
| *out_version = impl_.GetComponentVersion(name); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| bool ImageLoader::LoadComponent(brillo::ErrorPtr* err, |
| const std::string& name, |
| std::string* out_mount_point) { |
| *out_mount_point = impl_.LoadComponent(name, helper_process_proxy_.get()); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| bool ImageLoader::LoadComponentAtPath(brillo::ErrorPtr* err, |
| const std::string& name, |
| const std::string& absolute_path, |
| std::string* out_mount_point) { |
| *out_mount_point = impl_.LoadComponentAtPath( |
| name, base::FilePath(absolute_path), helper_process_proxy_.get()); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| bool ImageLoader::LoadDlcImage(brillo::ErrorPtr* err, |
| const std::string& id, |
| const std::string& package, |
| const std::string& a_or_b, |
| std::string* out_mount_point) { |
| *out_mount_point = |
| impl_.LoadDlcImage(id, package, a_or_b, helper_process_proxy_.get()); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| bool ImageLoader::RemoveComponent(brillo::ErrorPtr* err, |
| const std::string& name, |
| bool* out_success) { |
| *out_success = impl_.RemoveComponent(name); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| bool ImageLoader::GetComponentMetadata( |
| brillo::ErrorPtr* err, |
| const std::string& name, |
| std::map<std::string, std::string>* out_metadata) { |
| if (!impl_.GetComponentMetadata(name, out_metadata)) |
| out_metadata->clear(); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| bool ImageLoader::UnmountComponent(brillo::ErrorPtr* err, |
| const std::string& name, |
| bool* out_success) { |
| base::FilePath component_mount_root = |
| base::FilePath(imageloader::ImageLoader::kLoadedMountsBase).Append(name); |
| *out_success = impl_.CleanupAll(false, component_mount_root, nullptr, |
| helper_process_proxy_.get()); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| bool ImageLoader::UnloadDlcImage(brillo::ErrorPtr* err, |
| const std::string& id, |
| const std::string& package, |
| bool* out_success) { |
| *out_success = impl_.UnloadDlcImage(id, package, helper_process_proxy_.get()); |
| PostponeShutdown(); |
| return true; |
| } |
| |
| } // namespace imageloader |