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

Side by Side Diff: platform.cc

Issue 2645008: Update on feedback, update dbus API, add unit tests. TEST=manual,unit,BVT BUG=3628 323 (Closed) Base URL: ssh://git@chromiumos-git/cryptohome.git
Patch Set: Address second round of feedback. Created 10 years, 6 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
« no previous file with comments | « platform.h ('k') | secure_blob.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009-2010 The Chromium OS 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 // Contains the implementation of class Platform
6
7 #include "platform.h"
8
9 #include <errno.h>
10 #include <pwd.h>
11 #include <signal.h>
12 #include <sys/mount.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15
16 #include <base/file_util.h>
17 #include <base/string_util.h>
18
19 // Included last to avoid redefinition problems
20 extern "C" {
21 #include <keyutils.h>
22 }
23
24 using std::string;
25
26 namespace cryptohome {
27
28 const int kDefaultMountOptions = MS_NOEXEC | MS_NOSUID | MS_NODEV;
29 const int kDefaultPwnameLength = 1024;
30 const int kDefaultUmask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH
31 | S_IXOTH;
32 const std::string kMtab = "/etc/mtab";
33 const std::string kProcDir = "/proc";
34
35 Platform::Platform()
36 : mount_options_(kDefaultMountOptions),
37 umask_(kDefaultUmask),
38 mtab_file_(kMtab),
39 proc_dir_(kProcDir) {
40 }
41
42 Platform::~Platform() {
43 }
44
45 bool Platform::IsDirectoryMounted(const std::string& directory) {
46 // Trivial string match from /etc/mtab to see if the cryptohome mount point is
47 // listed. This works because Chrome OS is a controlled environment and the
48 // only way /home/chronos/user should be mounted is if cryptohome mounted it.
49 string contents;
50 if (file_util::ReadFileToString(FilePath(mtab_file_), &contents)) {
51 if (contents.find(StringPrintf(" %s ", directory.c_str()))
52 != string::npos) {
53 return true;
54 }
55 }
56 return false;
57 }
58
59 bool Platform::IsDirectoryMountedWith(const std::string& directory,
60 const std::string& from) {
61 // Trivial string match from /etc/mtab to see if the cryptohome mount point
62 // and the user's vault path are present. Assumes this user is mounted if it
63 // finds both. This will need to change if simultaneous login is implemented.
64 string contents;
65 if (file_util::ReadFileToString(FilePath(mtab_file_), &contents)) {
66 if ((contents.find(StringPrintf(" %s ", directory.c_str()))
67 != string::npos)
68 && (contents.find(StringPrintf("%s ",
69 from.c_str()).c_str())
70 != string::npos)) {
71 return true;
72 }
73 }
74 return false;
75 }
76
77 bool Platform::Mount(const std::string& from, const std::string& to,
78 const std::string& type,
79 const std::string& mount_options) {
80 if (mount(from.c_str(), to.c_str(), type.c_str(), mount_options_,
81 mount_options.c_str())) {
82 return false;
83 }
84 return true;
85 }
86
87 bool Platform::Unmount(const std::string& path, bool lazy, bool* was_busy) {
88 if (lazy) {
89 if (umount2(path.c_str(), MNT_DETACH)) {
90 if (was_busy) {
91 *was_busy = (errno == EBUSY);
92 }
93 return false;
94 }
95 } else {
96 if (umount(path.c_str())) {
97 if (was_busy) {
98 *was_busy = (errno == EBUSY);
99 }
100 return false;
101 }
102 }
103 if (was_busy) {
104 *was_busy = false;
105 }
106 return true;
107 }
108
109 bool Platform::TerminatePidsWithOpenFiles(const std::string& path, bool hard) {
110 std::vector<pid_t> pids;
111 LookForOpenFiles(path, &pids);
112 for (std::vector<pid_t>::iterator it = pids.begin(); it != pids.end(); it++) {
113 pid_t pid = static_cast<pid_t>(*it);
114 if (pid != getpid()) {
115 if (hard) {
116 kill(pid, SIGTERM);
117 } else {
118 kill(pid, SIGKILL);
119 }
120 }
121 }
122 return (pids.size() != 0);
123 }
124
125 void Platform::LookForOpenFiles(const std::string& path_in,
126 std::vector<pid_t>* pids) {
127 // Make sure that if we get a directory, it has a trailing separator
128 FilePath file_path(path_in);
129 file_util::EnsureEndsWithSeparator(&file_path);
130 std::string path = file_path.value();
131 bool is_directory = file_util::EndsWithSeparator(file_path);
132 std::string dir_path = (is_directory
133 ? path.substr(0, path.length() - 1)
134 : "");
135
136 // Open /proc
137 file_util::FileEnumerator proc_dir_enum(FilePath(proc_dir_), false,
138 file_util::FileEnumerator::DIRECTORIES);
139
140 int linkbuf_length = path.length();
141 std::vector<char> linkbuf(linkbuf_length);
142
143 // List PIDs in /proc
144 FilePath pid_path;
145 while (!(pid_path = proc_dir_enum.Next()).empty()) {
146 pid_t pid = static_cast<pid_t>(atoi(pid_path.BaseName().value().c_str()));
147 // Ignore PID 1 and errors
148 if (pid <= 1) {
149 continue;
150 }
151 // Open /proc/<pid>/fd
152 FilePath fd_dirpath = pid_path.Append("fd");
153
154 file_util::FileEnumerator fd_dir_enum(fd_dirpath, false,
155 file_util::FileEnumerator::FILES);
156
157 // List open file descriptors
158 FilePath fd_path;
159 while (!(fd_path = fd_dir_enum.Next()).empty()) {
160 ssize_t link_length = readlink(fd_path.value().c_str(), &linkbuf[0],
161 linkbuf.size());
162 if (link_length > 0) {
163 std::string open_file(&linkbuf[0], link_length);
164 if (open_file.length() >= path.length()) {
165 if (open_file.substr(0, path.length()).compare(path) == 0) {
166 pids->push_back(pid);
167 break;
168 }
169 } else if (is_directory && open_file.length() == dir_path.length()) {
170 if (open_file.compare(dir_path) == 0) {
171 pids->push_back(pid);
172 break;
173 }
174 }
175 }
176 }
177 }
178 }
179
180 bool Platform::TerminatePidsForUser(const uid_t uid, bool hard) {
181 std::vector<pid_t> pids;
182 GetPidsForUser(uid, &pids);
183 for (std::vector<pid_t>::iterator it = pids.begin(); it != pids.end(); it++) {
184 pid_t pid = static_cast<pid_t>(*it);
185 if (pid != getpid()) {
186 if (hard) {
187 kill(pid, SIGTERM);
188 } else {
189 kill(pid, SIGKILL);
190 }
191 }
192 }
193 return (pids.size() != 0);
194 }
195
196 void Platform::GetPidsForUser(uid_t uid, std::vector<pid_t>* pids) {
197
198 // Open /proc
199 file_util::FileEnumerator proc_dir_enum(FilePath(proc_dir_), false,
200 file_util::FileEnumerator::DIRECTORIES);
201
202
203 // List PIDs in /proc
204 FilePath pid_path;
205 while (!(pid_path = proc_dir_enum.Next()).empty()) {
206 pid_t pid = static_cast<pid_t>(atoi(pid_path.BaseName().value().c_str()));
207 if (pid <= 1) {
208 continue;
209 }
210 // Open /proc/<pid>/status
211 FilePath status_path = pid_path.Append("status");
212 string contents;
213 if (!file_util::ReadFileToString(status_path, &contents)) {
214 continue;
215 }
216
217 size_t uid_loc = contents.find("Uid:");
218 if (!uid_loc) {
219 continue;
220 }
221 uid_loc += 4;
222
223 size_t uid_end = contents.find("\n", uid_loc);
224 if (!uid_end) {
225 continue;
226 }
227
228 contents = contents.substr(uid_loc, uid_end - uid_loc);
229
230 std::vector<std::string> tokens;
231 Tokenize(contents, " \t", &tokens);
232
233 for (std::vector<std::string>::iterator it = tokens.begin();
234 it != tokens.end(); it++) {
235 std::string& value = *it;
236 if (value.length() == 0) {
237 continue;
238 }
239 uid_t check_uid = static_cast<uid_t>(atoi(value.c_str()));
240 if (check_uid == uid) {
241 pids->push_back(pid);
242 break;
243 }
244 }
245 }
246 }
247
248 bool Platform::SetOwnership(const std::string& directory, uid_t user_id,
249 gid_t group_id) {
250 if (chown(directory.c_str(), user_id, group_id)) {
251 return false;
252 }
253 return true;
254 }
255
256 int Platform::SetMask(int new_mask) {
257 return umask(new_mask);
258 }
259
260 bool Platform::GetUserId(const std::string& user, uid_t* user_id,
261 gid_t* group_id) {
262 // Load the passwd entry
263 long user_name_length = sysconf(_SC_GETPW_R_SIZE_MAX);
264 if(user_name_length == -1) {
265 user_name_length = kDefaultPwnameLength;
266 }
267 struct passwd user_info, *user_infop;
268 std::vector<char> user_name_buf(user_name_length);
269 if (getpwnam_r(user.c_str(), &user_info, &user_name_buf[0],
270 user_name_length, &user_infop)) {
271 return false;
272 }
273 *user_id = user_info.pw_uid;
274 *group_id = user_info.pw_gid;
275 return true;
276 }
277
278 void Platform::ClearUserKeyring() {
279 keyctl(KEYCTL_CLEAR, KEY_SPEC_USER_KEYRING);
280 }
281
282 } // namespace cryptohome
OLDNEW
« no previous file with comments | « platform.h ('k') | secure_blob.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698