// Copyright 2014 The Crashpad Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "util/posix/process_info.h"

#include <string.h>

#include <iterator>

#include "base/apple/mach_logging.h"
#include "base/check_op.h"
#include "base/logging.h"

namespace crashpad {

ProcessInfo::ProcessInfo() : kern_proc_info_(), initialized_() {
}

ProcessInfo::~ProcessInfo() {
}

bool ProcessInfo::InitializeWithPid(pid_t pid) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
  size_t len = sizeof(kern_proc_info_);
  if (sysctl(mib, std::size(mib), &kern_proc_info_, &len, nullptr, 0) != 0) {
    PLOG(ERROR) << "sysctl for pid " << pid;
    return false;
  }

  // This sysctl does not return an error if the pid was not found. 10.9.5
  // xnu-2422.115.4/bsd/kern/kern_sysctl.c sysctl_prochandle() calls
  // xnu-2422.115.4/bsd/kern/kern_proc.c proc_iterate(), which provides no
  // indication of whether anything was done. To catch this, check that the PID
  // has changed from the 0 value it was given when initialized by the
  // constructor.
  if (kern_proc_info_.kp_proc.p_pid == 0) {
    LOG(WARNING) << "pid " << pid << " not found";
    return false;
  }

  DCHECK_EQ(kern_proc_info_.kp_proc.p_pid, pid);

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

bool ProcessInfo::InitializeWithTask(task_t task) {
  pid_t pid;
  kern_return_t kr = pid_for_task(task, &pid);
  if (kr != KERN_SUCCESS) {
    MACH_LOG(ERROR, kr) << "pid_for_task";
    return false;
  }

  return InitializeWithPid(pid);
}

pid_t ProcessInfo::ProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_proc.p_pid;
}

pid_t ProcessInfo::ParentProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_eproc.e_ppid;
}

uid_t ProcessInfo::RealUserID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_eproc.e_pcred.p_ruid;
}

uid_t ProcessInfo::EffectiveUserID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_eproc.e_ucred.cr_uid;
}

uid_t ProcessInfo::SavedUserID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_eproc.e_pcred.p_svuid;
}

gid_t ProcessInfo::RealGroupID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_eproc.e_pcred.p_rgid;
}

gid_t ProcessInfo::EffectiveGroupID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_eproc.e_ucred.cr_gid;
}

gid_t ProcessInfo::SavedGroupID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_eproc.e_pcred.p_svgid;
}

std::set<gid_t> ProcessInfo::SupplementaryGroups() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  const short ngroups = kern_proc_info_.kp_eproc.e_ucred.cr_ngroups;
  DCHECK_GE(ngroups, 0);
  DCHECK_LE(static_cast<size_t>(ngroups),
            std::size(kern_proc_info_.kp_eproc.e_ucred.cr_groups));

  const gid_t* groups = kern_proc_info_.kp_eproc.e_ucred.cr_groups;
  return std::set<gid_t>(&groups[0], &groups[ngroups]);
}

std::set<gid_t> ProcessInfo::AllGroups() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::set<gid_t> all_groups = SupplementaryGroups();
  all_groups.insert(RealGroupID());
  all_groups.insert(EffectiveGroupID());
  all_groups.insert(SavedGroupID());
  return all_groups;
}

bool ProcessInfo::DidChangePrivileges() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_proc.p_flag & P_SUGID;
}

bool ProcessInfo::Is64Bit() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return kern_proc_info_.kp_proc.p_flag & P_LP64;
}

bool ProcessInfo::StartTime(timeval* start_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *start_time = kern_proc_info_.kp_proc.p_starttime;
  return true;
}

bool ProcessInfo::Arguments(std::vector<std::string>* argv) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  // The format of KERN_PROCARGS2 is explained in 10.9.2 adv_cmds-153/ps/print.c
  // getproclline(). It is an int (argc) followed by the executable’s string
  // area. The string area consists of NUL-terminated strings, beginning with
  // the executable path, and then starting on an aligned boundary, all of the
  // elements of argv, envp, and applev.

  // It is possible for a process to exec() in between the two sysctl() calls
  // below. If that happens, and the string area of the new program is larger
  // than that of the old one, args_size_estimate will be too small. To detect
  // this situation, the second sysctl() attempts to fetch args_size_estimate +
  // 1 bytes, expecting to only receive args_size_estimate. If it gets the extra
  // byte, it indicates that the string area has grown, and the sysctl() pair
  // will be retried a limited number of times.

  size_t args_size_estimate;
  size_t args_size;
  std::string args;
  int tries = 3;
  const pid_t pid = ProcessID();
  do {
    int mib[] = {CTL_KERN, KERN_PROCARGS2, pid};
    int rv =
        sysctl(mib, std::size(mib), nullptr, &args_size_estimate, nullptr, 0);
    if (rv != 0) {
      PLOG(ERROR) << "sysctl (size) for pid " << pid;
      return false;
    }

    // TODO(https://crashpad.chromium.org/bug/355): This was increased from + 1
    // to + 32 to work around a new bug in macOS 11.0db6 20A5364e that has
    // broken {CTL_KERN, KERN_PROCARGS2} such that it will not work properly
    // unless provided with a buffer at least 17 bytes larger than indicated in
    // args_size_estimate. If this bug is fixed prior to the 11.0 release,
    // remove the workaround and go back to + 1. (A positive offset is needed
    // for the reasons described above.)
    args_size = args_size_estimate + 32;
    args.resize(args_size);
    rv = sysctl(mib, std::size(mib), &args[0], &args_size, nullptr, 0);
    if (rv != 0) {
      PLOG(ERROR) << "sysctl (data) for pid " << pid;
      return false;
    }
  } while (args_size == args_size_estimate + 1 && tries--);

  if (args_size == args_size_estimate + 1) {
    LOG(ERROR) << "unexpected args_size";
    return false;
  }

  // KERN_PROCARGS2 needs to at least contain argc.
  if (args_size < sizeof(int)) {
    LOG(ERROR) << "tiny args_size";
    return false;
  }
  args.resize(args_size);

  // Get argc.
  int argc;
  memcpy(&argc, &args[0], sizeof(argc));

  // Find the end of the executable path.
  size_t start_pos = sizeof(argc);
  size_t nul_pos = args.find('\0', start_pos);
  if (nul_pos == std::string::npos) {
    LOG(ERROR) << "unterminated executable path";
    return false;
  }

  // Find the beginning of the string area.
  start_pos = args.find_first_not_of('\0', nul_pos);
  if (start_pos == std::string::npos) {
    LOG(ERROR) << "no string area";
    return false;
  }

  std::vector<std::string> local_argv;
  while (argc-- && nul_pos != std::string::npos) {
    nul_pos = args.find('\0', start_pos);
    local_argv.push_back(args.substr(start_pos, nul_pos - start_pos));
    start_pos = nul_pos + 1;
  }

  if (argc >= 0) {
    // Not every argument was recovered.
    LOG(ERROR) << "did not recover all arguments";
    return false;
  }

  argv->swap(local_argv);
  return true;
}

}  // namespace crashpad
