// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// 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 "base/cxx17_backports.h"
#include "base/logging.h"
#include "base/mac/mach_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, base::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),
            base::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, base::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, base::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
