OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/syscall_broker/broker_host.h" | 5 #include "sandbox/linux/syscall_broker/broker_host.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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 return syscall(__NR_openat, AT_FDCWD, pathname, flags, mode); | 52 return syscall(__NR_openat, AT_FDCWD, pathname, flags, mode); |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
56 // Open |requested_filename| with |flags| if allowed by our policy. | 56 // Open |requested_filename| with |flags| if allowed by our policy. |
57 // Write the syscall return value (-errno) to |write_pickle| and append | 57 // Write the syscall return value (-errno) to |write_pickle| and append |
58 // a file descriptor to |opened_files| if relevant. | 58 // a file descriptor to |opened_files| if relevant. |
59 void OpenFileForIPC(const BrokerPolicy& policy, | 59 void OpenFileForIPC(const BrokerPolicy& policy, |
60 const std::string& requested_filename, | 60 const std::string& requested_filename, |
61 int flags, | 61 int flags, |
62 Pickle* write_pickle, | 62 base::Pickle* write_pickle, |
63 std::vector<int>* opened_files) { | 63 std::vector<int>* opened_files) { |
64 DCHECK(write_pickle); | 64 DCHECK(write_pickle); |
65 DCHECK(opened_files); | 65 DCHECK(opened_files); |
66 const char* file_to_open = NULL; | 66 const char* file_to_open = NULL; |
67 bool unlink_after_open = false; | 67 bool unlink_after_open = false; |
68 const bool safe_to_open_file = policy.GetFileNameIfAllowedToOpen( | 68 const bool safe_to_open_file = policy.GetFileNameIfAllowedToOpen( |
69 requested_filename.c_str(), flags, &file_to_open, &unlink_after_open); | 69 requested_filename.c_str(), flags, &file_to_open, &unlink_after_open); |
70 | 70 |
71 if (safe_to_open_file) { | 71 if (safe_to_open_file) { |
72 CHECK(file_to_open); | 72 CHECK(file_to_open); |
(...skipping 11 matching lines...) Expand all Loading... |
84 } else { | 84 } else { |
85 write_pickle->WriteInt(-policy.denied_errno()); | 85 write_pickle->WriteInt(-policy.denied_errno()); |
86 } | 86 } |
87 } | 87 } |
88 | 88 |
89 // Perform access(2) on |requested_filename| with mode |mode| if allowed by our | 89 // Perform access(2) on |requested_filename| with mode |mode| if allowed by our |
90 // policy. Write the syscall return value (-errno) to |write_pickle|. | 90 // policy. Write the syscall return value (-errno) to |write_pickle|. |
91 void AccessFileForIPC(const BrokerPolicy& policy, | 91 void AccessFileForIPC(const BrokerPolicy& policy, |
92 const std::string& requested_filename, | 92 const std::string& requested_filename, |
93 int mode, | 93 int mode, |
94 Pickle* write_pickle) { | 94 base::Pickle* write_pickle) { |
95 DCHECK(write_pickle); | 95 DCHECK(write_pickle); |
96 const char* file_to_access = NULL; | 96 const char* file_to_access = NULL; |
97 const bool safe_to_access_file = policy.GetFileNameIfAllowedToAccess( | 97 const bool safe_to_access_file = policy.GetFileNameIfAllowedToAccess( |
98 requested_filename.c_str(), mode, &file_to_access); | 98 requested_filename.c_str(), mode, &file_to_access); |
99 | 99 |
100 if (safe_to_access_file) { | 100 if (safe_to_access_file) { |
101 CHECK(file_to_access); | 101 CHECK(file_to_access); |
102 int access_ret = access(file_to_access, mode); | 102 int access_ret = access(file_to_access, mode); |
103 int access_errno = errno; | 103 int access_errno = errno; |
104 if (!access_ret) | 104 if (!access_ret) |
105 write_pickle->WriteInt(0); | 105 write_pickle->WriteInt(0); |
106 else | 106 else |
107 write_pickle->WriteInt(-access_errno); | 107 write_pickle->WriteInt(-access_errno); |
108 } else { | 108 } else { |
109 write_pickle->WriteInt(-policy.denied_errno()); | 109 write_pickle->WriteInt(-policy.denied_errno()); |
110 } | 110 } |
111 } | 111 } |
112 | 112 |
113 // Handle a |command_type| request contained in |iter| and send the reply | 113 // Handle a |command_type| request contained in |iter| and send the reply |
114 // on |reply_ipc|. | 114 // on |reply_ipc|. |
115 // Currently COMMAND_OPEN and COMMAND_ACCESS are supported. | 115 // Currently COMMAND_OPEN and COMMAND_ACCESS are supported. |
116 bool HandleRemoteCommand(const BrokerPolicy& policy, | 116 bool HandleRemoteCommand(const BrokerPolicy& policy, |
117 IPCCommand command_type, | 117 IPCCommand command_type, |
118 int reply_ipc, | 118 int reply_ipc, |
119 PickleIterator iter) { | 119 base::PickleIterator iter) { |
120 // Currently all commands have two arguments: filename and flags. | 120 // Currently all commands have two arguments: filename and flags. |
121 std::string requested_filename; | 121 std::string requested_filename; |
122 int flags = 0; | 122 int flags = 0; |
123 if (!iter.ReadString(&requested_filename) || !iter.ReadInt(&flags)) | 123 if (!iter.ReadString(&requested_filename) || !iter.ReadInt(&flags)) |
124 return false; | 124 return false; |
125 | 125 |
126 Pickle write_pickle; | 126 base::Pickle write_pickle; |
127 std::vector<int> opened_files; | 127 std::vector<int> opened_files; |
128 | 128 |
129 switch (command_type) { | 129 switch (command_type) { |
130 case COMMAND_ACCESS: | 130 case COMMAND_ACCESS: |
131 AccessFileForIPC(policy, requested_filename, flags, &write_pickle); | 131 AccessFileForIPC(policy, requested_filename, flags, &write_pickle); |
132 break; | 132 break; |
133 case COMMAND_OPEN: | 133 case COMMAND_OPEN: |
134 OpenFileForIPC( | 134 OpenFileForIPC( |
135 policy, requested_filename, flags, &write_pickle, &opened_files); | 135 policy, requested_filename, flags, &write_pickle, &opened_files); |
136 break; | 136 break; |
137 default: | 137 default: |
138 LOG(ERROR) << "Invalid IPC command"; | 138 LOG(ERROR) << "Invalid IPC command"; |
139 break; | 139 break; |
140 } | 140 } |
141 | 141 |
142 CHECK_LE(write_pickle.size(), kMaxMessageLength); | 142 CHECK_LE(write_pickle.size(), kMaxMessageLength); |
143 ssize_t sent = UnixDomainSocket::SendMsg( | 143 ssize_t sent = base::UnixDomainSocket::SendMsg( |
144 reply_ipc, write_pickle.data(), write_pickle.size(), opened_files); | 144 reply_ipc, write_pickle.data(), write_pickle.size(), opened_files); |
145 | 145 |
146 // Close anything we have opened in this process. | 146 // Close anything we have opened in this process. |
147 for (std::vector<int>::iterator it = opened_files.begin(); | 147 for (std::vector<int>::iterator it = opened_files.begin(); |
148 it != opened_files.end(); | 148 it != opened_files.end(); |
149 ++it) { | 149 ++it) { |
150 int ret = IGNORE_EINTR(close(*it)); | 150 int ret = IGNORE_EINTR(close(*it)); |
151 DCHECK(!ret) << "Could not close file descriptor"; | 151 DCHECK(!ret) << "Could not close file descriptor"; |
152 } | 152 } |
153 | 153 |
(...skipping 15 matching lines...) Expand all Loading... |
169 } | 169 } |
170 | 170 |
171 // Handle a request on the IPC channel ipc_channel_. | 171 // Handle a request on the IPC channel ipc_channel_. |
172 // A request should have a file descriptor attached on which we will reply and | 172 // A request should have a file descriptor attached on which we will reply and |
173 // that we will then close. | 173 // that we will then close. |
174 // A request should start with an int that will be used as the command type. | 174 // A request should start with an int that will be used as the command type. |
175 BrokerHost::RequestStatus BrokerHost::HandleRequest() const { | 175 BrokerHost::RequestStatus BrokerHost::HandleRequest() const { |
176 ScopedVector<base::ScopedFD> fds; | 176 ScopedVector<base::ScopedFD> fds; |
177 char buf[kMaxMessageLength]; | 177 char buf[kMaxMessageLength]; |
178 errno = 0; | 178 errno = 0; |
179 const ssize_t msg_len = | 179 const ssize_t msg_len = base::UnixDomainSocket::RecvMsg( |
180 UnixDomainSocket::RecvMsg(ipc_channel_.get(), buf, sizeof(buf), &fds); | 180 ipc_channel_.get(), buf, sizeof(buf), &fds); |
181 | 181 |
182 if (msg_len == 0 || (msg_len == -1 && errno == ECONNRESET)) { | 182 if (msg_len == 0 || (msg_len == -1 && errno == ECONNRESET)) { |
183 // EOF from the client, or the client died, we should die. | 183 // EOF from the client, or the client died, we should die. |
184 return RequestStatus::LOST_CLIENT; | 184 return RequestStatus::LOST_CLIENT; |
185 } | 185 } |
186 | 186 |
187 // The client should send exactly one file descriptor, on which we | 187 // The client should send exactly one file descriptor, on which we |
188 // will write the reply. | 188 // will write the reply. |
189 // TODO(mdempsky): ScopedVector doesn't have 'at()', only 'operator[]'. | 189 // TODO(mdempsky): ScopedVector doesn't have 'at()', only 'operator[]'. |
190 if (msg_len < 0 || fds.size() != 1 || fds[0]->get() < 0) { | 190 if (msg_len < 0 || fds.size() != 1 || fds[0]->get() < 0) { |
191 PLOG(ERROR) << "Error reading message from the client"; | 191 PLOG(ERROR) << "Error reading message from the client"; |
192 return RequestStatus::FAILURE; | 192 return RequestStatus::FAILURE; |
193 } | 193 } |
194 | 194 |
195 base::ScopedFD temporary_ipc(fds[0]->Pass()); | 195 base::ScopedFD temporary_ipc(fds[0]->Pass()); |
196 | 196 |
197 Pickle pickle(buf, msg_len); | 197 base::Pickle pickle(buf, msg_len); |
198 PickleIterator iter(pickle); | 198 base::PickleIterator iter(pickle); |
199 int command_type; | 199 int command_type; |
200 if (iter.ReadInt(&command_type)) { | 200 if (iter.ReadInt(&command_type)) { |
201 bool command_handled = false; | 201 bool command_handled = false; |
202 // Go through all the possible IPC messages. | 202 // Go through all the possible IPC messages. |
203 switch (command_type) { | 203 switch (command_type) { |
204 case COMMAND_ACCESS: | 204 case COMMAND_ACCESS: |
205 case COMMAND_OPEN: | 205 case COMMAND_OPEN: |
206 // We reply on the file descriptor sent to us via the IPC channel. | 206 // We reply on the file descriptor sent to us via the IPC channel. |
207 command_handled = HandleRemoteCommand( | 207 command_handled = HandleRemoteCommand( |
208 broker_policy_, static_cast<IPCCommand>(command_type), | 208 broker_policy_, static_cast<IPCCommand>(command_type), |
(...skipping 13 matching lines...) Expand all Loading... |
222 NOTREACHED(); | 222 NOTREACHED(); |
223 } | 223 } |
224 | 224 |
225 LOG(ERROR) << "Error parsing IPC request"; | 225 LOG(ERROR) << "Error parsing IPC request"; |
226 return RequestStatus::FAILURE; | 226 return RequestStatus::FAILURE; |
227 } | 227 } |
228 | 228 |
229 } // namespace syscall_broker | 229 } // namespace syscall_broker |
230 | 230 |
231 } // namespace sandbox | 231 } // namespace sandbox |
OLD | NEW |