blob: 6bb45e2e11113cf64a0d1fb82d61c8fa3f0deb68 [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;
33
Andrei Homescu74a54452021-12-10 05:30:21 +000034// RpcTransport for Trusty.
35class RpcTransportTipcTrusty : public RpcTransport {
36public:
Pawan3e0061c2022-08-26 21:08:34 +000037 explicit RpcTransportTipcTrusty(android::RpcTransportFd socket) : mSocket(std::move(socket)) {}
Andrei Homescu74a54452021-12-10 05:30:21 +000038 ~RpcTransportTipcTrusty() { releaseMessage(); }
39
40 status_t pollRead() override {
41 auto status = ensureMessage(false);
42 if (status != OK) {
43 return status;
44 }
45 return mHaveMessage ? OK : WOULD_BLOCK;
46 }
47
48 status_t interruptableWriteFully(
Andrei Homescu875996f2022-08-24 04:25:11 +000049 FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
Tomasz Wasilczyk35804862023-10-30 14:19:19 +000050 const std::optional<SmallFunction<status_t()>>& /*altPoll*/,
Andrei Homescu1c18a802022-08-17 04:59:01 +000051 const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds)
Andrei Homescu74a54452021-12-10 05:30:21 +000052 override {
53 if (niovs < 0) {
54 return BAD_VALUE;
55 }
56
57 size_t size = 0;
58 for (int i = 0; i < niovs; i++) {
59 size += iovs[i].iov_len;
60 }
61
Andrei Homescu1c18a802022-08-17 04:59:01 +000062 handle_t msgHandles[IPC_MAX_MSG_HANDLES];
Andrei Homescu74a54452021-12-10 05:30:21 +000063 ipc_msg_t msg{
64 .num_iov = static_cast<uint32_t>(niovs),
65 .iov = iovs,
Andrei Homescu1c18a802022-08-17 04:59:01 +000066 .num_handles = 0,
Andrei Homescu74a54452021-12-10 05:30:21 +000067 .handles = nullptr,
68 };
Andrei Homescu1c18a802022-08-17 04:59:01 +000069
70 if (ancillaryFds != nullptr && !ancillaryFds->empty()) {
71 if (ancillaryFds->size() > IPC_MAX_MSG_HANDLES) {
72 // This shouldn't happen because we check the FD count in RpcState.
73 ALOGE("Saw too many file descriptors in RpcTransportCtxTipcTrusty: "
74 "%zu (max is %u). Aborting session.",
75 ancillaryFds->size(), IPC_MAX_MSG_HANDLES);
76 return BAD_VALUE;
77 }
78
79 for (size_t i = 0; i < ancillaryFds->size(); i++) {
80 msgHandles[i] =
81 std::visit([](const auto& fd) { return fd.get(); }, ancillaryFds->at(i));
82 }
83
84 msg.num_handles = ancillaryFds->size();
85 msg.handles = msgHandles;
86 }
87
Pawan49d74cb2022-08-03 21:19:11 +000088 ssize_t rc = send_msg(mSocket.fd.get(), &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +000089 if (rc == ERR_NOT_ENOUGH_BUFFER) {
90 // Peer is blocked, wait until it unblocks.
91 // TODO: when tipc supports a send-unblocked handler,
92 // save the message here in a queue and retry it asynchronously
93 // when the handler gets called by the library
94 uevent uevt;
95 do {
Pawan49d74cb2022-08-03 21:19:11 +000096 rc = ::wait(mSocket.fd.get(), &uevt, INFINITE_TIME);
Andrei Homescu74a54452021-12-10 05:30:21 +000097 if (rc < 0) {
98 return statusFromTrusty(rc);
99 }
100 if (uevt.event & IPC_HANDLE_POLL_HUP) {
101 return DEAD_OBJECT;
102 }
103 } while (!(uevt.event & IPC_HANDLE_POLL_SEND_UNBLOCKED));
104
105 // Retry the send, it should go through this time because
106 // sending is now unblocked
Pawan49d74cb2022-08-03 21:19:11 +0000107 rc = send_msg(mSocket.fd.get(), &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +0000108 }
109 if (rc < 0) {
110 return statusFromTrusty(rc);
111 }
112 LOG_ALWAYS_FATAL_IF(static_cast<size_t>(rc) != size,
Andrei Homescub14d3e52022-08-02 22:57:15 +0000113 "Sent the wrong number of bytes %zd!=%zu", rc, size);
Andrei Homescu74a54452021-12-10 05:30:21 +0000114
115 return OK;
116 }
117
118 status_t interruptableReadFully(
Andrei Homescu875996f2022-08-24 04:25:11 +0000119 FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
Tomasz Wasilczyk35804862023-10-30 14:19:19 +0000120 const std::optional<SmallFunction<status_t()>>& /*altPoll*/,
Andrei Homescu1c18a802022-08-17 04:59:01 +0000121 std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override {
Andrei Homescu74a54452021-12-10 05:30:21 +0000122 if (niovs < 0) {
123 return BAD_VALUE;
124 }
125
126 // If iovs has one or more empty vectors at the end and
127 // we somehow advance past all the preceding vectors and
128 // pass some or all of the empty ones to sendmsg/recvmsg,
129 // the call will return processSize == 0. In that case
130 // we should be returning OK but instead return DEAD_OBJECT.
131 // To avoid this problem, we make sure here that the last
132 // vector at iovs[niovs - 1] has a non-zero length.
133 while (niovs > 0 && iovs[niovs - 1].iov_len == 0) {
134 niovs--;
135 }
136 if (niovs == 0) {
137 // The vectors are all empty, so we have nothing to read.
138 return OK;
139 }
140
141 while (true) {
142 auto status = ensureMessage(true);
143 if (status != OK) {
144 return status;
145 }
146
Andrei Homescu1c18a802022-08-17 04:59:01 +0000147 LOG_ALWAYS_FATAL_IF(mMessageInfo.num_handles > IPC_MAX_MSG_HANDLES,
148 "Received too many handles %" PRIu32, mMessageInfo.num_handles);
149 bool haveHandles = mMessageInfo.num_handles != 0;
150 handle_t msgHandles[IPC_MAX_MSG_HANDLES];
151
Andrei Homescu74a54452021-12-10 05:30:21 +0000152 ipc_msg_t msg{
153 .num_iov = static_cast<uint32_t>(niovs),
154 .iov = iovs,
Andrei Homescu1c18a802022-08-17 04:59:01 +0000155 .num_handles = mMessageInfo.num_handles,
156 .handles = haveHandles ? msgHandles : 0,
Andrei Homescu74a54452021-12-10 05:30:21 +0000157 };
Pawan49d74cb2022-08-03 21:19:11 +0000158 ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +0000159 if (rc < 0) {
160 return statusFromTrusty(rc);
161 }
162
163 size_t processSize = static_cast<size_t>(rc);
164 mMessageOffset += processSize;
165 LOG_ALWAYS_FATAL_IF(mMessageOffset > mMessageInfo.len,
166 "Message offset exceeds length %zu/%zu", mMessageOffset,
167 mMessageInfo.len);
168
Andrei Homescu1c18a802022-08-17 04:59:01 +0000169 if (haveHandles) {
170 if (ancillaryFds != nullptr) {
171 ancillaryFds->reserve(ancillaryFds->size() + mMessageInfo.num_handles);
172 for (size_t i = 0; i < mMessageInfo.num_handles; i++) {
173 ancillaryFds->emplace_back(base::unique_fd(msgHandles[i]));
174 }
175
176 // Clear the saved number of handles so we don't accidentally
177 // read them multiple times
178 mMessageInfo.num_handles = 0;
179 haveHandles = false;
180 } else {
181 ALOGE("Received unexpected handles %" PRIu32, mMessageInfo.num_handles);
182 // It should be safe to continue here. We could abort, but then
183 // peers could DoS us by sending messages with handles in them.
184 // Close the handles since we are ignoring them.
185 for (size_t i = 0; i < mMessageInfo.num_handles; i++) {
186 ::close(msgHandles[i]);
187 }
188 }
189 }
190
Andrei Homescu74a54452021-12-10 05:30:21 +0000191 // Release the message if all of it has been read
192 if (mMessageOffset == mMessageInfo.len) {
193 releaseMessage();
194 }
195
196 while (processSize > 0 && niovs > 0) {
197 auto& iov = iovs[0];
198 if (processSize < iov.iov_len) {
199 // Advance the base of the current iovec
200 iov.iov_base = reinterpret_cast<char*>(iov.iov_base) + processSize;
201 iov.iov_len -= processSize;
202 break;
203 }
204
205 // The current iovec was fully written
206 processSize -= iov.iov_len;
207 iovs++;
208 niovs--;
209 }
210 if (niovs == 0) {
211 LOG_ALWAYS_FATAL_IF(processSize > 0,
212 "Reached the end of iovecs "
213 "with %zd bytes remaining",
214 processSize);
215 return OK;
216 }
217 }
218 }
219
Pawan49d74cb2022-08-03 21:19:11 +0000220 bool isWaiting() override { return mSocket.isInPollingState(); }
221
Andrei Homescu74a54452021-12-10 05:30:21 +0000222private:
223 status_t ensureMessage(bool wait) {
224 int rc;
225 if (mHaveMessage) {
226 LOG_ALWAYS_FATAL_IF(mMessageOffset >= mMessageInfo.len, "No data left in message");
227 return OK;
228 }
229
230 /* TODO: interruptible wait, maybe with a timeout??? */
231 uevent uevt;
Pawan49d74cb2022-08-03 21:19:11 +0000232 rc = ::wait(mSocket.fd.get(), &uevt, wait ? INFINITE_TIME : 0);
Andrei Homescu74a54452021-12-10 05:30:21 +0000233 if (rc < 0) {
234 if (rc == ERR_TIMED_OUT && !wait) {
235 // If we timed out with wait==false, then there's no message
236 return OK;
237 }
238 return statusFromTrusty(rc);
239 }
240 if (!(uevt.event & IPC_HANDLE_POLL_MSG)) {
241 /* No message, terminate here and leave mHaveMessage false */
Andrei Homescu805ca7a2022-12-09 07:16:23 +0000242 if (uevt.event & IPC_HANDLE_POLL_HUP) {
243 // Peer closed the connection. We need to preserve the order
244 // between MSG and HUP from FdTrigger.cpp, which means that
245 // getting MSG&HUP should return OK instead of DEAD_OBJECT.
246 return DEAD_OBJECT;
247 }
Andrei Homescu74a54452021-12-10 05:30:21 +0000248 return OK;
249 }
250
Pawan49d74cb2022-08-03 21:19:11 +0000251 rc = get_msg(mSocket.fd.get(), &mMessageInfo);
Andrei Homescu74a54452021-12-10 05:30:21 +0000252 if (rc < 0) {
253 return statusFromTrusty(rc);
254 }
255
256 mHaveMessage = true;
257 mMessageOffset = 0;
258 return OK;
259 }
260
261 void releaseMessage() {
262 if (mHaveMessage) {
Pawan49d74cb2022-08-03 21:19:11 +0000263 put_msg(mSocket.fd.get(), mMessageInfo.id);
Andrei Homescu74a54452021-12-10 05:30:21 +0000264 mHaveMessage = false;
265 }
266 }
267
Pawan3e0061c2022-08-26 21:08:34 +0000268 android::RpcTransportFd mSocket;
Andrei Homescu74a54452021-12-10 05:30:21 +0000269
270 bool mHaveMessage = false;
271 ipc_msg_info mMessageInfo;
272 size_t mMessageOffset;
273};
274
275// RpcTransportCtx for Trusty.
276class RpcTransportCtxTipcTrusty : public RpcTransportCtx {
277public:
Pawan3e0061c2022-08-26 21:08:34 +0000278 std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket,
Andrei Homescu74a54452021-12-10 05:30:21 +0000279 FdTrigger*) const override {
Pawan49d74cb2022-08-03 21:19:11 +0000280 return std::make_unique<RpcTransportTipcTrusty>(std::move(socket));
Andrei Homescu74a54452021-12-10 05:30:21 +0000281 }
282 std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
283};
284
Andrei Homescu74a54452021-12-10 05:30:21 +0000285std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newServerCtx() const {
286 return std::make_unique<RpcTransportCtxTipcTrusty>();
287}
288
289std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newClientCtx() const {
290 return std::make_unique<RpcTransportCtxTipcTrusty>();
291}
292
293const char* RpcTransportCtxFactoryTipcTrusty::toCString() const {
294 return "trusty";
295}
296
297std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTipcTrusty::make() {
298 return std::unique_ptr<RpcTransportCtxFactoryTipcTrusty>(
299 new RpcTransportCtxFactoryTipcTrusty());
300}
301
302} // namespace android