// Copyright (c) 2014 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/child_job.h"

#include <algorithm>
#include <memory>
#include <vector>

#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>  // For exit code defines (EX__MAX, etc).
#include <sys/types.h>
#include <unistd.h>

#include <base/logging.h>
#include <base/posix/file_descriptor_shuffle.h>
#include <base/process/launch.h>
#include <base/time/time.h>

#include "login_manager/session_manager_service.h"
#include "login_manager/system_utils.h"

namespace login_manager {

namespace {

bool GetGroupInfo(uid_t uid, gid_t* gid_out, std::vector<gid_t>* groups_out) {
  DCHECK(gid_out);
  DCHECK(groups_out);
  // 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;
  }
  *gid_out = 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
  // groups_out, then call getgrouplist() for realz.
  int ngroups = 0;
  CHECK_EQ(getgrouplist(pwd->pw_name, pwd->pw_gid, nullptr, &ngroups), -1);
  groups_out->resize(ngroups, pwd->pw_gid);
  int actual_ngroups =
      getgrouplist(pwd->pw_name, pwd->pw_gid, groups_out->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.";
    groups_out->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 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;
}

}  // namespace

const int ChildJobInterface::kCantSetUid = EX__MAX + 1;
const int ChildJobInterface::kCantSetGid = EX__MAX + 2;
const int ChildJobInterface::kCantSetGroups = EX__MAX + 3;
const int ChildJobInterface::kCantSetEnv = EX__MAX + 4;
const int ChildJobInterface::kCantExec = EX_OSERR;

ChildJobInterface::Subprocess::Subprocess(uid_t desired_uid,
                                          SystemUtils* system)
    : pid_(-1),
      desired_uid_(desired_uid),
      system_(system) {
}

ChildJobInterface::Subprocess::~Subprocess() {}

// The reason that this method looks complex is because it's doing a
// bunch of work to keep the code between fork() and exec/exit simple
// and mostly async signal safe. This is because using fork() in a
// multithreaded process can create a child with inconsistent state
// (e.g. locks held by other threads remain locked). While glibc
// generally handles this gracefully internally, other libs are not as
// reliable (including base).
bool ChildJobInterface::Subprocess::ForkAndExec(
    const std::vector<std::string>& args,
    const std::vector<std::string>& env_vars) {
  gid_t gid = 0;
  std::vector<gid_t> groups;
  if (desired_uid_ != 0 && !GetGroupInfo(desired_uid_, &gid, &groups)) {
    LOG(ERROR) << "Can't get group info for " << desired_uid_;
    return false;
  }

  std::unique_ptr<char const* []> argv(new char const* [args.size() + 1]);
  for (size_t i = 0; i < args.size(); ++i)
    argv[i] = args[i].c_str();
  argv[args.size()] = 0;

  std::unique_ptr<char const* []> envp(new char const* [env_vars.size() + 1]);
  for (size_t i = 0; i < env_vars.size(); ++i)
    envp[i] = env_vars[i].c_str();
  envp[env_vars.size()] = 0;

  // The browser should not inherit FDs other than stdio, stdin and stdout,
  // including the logging FD. base::CloseSuperfluousFds() can do this, but
  // it takes a map of FDs to keep open, and creating this map requires
  // allocating memory in a way which is not safe to do after forking, so do it
  // up here in the parent.
  base::InjectiveMultimap saved_fds;
  saved_fds.push_back(base::InjectionArc(STDIN_FILENO, STDIN_FILENO, false));
  saved_fds.push_back(base::InjectionArc(STDOUT_FILENO, STDOUT_FILENO, false));
  saved_fds.push_back(base::InjectionArc(STDERR_FILENO, STDERR_FILENO, false));

  // TODO(cmasone): Block signals here, so they're blocked in the child from
  // the get-go. http://crbug.com/493161
  pid_ = system_->fork();
  if (pid_ == 0) {
    SessionManagerService::RevertHandlers();
    // We try to set our UID/GID to the desired UID, and then exec
    // the command passed in.
    if (desired_uid_ != 0) {
      int exit_code = SetIDs(desired_uid_, gid, groups);
      if (exit_code)
        _exit(exit_code);
    }
    base::CloseSuperfluousFds(saved_fds);

    execve(argv[0],
           const_cast<char* const*>(argv.get()),
           const_cast<char* const*>(envp.get()));

    // Should never get here, unless we couldn't exec the command.
    RAW_LOG(ERROR, "Error executing...");
    RAW_LOG(ERROR, argv[0]);
    _exit(errno == E2BIG ? kCantSetEnv : kCantExec);
    return false;  // To make the compiler happy.
  }
  return pid_ > 0;
}

void ChildJobInterface::Subprocess::KillEverything(int signal) {
  DCHECK_GT(pid_, 0);
  system_->kill(-pid_, desired_uid_, signal);
}

void ChildJobInterface::Subprocess::Kill(int signal) {
  DCHECK_GT(pid_, 0);
  system_->kill(pid_, desired_uid_, signal);
}

};  // namespace login_manager
