// 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 "login_manager/system_utils_impl.h"

#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#include <algorithm>
#include <limits>
#include <string>
#include <utility>
#include <vector>

#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/important_file_writer.h>
#include <base/files/scoped_temp_dir.h>
#include <base/logging.h>
#include <base/process/launch.h>
#include <base/strings/string_util.h>
#include <base/sys_info.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>
#include <brillo/file_utils.h>
#include <brillo/process.h>
#include <brillo/userdb_utils.h>
#include <chromeos/dbus/service_constants.h>

#include "login_manager/child_job.h"  // For ChildJobInterface exit codes.

using std::string;
using std::vector;

namespace login_manager {

namespace {

// Sets the signal mask of child processes spawned by
// SystemUtilsImpl::LaunchAndWait() to have the default signal mask instead of
// [HUP INT TERM].
class ResetSigmaskDelegate : public base::LaunchOptions::PreExecDelegate {
 public:
  ResetSigmaskDelegate() = default;
  ~ResetSigmaskDelegate() override = default;

  void RunAsyncSafe() override {
    sigset_t new_sigset;
    sigemptyset(&new_sigset);
    // We cannot use PCHECK() here since that's not async-signal safe. Do the
    // next best thing which is call abort(3).
    if (sigprocmask(SIG_SETMASK, &new_sigset, nullptr) != 0)
      abort();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ResetSigmaskDelegate);
};

}  // namespace

SystemUtilsImpl::SystemUtilsImpl() = default;

SystemUtilsImpl::~SystemUtilsImpl() = default;

DevModeState SystemUtilsImpl::GetDevModeState() {
  // Return the cached result when possible. There is no reason to run
  // crossytem twice as cros_debug is always read-only.
  if (dev_mode_state_ == DevModeState::DEV_MODE_UNKNOWN) {
    int exit_code = -1;
    if (LaunchAndWait({"crossystem", "cros_debug?0"}, &exit_code)) {
      switch (exit_code) {
        case 0:
          dev_mode_state_ = DevModeState::DEV_MODE_OFF;
          break;
        case 1:
          dev_mode_state_ = DevModeState::DEV_MODE_ON;
          break;
        default:
          LOG(ERROR) << "Unexpected exit code from crossystem: " << exit_code;
          break;
      }
    }
  }
  return dev_mode_state_;
}

VmState SystemUtilsImpl::GetVmState() {
  // Return the cached result when possible. There is no reason to run
  // crossystem twice as inside_vm is always read-only.
  if (vm_state_ == VmState::UNKNOWN) {
    int exit_code = -1;
    if (LaunchAndWait({"crossystem", "inside_vm?0"}, &exit_code)) {
      switch (exit_code) {
        case 0:
          vm_state_ = VmState::OUTSIDE_VM;
          break;
        case 1:
          vm_state_ = VmState::INSIDE_VM;
          break;
        default:
          LOG(ERROR) << "Unexpected exit code from crossystem: " << exit_code;
          break;
      }
    }
  }
  return vm_state_;
}

int SystemUtilsImpl::kill(pid_t pid, uid_t owner, int signal) {
  LOG(INFO) << "Sending signal " << signal << " to PID " << pid << " as UID "
            << owner;
  uid_t uid, euid, suid;
  getresuid(&uid, &euid, &suid);
  if (setresuid(owner, owner, -1)) {
    PLOG(ERROR) << "Couldn't assume uid " << owner;
    return -1;
  }
  int ret = ::kill(pid, signal);
  if (setresuid(uid, euid, -1)) {
    PLOG(ERROR) << "Couldn't return to root";
    return -1;
  }
  return ret;
}

time_t SystemUtilsImpl::time(time_t* t) {
  return ::time(t);
}

pid_t SystemUtilsImpl::fork() {
  return ::fork();
}

int SystemUtilsImpl::close(int fd) {
  return ::close(fd);
}

int SystemUtilsImpl::chdir(const base::FilePath& path) {
  return ::chdir(path.value().c_str());
}

pid_t SystemUtilsImpl::setsid() {
  return ::setsid();
}

int SystemUtilsImpl::execve(const base::FilePath& exec_file,
                            const char* const argv[],
                            const char* const envp[]) {
  return ::execve(exec_file.value().c_str(), const_cast<char* const*>(argv),
                  const_cast<char* const*>(envp));
}

bool SystemUtilsImpl::EnterNewMountNamespace() {
  return ::unshare(CLONE_NEWNS) == 0;
}

bool SystemUtilsImpl::GetAppOutput(const std::vector<std::string>& argv,
                                   std::string* output) {
  return base::GetAppOutput(argv, output);
}

bool SystemUtilsImpl::ProcessGroupIsGone(pid_t child_spec,
                                         base::TimeDelta timeout) {
  return ProcessIsGone(-child_spec, timeout);
}

bool SystemUtilsImpl::ProcessIsGone(pid_t child_spec, base::TimeDelta timeout) {
  DCHECK_GE(timeout.InSeconds(), 0);
  DCHECK_LE(timeout.InSeconds(),
            static_cast<int64_t>(std::numeric_limits<int>::max()));

  base::TimeTicks timeout_time = base::TimeTicks::Now() + timeout;

  pid_t ret = 0;
  // We do this in a loop to support waiting on multiple children.
  // This is necessary for the ProcessGroupIsGone function to work.
  do {
    base::TimeDelta time_remaining = timeout_time - base::TimeTicks::Now();

    // Pass 0 to |timeout| if we already time out to reap all zombie processes
    // specified by |child_spec|. This loop will end when |ret| is no longer
    // larger than 0, i.e. no more zombie process to reap.
    ret =
        Wait(child_spec, std::max(time_remaining, base::TimeDelta()), nullptr);
    if (ret == -1 && errno == ECHILD)
      return true;
  } while (ret > 0);

  return false;
}

pid_t SystemUtilsImpl::Wait(pid_t child_spec,
                            base::TimeDelta timeout,
                            int* status_out) {
  DCHECK_GE(timeout, base::TimeDelta());

  const base::TimeTicks start = base::TimeTicks::Now();

  while (true) {
    pid_t pid = waitpid(child_spec, status_out, WNOHANG);

    // Error (including no children remaining).
    if (pid == -1 && errno != EINTR)
      return -1;

    // Process was reaped.
    if (pid > 0)
      return pid;

    // Timeout.
    if (base::TimeTicks::Now() - start > timeout)
      return 0;

    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
  }
}

bool SystemUtilsImpl::EnsureAndReturnSafeFileSize(const base::FilePath& file,
                                                  int32_t* file_size_32) {
  const base::FilePath file_in_base_dir = PutInsideBaseDir(file);
  // Get the file size (must fit in a 32 bit int for NSS).
  int64_t file_size;
  if (!base::GetFileSize(file_in_base_dir, &file_size)) {
    LOG(ERROR) << "Could not get size of " << file_in_base_dir.value();
    return false;
  }
  if (file_size > static_cast<int64_t>(std::numeric_limits<int32_t>::max())) {
    LOG(ERROR) << file_in_base_dir.value() << "is " << file_size
               << "bytes!!!  Too big!";
    return false;
  }
  *file_size_32 = static_cast<int32_t>(file_size);
  return true;
}

bool SystemUtilsImpl::Exists(const base::FilePath& file) {
  return base::PathExists(PutInsideBaseDir(file));
}

bool SystemUtilsImpl::GetUniqueFilenameInWriteOnlyTempDir(
    base::FilePath* temp_file_path) {
  // Create a temporary directory to put the testing channel in.
  // It will be made write-only below; we need to be able to read it
  // when trying to create a unique name inside it.
  base::FilePath temp_dir_path;
  if (!base::CreateNewTempDirectory("", &temp_dir_path)) {
    PLOG(ERROR) << "Can't create temp dir";
    return false;
  }
  // Create a temporary file in the temporary directory, to be deleted later.
  // This ensures a unique name.
  if (!base::CreateTemporaryFileInDir(temp_dir_path, temp_file_path)) {
    PLOG(ERROR) << "Can't get temp file name in " << temp_dir_path.value();
    return false;
  }
  // Now, allow access to non-root processes.
  if (chmod(temp_dir_path.value().c_str(), 0333)) {
    PLOG(ERROR) << "Can't chmod " << temp_file_path->value() << " to 0333.";
    return false;
  }
  if (!RemoveFile(*temp_file_path)) {
    PLOG(ERROR) << "Can't clear temp file in " << temp_file_path->value();
    return false;
  }
  return true;
}

bool SystemUtilsImpl::RemoveFile(const base::FilePath& filename) {
  const base::FilePath filename_in_base_dir = PutInsideBaseDir(filename);
  if (base::DirectoryExists(filename_in_base_dir))
    return false;
  return base::DeleteFile(filename_in_base_dir, false);
}

bool SystemUtilsImpl::AtomicFileWrite(const base::FilePath& filename,
                                      const std::string& data) {
  const base::FilePath filename_in_base_dir = PutInsideBaseDir(filename);
  return brillo::WriteToFileAtomic(filename_in_base_dir, data.data(),
                                   data.size(), (S_IRUSR | S_IWUSR | S_IROTH));
}

bool SystemUtilsImpl::DirectoryExists(const base::FilePath& dir) {
  return base::DirectoryExists(PutInsideBaseDir(dir));
}

bool SystemUtilsImpl::CreateDir(const base::FilePath& dir) {
  return base::CreateDirectoryAndGetError(PutInsideBaseDir(dir), nullptr);
}

bool SystemUtilsImpl::EnumerateFiles(const base::FilePath& root_path,
                                     int file_type,
                                     std::vector<base::FilePath>* out_files) {
  out_files->clear();

  if (!DirectoryExists(root_path)) {
    LOG(ERROR) << "\'" << root_path.value() << "\" is not a directory";
    return false;
  }

  base::FileEnumerator files(root_path, false, file_type);
  for (base::FilePath name = files.Next(); !name.empty(); name = files.Next()) {
    out_files->push_back(name);
  }

  return true;
}

int64_t SystemUtilsImpl::AmountOfFreeDiskSpace(const base::FilePath& path) {
  return base::SysInfo::AmountOfFreeDiskSpace(path);
}

base::FilePath SystemUtilsImpl::PutInsideBaseDirForTesting(
    const base::FilePath& path) {
  return PutInsideBaseDir(path);
}

base::FilePath SystemUtilsImpl::PutInsideBaseDir(const base::FilePath& path) {
  if (base_dir_for_testing_.empty())
    return path;  // for production, this function does nothing.

  if (base_dir_for_testing_.IsParent(path))
    return path;  // already chroot'ed.

  base::FilePath to_append(path);
  while (to_append.IsAbsolute()) {
    std::string ascii(path.MaybeAsASCII());
    to_append = base::FilePath(ascii.substr(1, std::string::npos));
  }
  return base_dir_for_testing_.Append(to_append);
}

bool SystemUtilsImpl::GetGidAndGroups(uid_t uid,
                                      gid_t* out_gid,
                                      std::vector<gid_t>* out_groups) {
  DCHECK(out_gid);
  DCHECK(out_groups);
  // First, get the pwent for |uid|, which gives us the related gid and
  // username.
  ssize_t buf_len = std::max(sysconf(_SC_GETPW_R_SIZE_MAX), 16384L);
  passwd pwd_buf = {};
  passwd* pwd = nullptr;
  std::vector<char> buf(buf_len);
  for (int i : {1, 2, 3, 4}) {
    buf_len = buf_len * i;
    buf.resize(buf_len);
    if (getpwuid_r(uid, &pwd_buf, buf.data(), buf_len, &pwd) == 0 ||
        errno != ERANGE) {
      break;
    }
  }
  if (!pwd) {
    PLOG(ERROR) << "Unable to find user " << uid;
    return false;
  }
  *out_gid = pwd->pw_gid;

  // Now, use the gid and username to find the list of all uid's groups.
  // Calling getgrouplist() with ngroups=0 causes it to set ngroups to the
  // number of groups available for the given username, including the provided
  // gid. So do that first, then reserve the right amount of space in
  // out_groups, then call getgrouplist() for realz.
  int ngroups = 0;
  CHECK_EQ(getgrouplist(pwd->pw_name, pwd->pw_gid, nullptr, &ngroups), -1);
  out_groups->resize(ngroups, pwd->pw_gid);
  int actual_ngroups =
      getgrouplist(pwd->pw_name, pwd->pw_gid, out_groups->data(), &ngroups);
  if (actual_ngroups == -1) {
    PLOG(ERROR) << "Even after querying number of groups, still failed!";
    return false;
  } else if (actual_ngroups < ngroups) {
    LOG(WARNING) << "Oddly, found fewer groups than initial call to"
                 << "getgrouplist() indicated.";
    out_groups->resize(actual_ngroups);
  }
  return true;
}

// This function will:
// 1) try to setgid to |gid|
// 2) try to setgroups to |gids|
// 3) try to setuid to |uid|
// 4) try to make a new session, with the current process as leader.
//
// Returns 0 on success, the appropriate exit code (defined above) if a
// call fails.
int SystemUtilsImpl::SetIDs(uid_t uid,
                            gid_t gid,
                            const std::vector<gid_t>& gids) {
  if (setgroups(gids.size(), gids.data()) == -1)
    return ChildJobInterface::kCantSetGroups;
  if (setgid(gid) == -1)
    return ChildJobInterface::kCantSetGid;
  if (setuid(uid) == -1)
    return ChildJobInterface::kCantSetUid;
  if (setsid() == -1)
    RAW_LOG(ERROR, "Can't setsid");
  return 0;
}

bool SystemUtilsImpl::ReadFileToString(const base::FilePath& path,
                                       std::string* str_out) {
  return base::ReadFileToString(path, str_out);
}

bool SystemUtilsImpl::WriteStringToFile(const base::FilePath& path,
                                        const std::string& data) {
  return brillo::WriteStringToFile(path, data);
}

bool SystemUtilsImpl::ChangeBlockedSignals(int how,
                                           const std::vector<int>& signals) {
  sigset_t sigset;
  if (sigemptyset(&sigset)) {
    PLOG(ERROR) << "Failed to empty sigset";
    return false;
  }

  for (int signal : signals) {
    if (sigaddset(&sigset, signal)) {
      PLOG(ERROR) << "Failed to add signal " << signal << " to sigset";
      return false;
    }
  }

  if (sigprocmask(how, &sigset, nullptr)) {
    PLOG(ERROR) << "Failed to change sigblk";
    return false;
  }

  return true;
}

void SystemUtilsImpl::CloseSuperfluousFds(
    const base::InjectiveMultimap& saved_mapping) {
  base::CloseSuperfluousFds(saved_mapping);
}

bool SystemUtilsImpl::LaunchAndWait(const std::vector<std::string>& argv,
                                    int* exit_code_out) {
  DCHECK(!argv.empty());

  // base::LaunchProcess() sets the signal mask of the child process to be the
  // same one as the parent process. ResetSigmaskDelegate will take care of that
  // and clear the child's process mask before calling execve(2).
  ResetSigmaskDelegate reset_sigmask_delegate;
  base::LaunchOptions options;
  options.pre_exec_delegate = &reset_sigmask_delegate;
  base::Process process(base::LaunchProcess(argv, std::move(options)));
  if (!process.IsValid()) {
    PLOG(ERROR) << "Failed to create a process for '"
                << base::JoinString(argv, " ") << "'";
    return false;
  }
  if (!process.WaitForExit(exit_code_out)) {
    PLOG(ERROR) << "Failed to wait for '" << base::JoinString(argv, " ")
                << "' to exit";
    return false;
  }
  return true;
}

}  // namespace login_manager
