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