//===-- ProcessLauncherPosixFork.cpp --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"

#include <climits>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>

#include <sstream>
#include <csignal>

#ifdef __ANDROID__
#include <android/api-level.h>
#define PT_TRACE_ME PTRACE_TRACEME
#endif

#if defined(__ANDROID_API__) && __ANDROID_API__ < 15
#include <linux/personality.h>
#elif defined(__linux__)
#include <sys/personality.h>
#endif

using namespace lldb;
using namespace lldb_private;

static void FixupEnvironment(Environment &env) {
#ifdef __ANDROID__
  // If there is no PATH variable specified inside the environment then set the
  // path to /system/bin. It is required because the default path used by
  // execve() is wrong on android.
  env.try_emplace("PATH", "/system/bin");
#endif
}

[[noreturn]] static void ExitWithError(int error_fd,
                                       const char *operation) {
  int err = errno;
  llvm::raw_fd_ostream os(error_fd, true);
  os << operation << " failed: " << llvm::sys::StrError(err);
  os.flush();
  _exit(1);
}

static void DisableASLRIfRequested(int error_fd, const ProcessLaunchInfo &info) {
#if defined(__linux__)
  if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) {
    const unsigned long personality_get_current = 0xffffffff;
    int value = personality(personality_get_current);
    if (value == -1)
      ExitWithError(error_fd, "personality get");

    value = personality(ADDR_NO_RANDOMIZE | value);
    if (value == -1)
      ExitWithError(error_fd, "personality set");
  }
#endif
}

static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd,
                          int flags) {
  int target_fd = llvm::sys::RetryAfterSignal(-1, ::open,
      file_spec.GetCString(), flags, 0666);

  if (target_fd == -1)
    ExitWithError(error_fd, "DupDescriptor-open");

  if (target_fd == fd)
    return;

  if (::dup2(target_fd, fd) == -1)
    ExitWithError(error_fd, "DupDescriptor-dup2");

  ::close(target_fd);
  return;
}

[[noreturn]] static void ChildFunc(int error_fd,
                                   const ProcessLaunchInfo &info) {
  if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) {
    if (setpgid(0, 0) != 0)
      ExitWithError(error_fd, "setpgid");
  }

  for (size_t i = 0; i < info.GetNumFileActions(); ++i) {
    const FileAction &action = *info.GetFileActionAtIndex(i);
    switch (action.GetAction()) {
    case FileAction::eFileActionClose:
      if (close(action.GetFD()) != 0)
        ExitWithError(error_fd, "close");
      break;
    case FileAction::eFileActionDuplicate:
      if (dup2(action.GetFD(), action.GetActionArgument()) == -1)
        ExitWithError(error_fd, "dup2");
      break;
    case FileAction::eFileActionOpen:
      DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(),
                    action.GetActionArgument());
      break;
    case FileAction::eFileActionNone:
      break;
    }
  }

  const char **argv = info.GetArguments().GetConstArgumentVector();

  // Change working directory
  if (info.GetWorkingDirectory() &&
      0 != ::chdir(info.GetWorkingDirectory().GetCString()))
    ExitWithError(error_fd, "chdir");

  DisableASLRIfRequested(error_fd, info);
  Environment env = info.GetEnvironment();
  FixupEnvironment(env);
  Environment::Envp envp = env.getEnvp();

  // Clear the signal mask to prevent the child from being affected by any
  // masking done by the parent.
  sigset_t set;
  if (sigemptyset(&set) != 0 ||
      pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0)
    ExitWithError(error_fd, "pthread_sigmask");

  if (info.GetFlags().Test(eLaunchFlagDebug)) {
    // Do not inherit setgid powers.
    if (setgid(getgid()) != 0)
      ExitWithError(error_fd, "setgid");

    // HACK:
    // Close everything besides stdin, stdout, and stderr that has no file
    // action to avoid leaking. Only do this when debugging, as elsewhere we
    // actually rely on passing open descriptors to child processes.

    const llvm::StringRef proc_fd_path = "/proc/self/fd";
    std::error_code ec;
    bool result;
    ec = llvm::sys::fs::is_directory(proc_fd_path, result);
    if (result) {
      std::vector<int> files_to_close;
      // Directory iterator doesn't ensure any sequence.
      for (llvm::sys::fs::directory_iterator iter(proc_fd_path, ec), file_end;
           iter != file_end && !ec; iter.increment(ec)) {
        int fd = std::stoi(iter->path().substr(proc_fd_path.size() + 1));

        // Don't close first three entries since they are stdin, stdout and
        // stderr.
        if (fd > 2 && !info.GetFileActionForFD(fd) && fd != error_fd)
          files_to_close.push_back(fd);
      }
      for (int file_to_close : files_to_close)
        close(file_to_close);
    } else {
      // Since /proc/self/fd didn't work, trying the slow way instead.
      int max_fd = sysconf(_SC_OPEN_MAX);
      for (int fd = 3; fd < max_fd; ++fd)
        if (!info.GetFileActionForFD(fd) && fd != error_fd)
          close(fd);
    }

    // Start tracing this child that is about to exec.
    if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1)
      ExitWithError(error_fd, "ptrace");
  }

  // Execute.  We should never return...
  execve(argv[0], const_cast<char *const *>(argv), envp);

#if defined(__linux__)
  if (errno == ETXTBSY) {
    // On android M and earlier we can get this error because the adb daemon
    // can hold a write handle on the executable even after it has finished
    // uploading it. This state lasts only a short time and happens only when
    // there are many concurrent adb commands being issued, such as when
    // running the test suite. (The file remains open when someone does an "adb
    // shell" command in the fork() child before it has had a chance to exec.)
    // Since this state should clear up quickly, wait a while and then give it
    // one more go.
    usleep(50000);
    execve(argv[0], const_cast<char *const *>(argv), envp);
  }
#endif

  // ...unless exec fails.  In which case we definitely need to end the child
  // here.
  ExitWithError(error_fd, "execve");
}

HostProcess
ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info,
                                        Status &error) {
  char exe_path[PATH_MAX];
  launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));

  // A pipe used by the child process to report errors.
  PipePosix pipe;
  const bool child_processes_inherit = false;
  error = pipe.CreateNew(child_processes_inherit);
  if (error.Fail())
    return HostProcess();

  ::pid_t pid = ::fork();
  if (pid == -1) {
    // Fork failed
    error.SetErrorStringWithFormatv("Fork failed with error message: {0}",
                                    llvm::sys::StrError());
    return HostProcess(LLDB_INVALID_PROCESS_ID);
  }
  if (pid == 0) {
    // child process
    pipe.CloseReadFileDescriptor();
    ChildFunc(pipe.ReleaseWriteFileDescriptor(), launch_info);
  }

  // parent process

  pipe.CloseWriteFileDescriptor();
  char buf[1000];
  int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf);

  if (r == 0)
    return HostProcess(pid); // No error. We're done.

  error.SetErrorString(buf);

  llvm::sys::RetryAfterSignal(-1, waitpid, pid, nullptr, 0);

  return HostProcess();
}
