// Copyright (c) 2012 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 "cros-disks/sandboxed_process.h"

#include <utility>

#include <stdlib.h>

#include <sys/mount.h>
#include <sys/wait.h>
#include <unistd.h>

#include <base/bind.h>
#include <base/check.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/posix/safe_strerror.h>
#include <chromeos/libminijail.h>

#include "cros-disks/mount_options.h"
#include "cros-disks/quote.h"

namespace cros_disks {
namespace {

int Exec(char* const args[], char* const env[]) {
  const char* const path = args[0];
  execve(path, args, env);
  const int ret =
      (errno == ENOENT ? MINIJAIL_ERR_NO_COMMAND : MINIJAIL_ERR_NO_ACCESS);
  PLOG(ERROR) << "Cannot exec " << quote(path);
  return ret;
}

}  // namespace

SandboxedProcess::SandboxedProcess() : jail_(minijail_new()) {
  CHECK(jail_) << "Failed to create a process jail";
}

SandboxedProcess::~SandboxedProcess() {
  minijail_destroy(jail_);
}

void SandboxedProcess::LoadSeccompFilterPolicy(const std::string& policy_file) {
  minijail_parse_seccomp_filters(jail_, policy_file.c_str());
  minijail_use_seccomp_filter(jail_);
}

void SandboxedProcess::NewCgroupNamespace() {
  minijail_namespace_cgroups(jail_);
}

void SandboxedProcess::NewIpcNamespace() {
  minijail_namespace_ipc(jail_);
}

void SandboxedProcess::NewMountNamespace() {
  minijail_namespace_vfs(jail_);
}

void SandboxedProcess::EnterExistingMountNamespace(const std::string& ns_path) {
  minijail_namespace_enter_vfs(jail_, ns_path.c_str());
}

void SandboxedProcess::NewPidNamespace() {
  minijail_namespace_pids(jail_);
  minijail_run_as_init(jail_);
  minijail_reset_signal_mask(jail_);
  minijail_reset_signal_handlers(jail_);
  minijail_skip_remount_private(jail_);  // crbug.com/1008262
  use_pid_namespace_ = true;
}

bool SandboxedProcess::SetUpMinimalMounts() {
  if (minijail_bind(jail_, "/", "/", 0))
    return false;
  if (minijail_bind(jail_, "/proc", "/proc", 0))
    return false;
  minijail_remount_proc_readonly(jail_);
  minijail_mount_tmp_size(jail_, 128 * 1024 * 1024);

  // Create a minimal /dev with a very restricted set of device nodes.
  minijail_mount_dev(jail_);
  if (minijail_bind(jail_, "/dev/log", "/dev/log", 0))
    return false;
  return true;
}

bool SandboxedProcess::BindMount(const std::string& from,
                                 const std::string& to,
                                 bool writeable,
                                 bool recursive) {
  int flags = MS_BIND;
  if (!writeable) {
    flags |= MS_RDONLY;
  }
  if (recursive) {
    flags |= MS_REC;
  }
  return minijail_mount(jail_, from.c_str(), to.c_str(), "", flags) == 0;
}

bool SandboxedProcess::Mount(const std::string& src,
                             const std::string& to,
                             const std::string& type,
                             const char* data) {
  return minijail_mount_with_data(jail_, src.c_str(), to.c_str(), type.c_str(),
                                  0, data) == 0;
}

bool SandboxedProcess::EnterPivotRoot() {
  return minijail_enter_pivot_root(jail_, "/mnt/empty") == 0;
}

void SandboxedProcess::NewNetworkNamespace() {
  // As of 2021-08-04, this can log a warning to /var/log/messages:
  // "ioctl(SIOCSIFFLAGS) failed: Operation not permitted"
  //
  // This libminijail message is harmless: https://crbug.com/1226229
  minijail_namespace_net(jail_);
}

void SandboxedProcess::SetNoNewPrivileges() {
  minijail_no_new_privs(jail_);
}

void SandboxedProcess::SetCapabilities(uint64_t capabilities) {
  minijail_use_caps(jail_, capabilities);
}

void SandboxedProcess::SetGroupId(gid_t group_id) {
  minijail_change_gid(jail_, group_id);
}

void SandboxedProcess::SetUserId(uid_t user_id) {
  minijail_change_uid(jail_, user_id);
}

void SandboxedProcess::SetSupplementaryGroupIds(base::span<const gid_t> gids) {
  minijail_set_supplementary_gids(jail_, gids.size(), gids.data());
}

bool SandboxedProcess::AddToCgroup(const std::string& cgroup) {
  return minijail_add_to_cgroup(jail_, cgroup.c_str()) == 0;
}

void SandboxedProcess::PreserveFile(int fd) {
  if (const int ret = minijail_preserve_fd(jail_, fd, fd)) {
    LOG(FATAL) << "Cannot preserve file descriptor " << fd << ": "
               << base::safe_strerror(-ret);
  }
}

pid_t SandboxedProcess::StartImpl(base::ScopedFD in_fd, base::ScopedFD out_fd) {
  char* const* const args = GetArguments();
  DCHECK(args && args[0]);
  char* const* const env = GetEnvironment();
  DCHECK(env);

  pid_t child_pid = kInvalidProcessId;

  minijail_close_open_fds(jail_);

  // Set up stdin, stdout and stderr to be connected to the matching pipes in
  // the jailed process.
  CHECK_EQ(minijail_preserve_fd(jail_, in_fd.get(), STDIN_FILENO), 0);
  CHECK_EQ(minijail_preserve_fd(jail_, out_fd.get(), STDOUT_FILENO), 0);
  CHECK_EQ(minijail_preserve_fd(jail_, out_fd.get(), STDERR_FILENO), 0);

  if (!use_pid_namespace_) {
    if (const int ret = minijail_run_env_pid_pipes(
            jail_, args[0], args, env, &child_pid, nullptr, nullptr, nullptr);
        ret < 0) {
      errno = -ret;
      PLOG(ERROR) << "Cannot start minijail process";
      return kInvalidProcessId;
    }
  } else {
    // The sandboxed process will run in a PID namespace.
    PreserveFile(launcher_pipe_.child_fd.get());

    SubprocessPipe termination_pipe(SubprocessPipe::kParentToChild);
    PreserveFile(termination_pipe.child_fd.get());

    // Create child 'init' process in the PID namespace.
    child_pid = minijail_fork(jail_);
    if (child_pid < 0) {
      errno = -child_pid;
      PLOG(ERROR) << "Cannot run minijail_fork";
      return kInvalidProcessId;
    }

    if (child_pid == 0) {
      // In child 'init' process.
      SandboxedInit(base::BindOnce(Exec, args, env),
                    std::move(launcher_pipe_.child_fd),
                    std::move(termination_pipe.child_fd))
          .Run();
      NOTREACHED();
    } else {
      // In parent process.
      PCHECK(base::SetNonBlocking(launcher_pipe_.parent_fd.get()));
      launcher_pipe_.child_fd.reset();

      DCHECK(!termination_fd_.is_valid());
      termination_fd_ = std::move(termination_pipe.parent_fd);
      DCHECK(termination_fd_.is_valid());
    }
  }

  return child_pid;
}

int SandboxedProcess::WaitImpl() {
  if (use_pid_namespace_) {
    launcher_watch_.reset();
    return SandboxedInit::WaitForLauncher(&launcher_pipe_.parent_fd);
  }

  while (true) {
    const int status = minijail_wait(jail_);
    if (status >= 0)
      return status;

    if (const int err = -status; err != EINTR) {
      LOG(ERROR) << "Cannot wait for process " << pid() << ": "
                 << base::safe_strerror(err);
      return MINIJAIL_ERR_INIT;
    }
  }
}

int SandboxedProcess::WaitNonBlockingImpl() {
  if (use_pid_namespace_) {
    const int exit_code =
        SandboxedInit::PollLauncher(&launcher_pipe_.parent_fd);
    if (exit_code >= 0)
      launcher_watch_.reset();
    return exit_code;
  }

  // TODO(chromium:971667) Use Minijail's non-blocking wait once it exists.
  int wstatus;
  const pid_t child_pid = pid();
  const int ret = waitpid(child_pid, &wstatus, WNOHANG);
  if (ret < 0) {
    PLOG(ERROR) << "Cannot wait for process " << child_pid;
    return MINIJAIL_ERR_INIT;
  }

  if (ret == 0) {
    // Process is still running.
    return -1;
  }

  return SandboxedInit::WaitStatusToExitCode(wstatus);
}

int FakeSandboxedProcess::OnProcessLaunch(
    const std::vector<std::string>& argv) {
  return 0;
}

pid_t FakeSandboxedProcess::StartImpl(base::ScopedFD, base::ScopedFD) {
  DCHECK(!ret_code_);
  ret_code_ = OnProcessLaunch(arguments());
  return 42;
}

int FakeSandboxedProcess::WaitImpl() {
  DCHECK(ret_code_);
  return ret_code_.value();
}

int FakeSandboxedProcess::WaitNonBlockingImpl() {
  if (ret_code_)
    return ret_code_.value();
  return -1;
}

}  // namespace cros_disks
