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 <sys/types.h> | |
6 #include <sys/wait.h> | |
7 | |
8 #include "base/eintr_wrapper.h" | |
9 #include "base/environment.h" | |
10 #include "base/logging.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/string_number_conversions.h" | |
13 | |
14 #include "sandbox/linux/suid/common/sandbox.h" | |
15 #include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h" | |
16 #include "setuid_sandbox_client.h" | |
17 | |
18 namespace { | |
19 | |
20 // Set an environment variable that reflects the API version we expect from the | |
21 // setuid sandbox. Old versions of the sandbox will ignore this. | |
22 void SetSandboxAPIEnvironmentVariable(base::Environment* env) { | |
23 env->SetVar(sandbox::kSandboxEnvironmentApiRequest, | |
24 base::IntToString(sandbox::kSUIDSandboxApiNumber)); | |
25 } | |
26 | |
27 // Wrapper around a shared C function. | |
28 // Returns the "saved" environment variable name corresponding to |envvar| | |
29 // in a new string or NULL. | |
30 std::string* CreateSavedVariableName(const char* envvar) { | |
31 char* const saved_env_var = SandboxSavedEnvironmentVariable(envvar); | |
32 if (!saved_env_var) | |
33 return NULL; | |
34 std::string* saved_env_var_copy = new std::string(saved_env_var); | |
35 // SandboxSavedEnvironmentVariable is the C function that we wrap and uses | |
36 // malloc() to allocate memory. | |
37 free(saved_env_var); | |
38 return saved_env_var_copy; | |
39 } | |
40 | |
41 // The ELF loader will clear many environment variables so we save them to | |
42 // different names here so that the SUID sandbox can resolve them for the | |
43 // renderer. | |
44 void SaveSUIDUnsafeEnvironmentVariables(base::Environment* env) { | |
45 for (unsigned i = 0; kSUIDUnsafeEnvironmentVariables[i]; ++i) { | |
46 const char* const env_var = kSUIDUnsafeEnvironmentVariables[i]; | |
47 // Get the saved environment variable corresponding to envvar. | |
48 scoped_ptr<std::string> saved_env_var(CreateSavedVariableName(env_var)); | |
49 if (saved_env_var == NULL) | |
50 continue; | |
51 | |
52 std::string value; | |
53 if (env->GetVar(env_var, &value)) | |
54 env->SetVar(saved_env_var->c_str(), value); | |
55 else | |
56 env->UnSetVar(saved_env_var->c_str()); | |
57 } | |
58 } | |
59 | |
60 int GetHelperApi(base::Environment* env) { | |
61 std::string api_string; | |
62 int api_number = 0; // Assume API version 0 if no environment was found. | |
63 if (env->GetVar(sandbox::kSandboxEnvironmentApiProvides, &api_string) && | |
64 !base::StringToInt(api_string, &api_number)) { | |
65 // It's an error if we could not convert the API number. | |
66 api_number = -1; | |
67 } | |
68 return api_number; | |
69 } | |
70 | |
71 // Convert |var_name| from the environment |env| to an int. | |
72 // Return -1 if the variable does not exist or the value cannot be converted. | |
73 int EnvToInt(base::Environment* env, const char* var_name) { | |
74 std::string var_string; | |
75 int var_value = -1; | |
76 if (env->GetVar(var_name, &var_string) && | |
77 !base::StringToInt(var_string, &var_value)) { | |
78 var_value = -1; | |
79 } | |
80 return var_value; | |
81 } | |
82 | |
83 pid_t GetHelperPID(base::Environment* env) { | |
84 return EnvToInt(env, sandbox::kSandboxHelperPidEnvironmentVarName); | |
85 } | |
86 | |
87 // Get the IPC file descriptor used to communicate with the setuid helper. | |
88 int GetIPCDescriptor(base::Environment* env) { | |
89 return EnvToInt(env, sandbox::kSandboxDescriptorEnvironmentVarName); | |
90 } | |
91 | |
92 } // namespace | |
93 | |
94 namespace sandbox { | |
95 | |
96 SetuidSandboxClient* SetuidSandboxClient::Create() { | |
97 base::Environment* environment(base::Environment::Create()); | |
98 SetuidSandboxClient* sandbox_client(new(SetuidSandboxClient)); | |
99 | |
100 CHECK(environment); | |
101 sandbox_client->env_ = environment; | |
102 return sandbox_client; | |
103 } | |
104 | |
105 SetuidSandboxClient::SetuidSandboxClient() { | |
106 env_ = NULL; | |
107 } | |
108 | |
109 SetuidSandboxClient::~SetuidSandboxClient() { | |
110 delete env_; | |
111 } | |
112 | |
113 bool SetuidSandboxClient::IsSuidSandboxChild() const { | |
114 return GetIPCDescriptor(env_) >= 0; | |
115 } | |
116 | |
117 bool SetuidSandboxClient::IsSuidSandboxUpToDate() const { | |
118 return GetHelperApi(env_) == kSUIDSandboxApiNumber; | |
119 } | |
120 | |
121 bool SetuidSandboxClient::IsInNewPIDNamespace() const { | |
122 return env_->HasVar(kSandboxPIDNSEnvironmentVarName); | |
123 } | |
124 | |
125 bool SetuidSandboxClient::IsInNewNETNamespace() const { | |
126 return env_->HasVar(kSandboxNETNSEnvironmentVarName); | |
127 } | |
128 | |
129 bool SetuidSandboxClient::ChrootMe() { | |
130 int fd = GetIPCDescriptor(env_); | |
131 | |
132 if (fd < 0) { | |
133 LOG(ERROR) << "Failed to obtain the sandbox IPC descriptor"; | |
134 return false; | |
135 } | |
136 | |
137 if (HANDLE_EINTR(write(fd, &kMsgChrootMe, 1)) != 1) { | |
138 LOG(ERROR) << "Failed to write to chroot pipe: " << errno; | |
Jorge Lucangeli Obes
2012/07/23 20:23:50
PLOG(ERROR)?
jln (very slow on Chromium)
2012/07/23 21:32:15
Done.
| |
139 return false; | |
140 } | |
141 | |
142 // We need to reap the chroot helper process in any event. | |
143 pid_t helper_pid = GetHelperPID(env_); | |
144 // If helper_pid is -1 we wait for any child. | |
145 if (waitpid(helper_pid, NULL, 0) < 0) { | |
146 LOG(ERROR) << "Failed to wait for setuid helper to die " << errno; | |
Jorge Lucangeli Obes
2012/07/23 20:23:50
PLOG
jln (very slow on Chromium)
2012/07/23 21:32:15
Done.
| |
147 return false; | |
148 } | |
149 | |
150 char reply; | |
151 if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) { | |
152 LOG(ERROR) << "Failed to read from chroot pipe: " << errno; | |
Jorge Lucangeli Obes
2012/07/23 20:23:50
PLOG
jln (very slow on Chromium)
2012/07/23 21:32:15
Done.
| |
153 return false; | |
154 } | |
155 | |
156 if (reply != kMsgChrootSuccessful) { | |
157 LOG(ERROR) << "Error code reply from chroot helper"; | |
158 return false; | |
159 } | |
160 return true; | |
161 } | |
162 | |
163 void SetuidSandboxClient::SetupLaunchEnvironment() { | |
164 SaveSUIDUnsafeEnvironmentVariables(env_); | |
165 SetSandboxAPIEnvironmentVariable(env_); | |
166 } | |
167 | |
168 } // namespace sandbox | |
OLD | NEW |