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 "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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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. |
OLD | NEW |