OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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 #include <fcntl.h> | |
6 #include <sys/stat.h> | |
7 #include <sys/types.h> | |
8 | |
9 #include "base/command_line.h" | |
10 #include "base/eintr_wrapper.h" | |
11 #include "base/logging.h" | |
12 #include "base/memory/singleton.h" | |
13 #include "content/common/sandbox_linux.h" | |
14 #include "content/common/seccomp_sandbox.h" | |
15 #include "content/public/common/content_switches.h" | |
16 #include "content/public/common/sandbox_linux.h" | |
17 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | |
18 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" | |
19 | |
20 namespace { | |
21 | |
22 // Implement the command line enabling logic for seccomp-legacy. | |
23 bool IsSeccompLegacyDesired() { | |
24 #if defined(SECCOMP_SANDBOX) | |
25 #if defined(NDEBUG) | |
26 // Off by default; allow turning on with a switch. | |
27 return CommandLine::ForCurrentProcess()->HasSwitch( | |
28 switches::kEnableSeccompSandbox); | |
29 #else | |
30 // On by default; allow turning off with a switch. | |
31 return !CommandLine::ForCurrentProcess()->HasSwitch( | |
32 switches::kDisableSeccompSandbox); | |
33 #endif // NDEBUG | |
34 #endif // SECCOMP_SANDBOX | |
35 return false; | |
36 } | |
37 | |
38 } // namespace | |
39 | |
40 namespace content { | |
41 | |
42 LinuxSandbox::LinuxSandbox() | |
43 : proc_fd_(-1), | |
44 pre_initialized_(false), | |
45 seccomp_legacy_supported_(false), | |
46 setuid_sandbox_(NULL) { | |
47 } | |
48 | |
49 LinuxSandbox::~LinuxSandbox() { | |
50 if (setuid_sandbox_) | |
51 delete setuid_sandbox_; | |
52 } | |
53 | |
54 LinuxSandbox* LinuxSandbox::GetInstance() { | |
55 LinuxSandbox* instance = Singleton<LinuxSandbox>::get(); | |
56 CHECK(instance); | |
57 instance->setuid_sandbox_ = sandbox::SetuidSandboxClient::Create(); | |
58 if (!instance->setuid_sandbox_) { | |
Jorge Lucangeli Obes
2012/08/01 22:37:50
Do we use braces around one-line if bodies?
jln (very slow on Chromium)
2012/08/01 22:48:11
The style guide has always been vague on this, and
| |
59 LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; | |
60 } | |
61 return instance; | |
62 } | |
63 | |
64 void LinuxSandbox::PreinitializeSandbox() { | |
65 CHECK(!pre_initialized_); | |
66 seccomp_legacy_supported_ = false; | |
67 #if defined(SECCOMP_SANDBOX) | |
68 if (IsSeccompLegacyDesired()) { | |
69 proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY); | |
70 if (proc_fd_ < 0) { | |
71 LOG(ERROR) << "Cannot access \"/proc\". Disabling seccomp-legacy " | |
72 "sandboxing."; | |
73 // Now is a good time to figure out if we can support seccomp sandboxing at | |
74 // all. We will call SupportsSeccompSandbox again later, when actually | |
75 // enabling it, but we allow the implementation to cache some information. | |
76 // This is the only place where we will log full lack of seccomp-legacy | |
77 // support. | |
78 } else if (!SupportsSeccompSandbox(proc_fd_)) { | |
79 VLOG(1) << "Lacking support for seccomp-legacy sandbox."; | |
80 CHECK_EQ(HANDLE_EINTR(close(proc_fd_)), 0); | |
81 proc_fd_ = -1; | |
82 } else { | |
83 seccomp_legacy_supported_ = true; | |
84 } | |
85 } | |
86 #endif // SECCOMP_SANDBOX | |
87 #if defined(SECCOMP_BPF_SANDBOX) | |
88 // Similarly, we "pre-warm" the code that detects supports for seccomp BPF. | |
89 // TODO(jln): Use proc_fd_ here too once we're comfortable it does not create | |
90 // an additional security risk. | |
91 if (playground2::Sandbox::supportsSeccompSandbox(-1) != | |
92 playground2::Sandbox::STATUS_AVAILABLE) { | |
93 VLOG(1) << "Lacking support for seccomp-bpf sandbox."; | |
94 } | |
95 #endif // SECCOMP_BPF_SANDBOX | |
96 pre_initialized_ = true; | |
97 } | |
98 | |
99 // Once we finally know our process type, we can cleanup proc_fd_ | |
100 // or pass it to seccomp-legacy. | |
101 void LinuxSandbox::PreinitializeSandboxFinish( | |
102 const std::string& process_type) { | |
103 CHECK(pre_initialized_); | |
104 if (proc_fd_ >= 0) { | |
105 if (ShouldEnableSeccompLegacy(process_type)) { | |
106 #if defined(SECCOMP_SANDBOX) | |
107 SeccompSandboxSetProcFd(proc_fd_); | |
108 #endif | |
109 } else { | |
110 DCHECK_GE(proc_fd_, 0); | |
111 CHECK_EQ(HANDLE_EINTR(close(proc_fd_)), 0); | |
112 } | |
113 proc_fd_ = -1; | |
114 } | |
115 } | |
116 | |
117 // Simplify the life of the caller if they know their process type. | |
118 void LinuxSandbox::PreinitializeSandbox(const std::string& process_type) { | |
119 PreinitializeSandbox(); | |
120 PreinitializeSandboxFinish(process_type); | |
121 } | |
122 | |
123 int LinuxSandbox::GetStatus() { | |
124 CHECK(pre_initialized_); | |
125 int sandbox_flags = 0; | |
126 if (setuid_sandbox_->IsSandboxed()) { | |
127 sandbox_flags |= kSandboxLinuxSUID; | |
128 if (setuid_sandbox_->IsInNewPIDNamespace()) | |
129 sandbox_flags |= kSandboxLinuxPIDNS; | |
130 if (setuid_sandbox_->IsInNewNETNamespace()) | |
131 sandbox_flags |= kSandboxLinuxNetNS; | |
132 } | |
133 if (seccomp_legacy_supported_) { | |
134 // Note: The current mechanism does not report if the sandbox is activated | |
135 // but only if it can be attempted. | |
136 sandbox_flags |= kSandboxLinuxSeccomp; | |
137 } | |
138 return sandbox_flags; | |
139 } | |
140 | |
141 sandbox::SetuidSandboxClient* LinuxSandbox::setuid_sandbox() { | |
142 return setuid_sandbox_; | |
143 } | |
144 | |
145 // For seccomp-legacy, we implement the policy inline, here. | |
146 bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) { | |
147 CHECK(pre_initialized_); | |
148 // Start the old seccomp mode 1 (sandbox/linux/seccomp-legacy) for renderers | |
149 // only. | |
150 if (ShouldEnableSeccompLegacy(process_type)) { | |
Jorge Lucangeli Obes
2012/08/01 22:37:50
Do we ask if we should enable even if the legacy s
jln (very slow on Chromium)
2012/08/01 22:48:11
Yes, I think that's the right way. In general my r
| |
151 // SupportsSeccompSandbox() returns a cached result, as we already | |
152 // called it earlier in the PreinitializeSandbox(). Thus, it is OK for us | |
153 // to not pass in a file descriptor for "/proc". | |
154 #if defined(SECCOMP_SANDBOX) | |
155 if (SupportsSeccompSandbox(-1)) { | |
156 StartSeccompSandbox(); | |
157 return true; | |
158 } | |
159 #endif | |
160 } | |
161 return false; | |
162 } | |
163 | |
164 // For seccomp-bpf, we will use the seccomp-bpf policy class. | |
165 // TODO(jln): implement this. | |
166 bool LinuxSandbox::StartSeccompBpf(const std::string& process_type) { | |
167 CHECK(pre_initialized_); | |
168 NOTREACHED(); | |
169 return false; | |
170 } | |
171 | |
172 // Our "policy" on whether or not to enable seccomp-legacy. Only renderers are | |
173 // supported. | |
174 bool LinuxSandbox::ShouldEnableSeccompLegacy( | |
175 const std::string& process_type) { | |
176 CHECK(pre_initialized_); | |
177 if (IsSeccompLegacyDesired() && | |
178 seccomp_legacy_supported_ && | |
179 process_type == switches::kRendererProcess) { | |
180 return true; | |
181 } else { | |
182 return false; | |
183 } | |
184 } | |
185 | |
186 } // namespace content | |
187 | |
OLD | NEW |