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

Side by Side Diff: sandbox/linux/services/broker_process.cc

Issue 23619009: Do not use O_CLOEXEC for open() in the broker process. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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
« no previous file with comments | « no previous file | sandbox/linux/services/broker_process_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "sandbox/linux/services/broker_process.h" 5 #include "sandbox/linux/services/broker_process.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <sys/socket.h> 8 #include <sys/socket.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <sys/syscall.h> 10 #include <sys/syscall.h>
(...skipping 25 matching lines...) Expand all
36 // O_CLOEXEC is tricky because in theory another thread could call execve() 36 // O_CLOEXEC is tricky because in theory another thread could call execve()
37 // before special treatment is made on the client, so a client needs to call 37 // before special treatment is made on the client, so a client needs to call
38 // recvmsg(2) with MSG_CMSG_CLOEXEC. 38 // recvmsg(2) with MSG_CMSG_CLOEXEC.
39 // To make things worse, there are two CLOEXEC related flags, FD_CLOEXEC (see 39 // To make things worse, there are two CLOEXEC related flags, FD_CLOEXEC (see
40 // F_GETFD in fcntl(2)) and O_CLOEXEC (see F_GETFL in fcntl(2)). O_CLOEXEC 40 // F_GETFD in fcntl(2)) and O_CLOEXEC (see F_GETFL in fcntl(2)). O_CLOEXEC
41 // doesn't affect the semantics on execve(), it's merely a note that the 41 // doesn't affect the semantics on execve(), it's merely a note that the
42 // descriptor was originally opened with O_CLOEXEC as a flag. And it is sent 42 // descriptor was originally opened with O_CLOEXEC as a flag. And it is sent
43 // over unix sockets just fine, so a receiver that would (incorrectly) look at 43 // over unix sockets just fine, so a receiver that would (incorrectly) look at
44 // O_CLOEXEC instead of FD_CLOEXEC may be tricked in thinking that the file 44 // O_CLOEXEC instead of FD_CLOEXEC may be tricked in thinking that the file
45 // descriptor will or won't be closed on execve(). 45 // descriptor will or won't be closed on execve().
46 // Since we have to account for buggy userland (see crbug.com/237283), we will
47 // open(2) the file with O_CLOEXEC in the broker process if necessary, in
48 // addition to calling recvmsg(2) with MSG_CMSG_CLOEXEC.
49 static const int kCurrentProcessOpenFlagsMask = O_CLOEXEC; 46 static const int kCurrentProcessOpenFlagsMask = O_CLOEXEC;
50 47
51 // Check whether |requested_filename| is in |allowed_file_names|. 48 // Check whether |requested_filename| is in |allowed_file_names|.
52 // See GetFileNameIfAllowedToOpen() for an explanation of |file_to_open|. 49 // See GetFileNameIfAllowedToOpen() for an explanation of |file_to_open|.
53 // async signal safe if |file_to_open| is NULL. 50 // async signal safe if |file_to_open| is NULL.
54 // TODO(jln): assert signal safety. 51 // TODO(jln): assert signal safety.
55 bool GetFileNameInWhitelist(const std::vector<std::string>& allowed_file_names, 52 bool GetFileNameInWhitelist(const std::vector<std::string>& allowed_file_names,
56 const char* requested_filename, 53 const char* requested_filename,
57 const char** file_to_open) { 54 const char** file_to_open) {
58 if (file_to_open && *file_to_open) { 55 if (file_to_open && *file_to_open) {
(...skipping 15 matching lines...) Expand all
74 return true; 71 return true;
75 } 72 }
76 } 73 }
77 return false; 74 return false;
78 } 75 }
79 76
80 // We maintain a list of flags that have been reviewed for "sanity" and that 77 // We maintain a list of flags that have been reviewed for "sanity" and that
81 // we're ok to allow in the broker. 78 // we're ok to allow in the broker.
82 // I.e. here is where we wouldn't add O_RESET_FILE_SYSTEM. 79 // I.e. here is where we wouldn't add O_RESET_FILE_SYSTEM.
83 bool IsAllowedOpenFlags(int flags) { 80 bool IsAllowedOpenFlags(int flags) {
84 // First, check the access mode 81 // First, check the access mode.
85 const int access_mode = flags & O_ACCMODE; 82 const int access_mode = flags & O_ACCMODE;
86 if (access_mode != O_RDONLY && access_mode != O_WRONLY && 83 if (access_mode != O_RDONLY && access_mode != O_WRONLY &&
87 access_mode != O_RDWR) { 84 access_mode != O_RDWR) {
88 return false; 85 return false;
89 } 86 }
90 87
91 // We only support a 2-parameters open, so we forbid O_CREAT. 88 // We only support a 2-parameters open, so we forbid O_CREAT.
92 if (flags & O_CREAT) { 89 if (flags & O_CREAT) {
93 return false; 90 return false;
94 } 91 }
95 92
96 // Some flags affect the behavior of the current process. We don't support 93 // Some flags affect the behavior of the current process. We don't support
97 // them and don't allow them for now. 94 // them and don't allow them for now.
98 if (flags & kCurrentProcessOpenFlagsMask) { 95 if (flags & kCurrentProcessOpenFlagsMask)
99 // We make an exception for O_CLOEXEC. Buggy userland could check for 96 return false;
100 // O_CLOEXEC and the only way to set it is to originally open with this
101 // flag. See the comment around kCurrentProcessOpenFlagsMask.
102 if (!(flags & O_CLOEXEC))
103 return false;
104 }
105 97
106 // Now check that all the flags are known to us. 98 // Now check that all the flags are known to us.
107 const int creation_and_status_flags = flags & ~O_ACCMODE; 99 const int creation_and_status_flags = flags & ~O_ACCMODE;
108 100
109 const int known_flags = 101 const int known_flags =
110 O_APPEND | O_ASYNC | O_CLOEXEC | O_CREAT | O_DIRECT | 102 O_APPEND | O_ASYNC | O_CLOEXEC | O_CREAT | O_DIRECT |
111 O_DIRECTORY | O_EXCL | O_LARGEFILE | O_NOATIME | O_NOCTTY | 103 O_DIRECTORY | O_EXCL | O_LARGEFILE | O_NOATIME | O_NOCTTY |
112 O_NOFOLLOW | O_NONBLOCK | O_NDELAY | O_SYNC | O_TRUNC; 104 O_NOFOLLOW | O_NONBLOCK | O_NDELAY | O_SYNC | O_TRUNC;
113 105
114 const int unknown_flags = ~known_flags; 106 const int unknown_flags = ~known_flags;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 return -EFAULT; 202 return -EFAULT;
211 203
212 // For this "remote system call" to work, we need to handle any flag that 204 // For this "remote system call" to work, we need to handle any flag that
213 // cannot be sent over a Unix socket in a special way. 205 // cannot be sent over a Unix socket in a special way.
214 // See the comments around kCurrentProcessOpenFlagsMask. 206 // See the comments around kCurrentProcessOpenFlagsMask.
215 if (syscall_type == kCommandOpen && (flags & kCurrentProcessOpenFlagsMask)) { 207 if (syscall_type == kCommandOpen && (flags & kCurrentProcessOpenFlagsMask)) {
216 // This implementation only knows about O_CLOEXEC, someone needs to look at 208 // This implementation only knows about O_CLOEXEC, someone needs to look at
217 // this code if other flags are added. 209 // this code if other flags are added.
218 RAW_CHECK(kCurrentProcessOpenFlagsMask == O_CLOEXEC); 210 RAW_CHECK(kCurrentProcessOpenFlagsMask == O_CLOEXEC);
219 recvmsg_flags |= MSG_CMSG_CLOEXEC; 211 recvmsg_flags |= MSG_CMSG_CLOEXEC;
212 flags &= ~O_CLOEXEC;
220 } 213 }
221 214
222 // There is no point in forwarding a request that we know will be denied. 215 // There is no point in forwarding a request that we know will be denied.
223 // Of course, the real security check needs to be on the other side of the 216 // Of course, the real security check needs to be on the other side of the
224 // IPC. 217 // IPC.
225 if (fast_check_in_client_) { 218 if (fast_check_in_client_) {
226 if (syscall_type == kCommandOpen && 219 if (syscall_type == kCommandOpen &&
227 !GetFileNameIfAllowedToOpen(pathname, flags, NULL)) { 220 !GetFileNameIfAllowedToOpen(pathname, flags, NULL)) {
228 return -EPERM; 221 return -EPERM;
229 } 222 }
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 GetFileNameInWhitelist(allowed_w_files_, requested_filename, 506 GetFileNameInWhitelist(allowed_w_files_, requested_filename,
514 file_to_open); 507 file_to_open);
515 return allowed_for_read_and_write; 508 return allowed_for_read_and_write;
516 } 509 }
517 default: 510 default:
518 return false; 511 return false;
519 } 512 }
520 } 513 }
521 514
522 } // namespace sandbox. 515 } // namespace sandbox.
OLDNEW
« no previous file with comments | « no previous file | sandbox/linux/services/broker_process_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698