blob: c74ba0a65e410226c4649d4f3af0bf5328425413 [file] [log] [blame]
Andrei Homescu74a54452021-12-10 05:30:21 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "RpcTransportTipcTrusty"
18
Andrei Homescu1c18a802022-08-17 04:59:01 +000019#include <inttypes.h>
Andrei Homescu74a54452021-12-10 05:30:21 +000020#include <trusty_ipc.h>
21
22#include <binder/RpcSession.h>
23#include <binder/RpcTransportTipcTrusty.h>
24#include <log/log.h>
25
26#include "../FdTrigger.h"
27#include "../RpcState.h"
28#include "TrustyStatus.h"
29
30namespace android {
31
Tomasz Wasilczyk35804862023-10-30 14:19:19 +000032using namespace android::binder::impl;
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -070033using android::binder::borrowed_fd;
34using android::binder::unique_fd;
Tomasz Wasilczyk35804862023-10-30 14:19:19 +000035
Andrei Homescu74a54452021-12-10 05:30:21 +000036// RpcTransport for Trusty.
37class RpcTransportTipcTrusty : public RpcTransport {
38public:
Pawan3e0061c2022-08-26 21:08:34 +000039 explicit RpcTransportTipcTrusty(android::RpcTransportFd socket) : mSocket(std::move(socket)) {}
Andrei Homescu74a54452021-12-10 05:30:21 +000040 ~RpcTransportTipcTrusty() { releaseMessage(); }
41
42 status_t pollRead() override {
43 auto status = ensureMessage(false);
44 if (status != OK) {
45 return status;
46 }
47 return mHaveMessage ? OK : WOULD_BLOCK;
48 }
49
50 status_t interruptableWriteFully(
Andrei Homescu875996f2022-08-24 04:25:11 +000051 FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
Tomasz Wasilczyk35804862023-10-30 14:19:19 +000052 const std::optional<SmallFunction<status_t()>>& /*altPoll*/,
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -070053 const std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds) override {
Andrei Homescu74a54452021-12-10 05:30:21 +000054 if (niovs < 0) {
55 return BAD_VALUE;
56 }
57
58 size_t size = 0;
59 for (int i = 0; i < niovs; i++) {
60 size += iovs[i].iov_len;
61 }
62
Andrei Homescu1c18a802022-08-17 04:59:01 +000063 handle_t msgHandles[IPC_MAX_MSG_HANDLES];
Andrei Homescu74a54452021-12-10 05:30:21 +000064 ipc_msg_t msg{
65 .num_iov = static_cast<uint32_t>(niovs),
66 .iov = iovs,
Andrei Homescu1c18a802022-08-17 04:59:01 +000067 .num_handles = 0,
Andrei Homescu74a54452021-12-10 05:30:21 +000068 .handles = nullptr,
69 };
Andrei Homescu1c18a802022-08-17 04:59:01 +000070
71 if (ancillaryFds != nullptr && !ancillaryFds->empty()) {
72 if (ancillaryFds->size() > IPC_MAX_MSG_HANDLES) {
73 // This shouldn't happen because we check the FD count in RpcState.
74 ALOGE("Saw too many file descriptors in RpcTransportCtxTipcTrusty: "
75 "%zu (max is %u). Aborting session.",
76 ancillaryFds->size(), IPC_MAX_MSG_HANDLES);
77 return BAD_VALUE;
78 }
79
80 for (size_t i = 0; i < ancillaryFds->size(); i++) {
81 msgHandles[i] =
82 std::visit([](const auto& fd) { return fd.get(); }, ancillaryFds->at(i));
83 }
84
85 msg.num_handles = ancillaryFds->size();
86 msg.handles = msgHandles;
87 }
88
Pawan49d74cb2022-08-03 21:19:11 +000089 ssize_t rc = send_msg(mSocket.fd.get(), &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +000090 if (rc == ERR_NOT_ENOUGH_BUFFER) {
91 // Peer is blocked, wait until it unblocks.
92 // TODO: when tipc supports a send-unblocked handler,
93 // save the message here in a queue and retry it asynchronously
94 // when the handler gets called by the library
95 uevent uevt;
96 do {
Pawan49d74cb2022-08-03 21:19:11 +000097 rc = ::wait(mSocket.fd.get(), &uevt, INFINITE_TIME);
Andrei Homescu74a54452021-12-10 05:30:21 +000098 if (rc < 0) {
99 return statusFromTrusty(rc);
100 }
101 if (uevt.event & IPC_HANDLE_POLL_HUP) {
102 return DEAD_OBJECT;
103 }
104 } while (!(uevt.event & IPC_HANDLE_POLL_SEND_UNBLOCKED));
105
106 // Retry the send, it should go through this time because
107 // sending is now unblocked
Pawan49d74cb2022-08-03 21:19:11 +0000108 rc = send_msg(mSocket.fd.get(), &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +0000109 }
110 if (rc < 0) {
111 return statusFromTrusty(rc);
112 }
113 LOG_ALWAYS_FATAL_IF(static_cast<size_t>(rc) != size,
Andrei Homescub14d3e52022-08-02 22:57:15 +0000114 "Sent the wrong number of bytes %zd!=%zu", rc, size);
Andrei Homescu74a54452021-12-10 05:30:21 +0000115
116 return OK;
117 }
118
119 status_t interruptableReadFully(
Andrei Homescu875996f2022-08-24 04:25:11 +0000120 FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
Tomasz Wasilczyk35804862023-10-30 14:19:19 +0000121 const std::optional<SmallFunction<status_t()>>& /*altPoll*/,
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -0700122 std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds) override {
Andrei Homescu74a54452021-12-10 05:30:21 +0000123 if (niovs < 0) {
124 return BAD_VALUE;
125 }
126
127 // If iovs has one or more empty vectors at the end and
128 // we somehow advance past all the preceding vectors and
129 // pass some or all of the empty ones to sendmsg/recvmsg,
130 // the call will return processSize == 0. In that case
131 // we should be returning OK but instead return DEAD_OBJECT.
132 // To avoid this problem, we make sure here that the last
133 // vector at iovs[niovs - 1] has a non-zero length.
134 while (niovs > 0 && iovs[niovs - 1].iov_len == 0) {
135 niovs--;
136 }
137 if (niovs == 0) {
138 // The vectors are all empty, so we have nothing to read.
139 return OK;
140 }
141
142 while (true) {
143 auto status = ensureMessage(true);
144 if (status != OK) {
145 return status;
146 }
147
Andrei Homescu1c18a802022-08-17 04:59:01 +0000148 LOG_ALWAYS_FATAL_IF(mMessageInfo.num_handles > IPC_MAX_MSG_HANDLES,
149 "Received too many handles %" PRIu32, mMessageInfo.num_handles);
150 bool haveHandles = mMessageInfo.num_handles != 0;
151 handle_t msgHandles[IPC_MAX_MSG_HANDLES];
152
Andrei Homescu74a54452021-12-10 05:30:21 +0000153 ipc_msg_t msg{
154 .num_iov = static_cast<uint32_t>(niovs),
155 .iov = iovs,
Andrei Homescu1c18a802022-08-17 04:59:01 +0000156 .num_handles = mMessageInfo.num_handles,
157 .handles = haveHandles ? msgHandles : 0,
Andrei Homescu74a54452021-12-10 05:30:21 +0000158 };
Pawan49d74cb2022-08-03 21:19:11 +0000159 ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +0000160 if (rc < 0) {
161 return statusFromTrusty(rc);
162 }
163
164 size_t processSize = static_cast<size_t>(rc);
165 mMessageOffset += processSize;
166 LOG_ALWAYS_FATAL_IF(mMessageOffset > mMessageInfo.len,
167 "Message offset exceeds length %zu/%zu", mMessageOffset,
168 mMessageInfo.len);
169
Andrei Homescu1c18a802022-08-17 04:59:01 +0000170 if (haveHandles) {
171 if (ancillaryFds != nullptr) {
172 ancillaryFds->reserve(ancillaryFds->size() + mMessageInfo.num_handles);
173 for (size_t i = 0; i < mMessageInfo.num_handles; i++) {
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -0700174 ancillaryFds->emplace_back(unique_fd(msgHandles[i]));
Andrei Homescu1c18a802022-08-17 04:59:01 +0000175 }
176
177 // Clear the saved number of handles so we don't accidentally
178 // read them multiple times
179 mMessageInfo.num_handles = 0;
180 haveHandles = false;
181 } else {
182 ALOGE("Received unexpected handles %" PRIu32, mMessageInfo.num_handles);
183 // It should be safe to continue here. We could abort, but then
184 // peers could DoS us by sending messages with handles in them.
185 // Close the handles since we are ignoring them.
186 for (size_t i = 0; i < mMessageInfo.num_handles; i++) {
187 ::close(msgHandles[i]);
188 }
189 }
190 }
191
Andrei Homescu74a54452021-12-10 05:30:21 +0000192 // Release the message if all of it has been read
193 if (mMessageOffset == mMessageInfo.len) {
194 releaseMessage();
195 }
196
197 while (processSize > 0 && niovs > 0) {
198 auto& iov = iovs[0];
199 if (processSize < iov.iov_len) {
200 // Advance the base of the current iovec
201 iov.iov_base = reinterpret_cast<char*>(iov.iov_base) + processSize;
202 iov.iov_len -= processSize;
203 break;
204 }
205
206 // The current iovec was fully written
207 processSize -= iov.iov_len;
208 iovs++;
209 niovs--;
210 }
211 if (niovs == 0) {
212 LOG_ALWAYS_FATAL_IF(processSize > 0,
213 "Reached the end of iovecs "
214 "with %zd bytes remaining",
215 processSize);
216 return OK;
217 }
218 }
219 }
220
Pawan49d74cb2022-08-03 21:19:11 +0000221 bool isWaiting() override { return mSocket.isInPollingState(); }
222
Andrei Homescu74a54452021-12-10 05:30:21 +0000223private:
224 status_t ensureMessage(bool wait) {
225 int rc;
226 if (mHaveMessage) {
227 LOG_ALWAYS_FATAL_IF(mMessageOffset >= mMessageInfo.len, "No data left in message");
228 return OK;
229 }
230
231 /* TODO: interruptible wait, maybe with a timeout??? */
232 uevent uevt;
Pawan49d74cb2022-08-03 21:19:11 +0000233 rc = ::wait(mSocket.fd.get(), &uevt, wait ? INFINITE_TIME : 0);
Andrei Homescu74a54452021-12-10 05:30:21 +0000234 if (rc < 0) {
235 if (rc == ERR_TIMED_OUT && !wait) {
236 // If we timed out with wait==false, then there's no message
237 return OK;
238 }
239 return statusFromTrusty(rc);
240 }
241 if (!(uevt.event & IPC_HANDLE_POLL_MSG)) {
242 /* No message, terminate here and leave mHaveMessage false */
Andrei Homescu805ca7a2022-12-09 07:16:23 +0000243 if (uevt.event & IPC_HANDLE_POLL_HUP) {
244 // Peer closed the connection. We need to preserve the order
245 // between MSG and HUP from FdTrigger.cpp, which means that
246 // getting MSG&HUP should return OK instead of DEAD_OBJECT.
247 return DEAD_OBJECT;
248 }
Andrei Homescu74a54452021-12-10 05:30:21 +0000249 return OK;
250 }
251
Pawan49d74cb2022-08-03 21:19:11 +0000252 rc = get_msg(mSocket.fd.get(), &mMessageInfo);
Andrei Homescu74a54452021-12-10 05:30:21 +0000253 if (rc < 0) {
254 return statusFromTrusty(rc);
255 }
256
257 mHaveMessage = true;
258 mMessageOffset = 0;
259 return OK;
260 }
261
262 void releaseMessage() {
263 if (mHaveMessage) {
Pawan49d74cb2022-08-03 21:19:11 +0000264 put_msg(mSocket.fd.get(), mMessageInfo.id);
Andrei Homescu74a54452021-12-10 05:30:21 +0000265 mHaveMessage = false;
266 }
267 }
268
Pawan3e0061c2022-08-26 21:08:34 +0000269 android::RpcTransportFd mSocket;
Andrei Homescu74a54452021-12-10 05:30:21 +0000270
271 bool mHaveMessage = false;
272 ipc_msg_info mMessageInfo;
273 size_t mMessageOffset;
274};
275
276// RpcTransportCtx for Trusty.
277class RpcTransportCtxTipcTrusty : public RpcTransportCtx {
278public:
Pawan3e0061c2022-08-26 21:08:34 +0000279 std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket,
Andrei Homescu74a54452021-12-10 05:30:21 +0000280 FdTrigger*) const override {
Pawan49d74cb2022-08-03 21:19:11 +0000281 return std::make_unique<RpcTransportTipcTrusty>(std::move(socket));
Andrei Homescu74a54452021-12-10 05:30:21 +0000282 }
283 std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
284};
285
Andrei Homescu74a54452021-12-10 05:30:21 +0000286std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newServerCtx() const {
287 return std::make_unique<RpcTransportCtxTipcTrusty>();
288}
289
290std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newClientCtx() const {
291 return std::make_unique<RpcTransportCtxTipcTrusty>();
292}
293
294const char* RpcTransportCtxFactoryTipcTrusty::toCString() const {
295 return "trusty";
296}
297
298std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTipcTrusty::make() {
299 return std::unique_ptr<RpcTransportCtxFactoryTipcTrusty>(
300 new RpcTransportCtxFactoryTipcTrusty());
301}
302
303} // namespace android