// Copyright 2016 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 "debugd/src/oom_adj_tool.h"

#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <sys/stat.h>
#include <unistd.h>

#include <memory>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/strings/stringprintf.h>

#include "debugd/src/process_with_output.h"

namespace debugd {

namespace {

constexpr char kProcfsDirFormat[] = "/proc/%d";
constexpr char kOomScoreAdjFileFormat[] = "/proc/%d/oom_score_adj";
constexpr char kUidMapFileFormat[] = "/proc/%d/uid_map";

// Though uid might be an unsigned int, some system call like setreuid() still
// accepts uid_t as -1 as a special invalid value. I followed the tradition in
// this file.
constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);

uid_t GetUidForUsername(const char* user_name) {
  struct passwd pwd;
  struct passwd* ppwd = nullptr;

  ssize_t buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
  if (buf_size == -1)
    buf_size = 65536;  // A random guess.
  std::unique_ptr<char[]> buf(new char[buf_size]);
  getpwnam_r(user_name, &pwd, buf.get(), buf_size, &ppwd);

  if (ppwd == nullptr)
    return kInvalidUid;

  return ppwd->pw_uid;
}

bool IsValidUid(const uid_t uid) {
  return uid != kInvalidUid;
}

// Print and collect errors.
void PrintAndAppendError(std::string* errors, const std::string& new_error) {
  LOG(WARNING) << new_error;
  *errors += new_error + "\n";
}

// A helper class to get process attributes like process owner, etc.
class ProcessHandler {
 public:
  explicit ProcessHandler(const pid_t pid);
  ~ProcessHandler() = default;

  // Get UID of the process |pid_|.
  uid_t GetProcessOwnerUid(std::string* errors);

  // Get UID of root inside the user namespace |pid_| is in.
  uid_t GetUserNamespaceRootUid(std::string* errors);

 private:
  const pid_t pid_;
};

ProcessHandler::ProcessHandler(const pid_t pid): pid_(pid) {}

uid_t ProcessHandler::GetProcessOwnerUid(std::string* errors) {
  std::string procfs_entry = base::StringPrintf(kProcfsDirFormat, pid_);
  base::ScopedFD procfs_fd(open(procfs_entry.c_str(), O_RDONLY | O_DIRECTORY));
  if (!procfs_fd.is_valid()) {
    PrintAndAppendError(
        errors,
        base::StringPrintf("Failed to open procfs entry of process %d", pid_));
    return kInvalidUid;
  }

  struct stat statbuf;
  if (fstat(procfs_fd.get(), &statbuf) < 0) {
    PrintAndAppendError(
        errors,
        base::StringPrintf("Failed to get uid of process %d", pid_));
    return kInvalidUid;
  }

  return statbuf.st_uid;
}

uid_t ProcessHandler::GetUserNamespaceRootUid(std::string* errors) {
  base::FilePath uid_map_file(base::StringPrintf(kUidMapFileFormat, pid_));
  base::ScopedFILE uid_file(base::OpenFile(uid_map_file, "r"));
  if (!uid_file) {
    PrintAndAppendError(
        errors,
        base::StringPrintf("Failed to open uid map file %s for process %d",
                           uid_map_file.value().c_str(), pid_));
    return kInvalidUid;
  }

  uid_t start, map;
  // Each line in the uid_map file specifies a 1-to-1 mapping of a range
  // of contiguous user IDs between two user namespaces. The first two numbers
  // specify the starting user ID in each of the two user namespaces. The
  // third number specifies the length of the mapped range.
  // Assume root user in the user namespace of |pid_| is mapped to the calling
  // user namespace. If not it returns kInvalidUid.
  while (fscanf(uid_file.get(), "%d%d%*d", &start, &map) == 2) {
    // Returns mapping of UID 0 = root.
    if (start == 0)
      return map;
  }
  return kInvalidUid;
}

// Batch set oom_score_adj for a list of processes. Only Chrome tabs and
// Android apps are valid target.
class OomScoreSetter {
 public:
  OomScoreSetter()
      : chronos_uid_(GetUidForUsername("chronos")),
        android_root_uid_(GetUidForUsername("android-root")) {
  }
  ~OomScoreSetter() = default;

  // Entry point.
  std::string Set(const std::map<pid_t, int32_t>& scores);

 private:
  // Sets oom_score_adj for one process.
  void SetOne(const pid_t pid, const int32_t score, std::string* errors);

  // Whether it's valid to alter OOM score of the given process |pid_|.
  bool IsValidOwner(const pid_t pid, std::string* errors);

  const uid_t chronos_uid_;
  const uid_t android_root_uid_;
};

std::string OomScoreSetter::Set(const std::map<pid_t, int32_t>& scores) {
  VLOG(2) << "UID of chronos: " << chronos_uid_;
  VLOG(2) << "UID of android-root: " << android_root_uid_;

  std::string errors;
  for (const auto& entry : scores) {
    const pid_t& pid = entry.first;
    const int32_t& score = entry.second;
    VLOG(2) << "Setting OOM score " << score << " for process " << pid;

    SetOne(pid, score, &errors);
  }
  return errors;
}

void OomScoreSetter::SetOne(
    const pid_t pid, const int32_t score, std::string* errors) {
  if (!IsValidOwner(pid, errors)) {
    PrintAndAppendError(
        errors,
        base::StringPrintf("Invalid pid %d, operation not allowed", pid));
    return;
  }

  std::string score_str = std::to_string(score);
  const size_t len = score_str.length();
  base::FilePath oom_file(base::StringPrintf(kOomScoreAdjFileFormat, pid));
  ssize_t bytes_written = base::WriteFile(oom_file, score_str.c_str(), len);

  std::string write_error;
  if (bytes_written < 0) {
    write_error = strerror(errno);
  } else if ((size_t)bytes_written != len) {
    write_error = base::StringPrintf(
        "%zd instead of %zu bytes written", bytes_written, len);
  }

  if (!write_error.empty()) {
    PrintAndAppendError(
        errors, base::StringPrintf(
            "Write %d to %s failed: %s",
            score, oom_file.value().c_str(), write_error.c_str()));
  }
}

// Returns true if
// 1. The process is owned by "chronos", or
// 2. The process is created in a user namespace where root is "android-root".
bool OomScoreSetter::IsValidOwner(const pid_t pid, std::string* errors) {
  ProcessHandler handler(pid);

  uid_t process_owner_uid = handler.GetProcessOwnerUid(errors);
  VLOG(2) << "Owner of " << pid << ": " << process_owner_uid;
  if (IsValidUid(process_owner_uid) && process_owner_uid == chronos_uid_)
    return true;

  uid_t namespace_root_uid = handler.GetUserNamespaceRootUid(errors);
  VLOG(2) << "Root of the user namespace " << pid
            << " is in: " << namespace_root_uid;
  if (IsValidUid(namespace_root_uid) && namespace_root_uid == android_root_uid_)
    return true;

  return false;
}

}  // namespace

std::string OomAdjTool::Set(const std::map<pid_t, int32_t>& scores) {
  OomScoreSetter setter;
  return setter.Set(scores);
}

}  // namespace debugd
