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.
5 #include "sandbox/linux/services/namespace_sandbox.h"
16 #include "base/command_line.h"
17 #include "base/environment.h"
18 #include "base/files/scoped_file.h"
19 #include "base/logging.h"
20 #include "base/posix/eintr_wrapper.h"
21 #include "base/process/launch.h"
22 #include "base/process/process.h"
23 #include "sandbox/linux/services/namespace_utils.h"
29 class WriteUidGidMapDelegate
: public base::LaunchOptions::PreExecDelegate
{
31 WriteUidGidMapDelegate()
34 supports_deny_setgroups_(
35 NamespaceUtils::KernelSupportsDenySetgroups()) {}
37 ~WriteUidGidMapDelegate() override
{}
39 void RunAsyncSafe() override
{
40 if (supports_deny_setgroups_
) {
41 RAW_CHECK(NamespaceUtils::DenySetgroups());
43 RAW_CHECK(NamespaceUtils::WriteToIdMapFile("/proc/self/uid_map", uid_
));
44 RAW_CHECK(NamespaceUtils::WriteToIdMapFile("/proc/self/gid_map", gid_
));
50 const bool supports_deny_setgroups_
;
51 DISALLOW_COPY_AND_ASSIGN(WriteUidGidMapDelegate
);
54 void SetEnvironForNamespaceType(base::EnvironmentMap
* environ
,
55 base::NativeEnvironmentString env_var
,
57 // An empty string causes the env var to be unset in the child process.
58 (*environ
)[env_var
] = value
? "1" : "";
61 const char kSandboxUSERNSEnvironmentVarName
[] = "SBX_USER_NS";
62 const char kSandboxPIDNSEnvironmentVarName
[] = "SBX_PID_NS";
63 const char kSandboxNETNSEnvironmentVarName
[] = "SBX_NET_NS";
68 base::Process
NamespaceSandbox::LaunchProcess(
69 const base::CommandLine
& cmdline
,
70 const base::LaunchOptions
& options
) {
71 return LaunchProcess(cmdline
.argv(), options
);
75 base::Process
NamespaceSandbox::LaunchProcess(
76 const std::vector
<std::string
>& argv
,
77 const base::LaunchOptions
& options
) {
79 int ns_types
[] = {CLONE_NEWUSER
, CLONE_NEWPID
, CLONE_NEWNET
};
80 for (const int ns_type
: ns_types
) {
81 if (NamespaceUtils::KernelSupportsUnprivilegedNamespace(ns_type
)) {
82 clone_flags
|= ns_type
;
85 CHECK(clone_flags
& CLONE_NEWUSER
);
87 // These fields may not be set by the caller.
88 CHECK(options
.pre_exec_delegate
== nullptr);
89 CHECK_EQ(0, options
.clone_flags
);
91 WriteUidGidMapDelegate write_uid_gid_map_delegate
;
93 base::LaunchOptions launch_options
= options
;
94 launch_options
.pre_exec_delegate
= &write_uid_gid_map_delegate
;
95 launch_options
.clone_flags
= clone_flags
;
97 const std::pair
<int, const char*> clone_flag_environ
[] = {
98 std::make_pair(CLONE_NEWUSER
, kSandboxUSERNSEnvironmentVarName
),
99 std::make_pair(CLONE_NEWPID
, kSandboxPIDNSEnvironmentVarName
),
100 std::make_pair(CLONE_NEWNET
, kSandboxNETNSEnvironmentVarName
),
103 base::EnvironmentMap
* environ
= &launch_options
.environ
;
104 for (const auto& entry
: clone_flag_environ
) {
105 const int flag
= entry
.first
;
106 const char* environ_name
= entry
.second
;
107 SetEnvironForNamespaceType(environ
, environ_name
, clone_flags
& flag
);
110 return base::LaunchProcess(argv
, launch_options
);
114 bool NamespaceSandbox::InNewUserNamespace() {
115 return getenv(kSandboxUSERNSEnvironmentVarName
) != nullptr;
119 bool NamespaceSandbox::InNewPidNamespace() {
120 return getenv(kSandboxPIDNSEnvironmentVarName
) != nullptr;
124 bool NamespaceSandbox::InNewNetNamespace() {
125 return getenv(kSandboxNETNSEnvironmentVarName
) != nullptr;
128 } // namespace sandbox