tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

process_util.h (9494B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 
      7 // This file/namespace contains utility functions for enumerating, ending and
      8 // computing statistics of processes.
      9 
     10 #ifndef BASE_PROCESS_UTIL_H_
     11 #define BASE_PROCESS_UTIL_H_
     12 
     13 #include "base/basictypes.h"
     14 
     15 #if defined(XP_WIN)
     16 #  include "mozilla/ipc/EnvironmentMap.h"
     17 #  include <windows.h>
     18 #  include <tlhelp32.h>
     19 #elif defined(XP_LINUX) || defined(__GLIBC__)
     20 #  include <dirent.h>
     21 #  include <limits.h>
     22 #  include <sys/types.h>
     23 #elif defined(XP_DARWIN)
     24 #  include <mach/mach.h>
     25 #endif
     26 
     27 #include <cstddef>
     28 #include <map>
     29 #include <string>
     30 #include <utility>
     31 #include <vector>
     32 
     33 #include "base/process.h"
     34 
     35 #include "mozilla/UniquePtr.h"
     36 #include "mozilla/UniquePtrExtensions.h"
     37 #include "mozilla/Result.h"
     38 #include "mozilla/ResultVariant.h"
     39 
     40 #include "mozilla/ipc/LaunchError.h"
     41 
     42 #if defined(XP_DARWIN)
     43 struct kinfo_proc;
     44 #endif
     45 
     46 class CommandLine;
     47 
     48 namespace base {
     49 
     50 using mozilla::Err;
     51 using mozilla::Ok;
     52 using mozilla::Result;
     53 using mozilla::ipc::LaunchError;
     54 
     55 enum ProcessArchitecture {
     56  PROCESS_ARCH_INVALID = 0x0,
     57  PROCESS_ARCH_I386 = 0x1,
     58  PROCESS_ARCH_X86_64 = 0x2,
     59  PROCESS_ARCH_PPC = 0x4,
     60  PROCESS_ARCH_PPC_64 = 0x8,
     61  PROCESS_ARCH_ARM = 0x10,
     62  PROCESS_ARCH_ARM_64 = 0x20
     63 };
     64 
     65 // A minimalistic but hopefully cross-platform set of exit codes.
     66 // Do not change the enumeration values or you will break third-party
     67 // installers.
     68 enum {
     69  PROCESS_END_NORMAL_TERMINATON = 0,
     70  PROCESS_END_KILLED_BY_USER = 1,
     71  PROCESS_END_PROCESS_WAS_HUNG = 2
     72 };
     73 
     74 // Returns the id of the current process.
     75 ProcessId GetCurrentProcId();
     76 
     77 // Returns the ProcessHandle of the current process.
     78 ProcessHandle GetCurrentProcessHandle();
     79 
     80 // Converts a PID to a process handle. This handle must be closed by
     81 // CloseProcessHandle when you are done with it. Returns true on success.
     82 bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle);
     83 
     84 // Converts a PID to a process handle. On Windows the handle is opened
     85 // with more access rights and must only be used by trusted code.
     86 // You have to close returned handle using CloseProcessHandle. Returns true
     87 // on success.
     88 bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle);
     89 
     90 // Closes the process handle opened by OpenProcessHandle.
     91 void CloseProcessHandle(ProcessHandle process);
     92 
     93 // Returns the unique ID for the specified process. This is functionally the
     94 // same as Windows' GetProcessId(), but works on versions of Windows before
     95 // Win XP SP1 as well.
     96 ProcessId GetProcId(ProcessHandle process);
     97 
     98 #if defined(XP_UNIX)
     99 // Close all file descriptors, except for std{in,out,err} and those
    100 // for which the given function returns true.  Only call this function
    101 // in a child process where you know that there aren't any other
    102 // threads.
    103 void CloseSuperfluousFds(void* aCtx, bool (*aShouldPreserve)(void*, int));
    104 
    105 typedef std::vector<std::pair<int, int> > file_handle_mapping_vector;
    106 typedef std::map<std::string, std::string> environment_map;
    107 
    108 // Deleter for the array of strings allocated within BuildEnvironmentArray.
    109 struct FreeEnvVarsArray {
    110  void operator()(char** array);
    111 };
    112 
    113 typedef mozilla::UniquePtr<char*[], FreeEnvVarsArray> EnvironmentArray;
    114 #endif
    115 
    116 struct LaunchOptions {
    117  // If true, wait for the process to terminate.  Otherwise, return
    118  // immediately.
    119  bool wait = false;
    120 
    121 #if defined(XP_WIN)
    122  bool start_hidden = false;
    123 
    124  // Start as an independent process rather than a process that is closed by the
    125  // parent job. This will pass the flag CREATE_BREAKAWAY_FROM_JOB.
    126  bool start_independent = false;
    127 
    128  // Environment variables to be applied in addition to the current
    129  // process's environment, replacing them where necessary.
    130  EnvironmentMap env_map;
    131 
    132  std::vector<HANDLE> handles_to_inherit;
    133 #endif
    134 #if defined(XP_UNIX)
    135  environment_map env_map;
    136 
    137  // If non-null, specifies the entire environment to use for the
    138  // child process, instead of inheriting from the parent; env_map is
    139  // ignored in that case.  Note that the strings are allocated using
    140  // malloc (e.g., with strdup), but the array of pointers is
    141  // allocated with new[] and is terminated with a null pointer.
    142  EnvironmentArray full_env;
    143 
    144  // If non-empty, set the child process's current working directory.
    145  std::string workdir;
    146 
    147  // A mapping of (src fd -> dest fd) to propagate into the child
    148  // process.  All other fds will be closed, except std{in,out,err}.
    149  file_handle_mapping_vector fds_to_remap;
    150 #endif
    151 
    152 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
    153  // These fields are used by the sandboxing code in SandboxLaunch.cpp.
    154  // It's not ideal to have them here, but trying to abstract them makes
    155  // it harder to serialize LaunchOptions for the fork server.
    156  //
    157  // (fork_flags holds extra flags for the clone() syscall, and
    158  // sandbox_chroot_server, if set, is used internally by the sandbox
    159  // to chroot() the process to an empty directory.)
    160  int fork_flags = 0;
    161  mozilla::UniqueFileHandle sandbox_chroot_server;
    162 #endif
    163 
    164 #ifdef XP_DARWIN
    165  // On macOS 10.14+, disclaims responsibility for the child process
    166  // with respect to privacy/security permission prompts and
    167  // decisions.  Ignored if not supported by the OS.
    168  bool disclaim = false;
    169 #  ifdef __aarch64__
    170  // The architecture to launch when launching a "universal" binary.
    171  // Note: the implementation only supports launching x64 child
    172  // processes from arm64 parent processes.
    173  uint32_t arch = PROCESS_ARCH_INVALID;
    174 #  endif  // __aarch64__
    175 #endif    // XP_DARWIN
    176 };
    177 
    178 #if defined(XP_WIN)
    179 // Runs the given application name with the given command line. Normally, the
    180 // first command line argument should be the path to the process, and don't
    181 // forget to quote it.
    182 //
    183 // Example (including literal quotes)
    184 //  cmdline = "c:\windows\explorer.exe" -foo "c:\bar\"
    185 //
    186 // If process_handle is non-NULL, the process handle of the launched app will be
    187 // stored there on a successful launch.
    188 // NOTE: In this case, the caller is responsible for closing the handle so
    189 //       that it doesn't leak!
    190 Result<Ok, LaunchError> LaunchApp(const std::wstring& cmdline,
    191                                  const LaunchOptions& options,
    192                                  ProcessHandle* process_handle);
    193 
    194 Result<Ok, LaunchError> LaunchApp(const CommandLine& cl, const LaunchOptions&,
    195                                  ProcessHandle* process_handle);
    196 #else
    197 // Runs the application specified in argv[0] with the command line argv.
    198 //
    199 // The pid will be stored in process_handle if that pointer is
    200 // non-null.
    201 //
    202 // Note that the first argument in argv must point to the filename,
    203 // and must be fully specified (i.e., this will not search $PATH).
    204 Result<Ok, LaunchError> LaunchApp(const std::vector<std::string>& argv,
    205                                  LaunchOptions&& options,
    206                                  ProcessHandle* process_handle);
    207 
    208 // Merge an environment map with the current environment.
    209 // Existing variables are overwritten by env_vars_to_set.
    210 EnvironmentArray BuildEnvironmentArray(const environment_map& env_vars_to_set);
    211 #endif
    212 
    213 // Attempts to kill the process identified by the given process
    214 // entry structure, giving it the specified exit code.
    215 // Returns true if this is successful, false otherwise.
    216 bool KillProcess(ProcessHandle process, int exit_code);
    217 
    218 #ifdef XP_UNIX
    219 enum class BlockingWait { No, Yes };
    220 enum class ProcessStatus { Running, Exited, Killed, Error };
    221 
    222 // Checks whether the given process has exited; returns a
    223 // `ProcessStatus` indicating whether the process is still running,
    224 // exited normally, was killed by a signal, or whether an error was
    225 // encountered (e.g., if the given process isn't a direct child of
    226 // this process).  In the `Exited` and `Killed` cases, the dead
    227 // process is collected (like `waitpid`) and the pid is freed for
    228 // potential reuse by another process.
    229 //
    230 // The value returned in `*info_out` depends on the process status:
    231 // * for `Running`, it's always set to 0
    232 // * for `Exited`, the value passed to `exit()`
    233 // * for `Killed`, the signal number
    234 // * for `Error`, the error code (like `errno`)
    235 //
    236 // If the `blocking` parameter is set to `Yes`, this function will try
    237 // to block the calling thread indefinitely until the process exits.
    238 // This may not be possible (if the child is also being debugged by
    239 // the parent process, e.g. due to the crash reporter), in which case
    240 // it will return `Running` and the caller will need to wait and retry.
    241 ProcessStatus WaitForProcess(ProcessHandle handle, BlockingWait blocking,
    242                             int* info_out);
    243 #endif
    244 
    245 }  // namespace base
    246 
    247 namespace mozilla {
    248 
    249 class EnvironmentLog {
    250 public:
    251  template <size_t N>
    252  explicit EnvironmentLog(const char (&varname)[N])
    253      : EnvironmentLog(varname, N) {}
    254 
    255  ~EnvironmentLog() {}
    256 
    257  void print(const char* format, ...);
    258 
    259 private:
    260  explicit EnvironmentLog(const char* varname, size_t len);
    261 
    262 #if defined(XP_WIN)
    263  std::wstring fname_;
    264 #else
    265  std::string fname_;
    266 #endif
    267 
    268  DISALLOW_EVIL_CONSTRUCTORS(EnvironmentLog);
    269 };
    270 
    271 }  // namespace mozilla
    272 
    273 #if defined(XP_WIN)
    274 // Undo the windows.h damage
    275 #  undef GetMessage
    276 #  undef CreateEvent
    277 #  undef GetClassName
    278 #  undef GetBinaryType
    279 #  undef RemoveDirectory
    280 #  undef LoadImage
    281 #  undef LoadIcon
    282 #endif
    283 
    284 #endif  // BASE_PROCESS_UTIL_H_