Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: sandbox/linux/suid/client/setuid_sandbox_client.cc

Issue 10807059: Refactor the setuid sandbox client code to its own class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address reviewer's comments and other minor nits. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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::ChrootMe() {
114 int fd = GetIPCDescriptor(env_);
115
116 if (fd < 0) {
117 LOG(ERROR) << "Failed to obtain the sandbox IPC descriptor";
118 return false;
119 }
120
121 if (HANDLE_EINTR(write(fd, &kMsgChrootMe, 1)) != 1) {
122 PLOG(ERROR) << "Failed to write to chroot pipe";
123 return false;
124 }
125
126 // We need to reap the chroot helper process in any event.
127 pid_t helper_pid = GetHelperPID(env_);
128 // If helper_pid is -1 we wait for any child.
129 if (waitpid(helper_pid, NULL, 0) < 0) {
130 PLOG(ERROR) << "Failed to wait for setuid helper to die";
131 return false;
132 }
133
134 char reply;
135 if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) {
136 PLOG(ERROR) << "Failed to read from chroot pipe";
137 return false;
138 }
139
140 if (reply != kMsgChrootSuccessful) {
141 LOG(ERROR) << "Error code reply from chroot helper";
142 return false;
143 }
144 return true;
145 }
146
147 bool SetuidSandboxClient::IsSuidSandboxUpToDate() const {
148 return GetHelperApi(env_) == kSUIDSandboxApiNumber;
149 }
150
151 bool SetuidSandboxClient::IsSuidSandboxChild() const {
152 return GetIPCDescriptor(env_) >= 0;
153 }
154
155 bool SetuidSandboxClient::IsInNewPIDNamespace() const {
156 return env_->HasVar(kSandboxPIDNSEnvironmentVarName);
157 }
158
159 bool SetuidSandboxClient::IsInNewNETNamespace() const {
160 return env_->HasVar(kSandboxNETNSEnvironmentVarName);
161 }
162
163 void SetuidSandboxClient::SetupLaunchEnvironment() {
164 SaveSUIDUnsafeEnvironmentVariables(env_);
165 SetSandboxAPIEnvironmentVariable(env_);
166 }
167
168 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/suid/client/setuid_sandbox_client.h ('k') | sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698