OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/memory/shared_memory.h" | 5 #include "base/memory/shared_memory.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <sys/mman.h> | 9 #include <sys/mman.h> |
10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| 11 #include <sys/types.h> |
11 #include <unistd.h> | 12 #include <unistd.h> |
12 | 13 |
13 #include "base/file_util.h" | 14 #include "base/file_util.h" |
14 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/process_util.h" | 17 #include "base/process_util.h" |
17 #include "base/safe_strerror_posix.h" | 18 #include "base/safe_strerror_posix.h" |
18 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
19 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
20 #include "base/threading/platform_thread.h" | 21 #include "base/threading/platform_thread.h" |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 // private), and prevents the need for cleanup (once the last fd is closed, | 143 // private), and prevents the need for cleanup (once the last fd is closed, |
143 // it is truly freed). | 144 // it is truly freed). |
144 if (fp) { | 145 if (fp) { |
145 if (unlink(path.value().c_str())) | 146 if (unlink(path.value().c_str())) |
146 PLOG(WARNING) << "unlink"; | 147 PLOG(WARNING) << "unlink"; |
147 } | 148 } |
148 } else { | 149 } else { |
149 if (!FilePathForMemoryName(*options.name, &path)) | 150 if (!FilePathForMemoryName(*options.name, &path)) |
150 return false; | 151 return false; |
151 | 152 |
152 fp = file_util::OpenFile(path, "w+x"); | 153 // Make sure that the file is opened without any permission |
153 if (fp == NULL && options.open_existing) { | 154 // to other users on the system. |
154 // "w+" will truncate if it already exists. | 155 const mode_t kOwnerOnly = S_IRUSR | S_IWUSR; |
155 fp = file_util::OpenFile(path, "a+"); | 156 |
| 157 // First, try to create the file. |
| 158 int fd = HANDLE_EINTR( |
| 159 open(path.value().c_str(), O_RDWR | O_CREAT | O_EXCL, kOwnerOnly)); |
| 160 if (fd == -1 && options.open_existing) { |
| 161 // If this doesn't work, try and open an existing file in append mode. |
| 162 // Opening an existing file in a world writable directory has two main |
| 163 // security implications: |
| 164 // - Attackers could plant a file under their control, so ownership of |
| 165 // the file is checked below. |
| 166 // - Attackers could plant a symbolic link so that an unexpected file |
| 167 // is opened, so O_NOFOLLOW is passed to open(). |
| 168 fd = HANDLE_EINTR( |
| 169 open(path.value().c_str(), O_RDWR | O_APPEND | O_NOFOLLOW)); |
| 170 |
| 171 // Check that the current user owns the file. |
| 172 // If uid != euid, then a more complex permission model is used and this |
| 173 // API is not appropriate. |
| 174 const uid_t real_uid = getuid(); |
| 175 const uid_t effective_uid = geteuid(); |
| 176 struct stat sb; |
| 177 if (fd >= 0 && |
| 178 (fstat(fd, &sb) != 0 || sb.st_uid != real_uid || |
| 179 sb.st_uid != effective_uid)) { |
| 180 LOG(ERROR) << |
| 181 "Invalid owner when opening existing shared memory file."; |
| 182 HANDLE_EINTR(close(fd)); |
| 183 return false; |
| 184 } |
| 185 |
| 186 // An existing file was opened, so its size should not be fixed. |
156 fix_size = false; | 187 fix_size = false; |
157 } | 188 } |
| 189 fp = NULL; |
| 190 if (fd >= 0) { |
| 191 // "a+" is always appropriate: if it's a new file, a+ is similar to w+. |
| 192 fp = fdopen(fd, "a+"); |
| 193 } |
158 } | 194 } |
159 if (fp && fix_size) { | 195 if (fp && fix_size) { |
160 // Get current size. | 196 // Get current size. |
161 struct stat stat; | 197 struct stat stat; |
162 if (fstat(fileno(fp), &stat) != 0) { | 198 if (fstat(fileno(fp), &stat) != 0) { |
163 file_util::CloseFile(fp); | 199 file_util::CloseFile(fp); |
164 return false; | 200 return false; |
165 } | 201 } |
166 const size_t current_size = stat.st_size; | 202 const size_t current_size = stat.st_size; |
167 if (current_size != options.size) { | 203 if (current_size != options.size) { |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 new_handle->fd = new_fd; | 415 new_handle->fd = new_fd; |
380 new_handle->auto_close = true; | 416 new_handle->auto_close = true; |
381 | 417 |
382 if (close_self) | 418 if (close_self) |
383 Close(); | 419 Close(); |
384 | 420 |
385 return true; | 421 return true; |
386 } | 422 } |
387 | 423 |
388 } // namespace base | 424 } // namespace base |
OLD | NEW |