1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_ 6 #define SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_ 7 8 #include <sys/types.h> 9 10 #include <string> 11 #include <vector> 12 13 #include "base/command_line.h" 14 #include "base/macros.h" 15 #include "base/process/launch.h" 16 #include "base/process/process.h" 17 #include "sandbox/sandbox_export.h" 18 19 namespace sandbox { 20 21 // Helper class for starting a process inside a new user, PID, and network 22 // namespace. Before using a namespace sandbox, check for namespaces support 23 // using Credentials::CanCreateProcessInNewUserNS. 24 // 25 // A typical use for "A" launching a sandboxed process "B" would be: 26 // 1. A sets up a command line and launch options for process B. 27 // 2. A launches B with LaunchProcess. 28 // 3. B should be prepared to assume the role of init(1). In particular, apart 29 // from SIGKILL and SIGSTOP, B cannot receive any signal for which it does 30 // not have an explicit signal handler registered. 31 // If B dies, all the processes in the namespace will die. 32 // B can fork() and the parent can assume the role of init(1), by using 33 // CreateInitProcessReaper(). 34 // 4. B chroots using Credentials::MoveToNewUserNS() and 35 // Credentials::DropFileSystemAccess() 36 // 5. B drops capabilities gained by entering the new user namespace with 37 // Credentials::DropAllCapabilities(). 38 class SANDBOX_EXPORT NamespaceSandbox { 39 public: 40 #if !defined(OS_NACL_NONSFI) 41 struct Options { 42 Options(); 43 ~Options(); 44 45 // Bitmask of namespace types. Must be some combination of CLONE_NEWUSER 46 // (required), CLONE_NEWPID, and CLONE_NEWNET. Defaults to all of the above. 47 int ns_types; 48 49 // Fail if any of the namespace types are not supported. Defaults to false. 50 bool fail_on_unsupported_ns_type; 51 }; 52 53 // Launch a new process inside its own user/PID/network namespaces (depending 54 // on kernel support). Requires at a minimum that user namespaces are 55 // supported (use Credentials::CanCreateProcessInNewUserNS to check this). 56 // 57 // pre_exec_delegate and clone_flags fields of LaunchOptions should be nullptr 58 // and 0, respectively, since this function makes a copy of options and 59 // overrides them. 60 static base::Process LaunchProcess(const base::CommandLine& cmdline, 61 const base::LaunchOptions& launch_options); 62 static base::Process LaunchProcess(const std::vector<std::string>& argv, 63 const base::LaunchOptions& launch_options); 64 65 // Versions which take namespace sandbox options. These allow fine grained 66 // control over the types of namespaces used. 67 static base::Process LaunchProcessWithOptions( 68 const base::CommandLine& cmdline, 69 const base::LaunchOptions& launch_options, 70 const Options& ns_sandbox_options); 71 static base::Process LaunchProcessWithOptions( 72 const std::vector<std::string>& argv, 73 const base::LaunchOptions& launch_options, 74 const Options& ns_sandbox_options); 75 #endif // !defined(OS_NACL_NONSFI) 76 77 // Forks a process in its own PID namespace. The child process is the init 78 // process inside of the PID namespace, so if the child needs to fork further, 79 // it should call CreateInitProcessReaper, which turns the init process into a 80 // reaper process. 81 // 82 // Otherwise, the child should setup handlers for signals which should 83 // terminate the process using InstallDefaultTerminationSignalHandlers or 84 // InstallTerminationSignalHandler. This works around the fact that init 85 // processes ignore such signals unless they have an explicit handler set. 86 // 87 // This function requries CAP_SYS_ADMIN. If |drop_capabilities_in_child| is 88 // true, then capabilities are dropped in the child. 89 static pid_t ForkInNewPidNamespace(bool drop_capabilities_in_child); 90 91 // Installs a signal handler for: 92 // 93 // SIGHUP, SIGINT, SIGABRT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2 94 // 95 // that exits with SignalExitCode(sig). These are signals whose default action 96 // is to terminate the program (apart from SIGILL, SIGFPE, and SIGSEGV, which 97 // will still terminate the process if e.g. an illegal instruction is 98 // encountered, etc.). 99 // 100 // If any of these already had a signal handler installed, this function will 101 // not override them. 102 static void InstallDefaultTerminationSignalHandlers(); 103 104 // Installs a signal handler for |sig| which exits with |exit_code|. If a 105 // signal handler was already present for |sig|, does nothing and returns 106 // false. 107 static bool InstallTerminationSignalHandler(int sig, int exit_code); 108 109 // Returns an exit code corresponding to the process being killed by sig. This 110 // is the same as exit code that NaCl's default signal handler uses. 111 static int SignalExitCode(int sig) { return -sig & 0xff; } 112 113 // Returns whether the namespace sandbox created a new user, PID, and network 114 // namespace. In particular, InNewUserNamespace should return true iff the 115 // process was started via this class. 116 static bool InNewUserNamespace(); 117 static bool InNewPidNamespace(); 118 static bool InNewNetNamespace(); 119 120 private: 121 DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceSandbox); 122 }; 123 124 } // namespace sandbox 125 126 #endif // SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_ 127