blob: 4777a5e0cc3fee8e7d16cbc36882bb016893fb3d [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
19#include <trusty_ipc.h>
20
21#include <binder/RpcSession.h>
22#include <binder/RpcTransportTipcTrusty.h>
23#include <log/log.h>
24
25#include "../FdTrigger.h"
26#include "../RpcState.h"
27#include "TrustyStatus.h"
28
29namespace android {
30
31namespace {
32
33// RpcTransport for Trusty.
34class RpcTransportTipcTrusty : public RpcTransport {
35public:
Pawan49d74cb2022-08-03 21:19:11 +000036 explicit RpcTransportTipcTrusty(android::TransportFd socket) : mSocket(std::move(socket)) {}
Andrei Homescu74a54452021-12-10 05:30:21 +000037 ~RpcTransportTipcTrusty() { releaseMessage(); }
38
39 status_t pollRead() override {
40 auto status = ensureMessage(false);
41 if (status != OK) {
42 return status;
43 }
44 return mHaveMessage ? OK : WOULD_BLOCK;
45 }
46
47 status_t interruptableWriteFully(
48 FdTrigger* fdTrigger, iovec* iovs, int niovs,
49 const std::optional<android::base::function_ref<status_t()>>& altPoll,
50 const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds)
51 override {
52 if (niovs < 0) {
53 return BAD_VALUE;
54 }
55
56 size_t size = 0;
57 for (int i = 0; i < niovs; i++) {
58 size += iovs[i].iov_len;
59 }
60
61 ipc_msg_t msg{
62 .num_iov = static_cast<uint32_t>(niovs),
63 .iov = iovs,
64 .num_handles = 0, // TODO: add ancillaryFds
65 .handles = nullptr,
66 };
Pawan49d74cb2022-08-03 21:19:11 +000067 ssize_t rc = send_msg(mSocket.fd.get(), &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +000068 if (rc == ERR_NOT_ENOUGH_BUFFER) {
69 // Peer is blocked, wait until it unblocks.
70 // TODO: when tipc supports a send-unblocked handler,
71 // save the message here in a queue and retry it asynchronously
72 // when the handler gets called by the library
73 uevent uevt;
74 do {
Pawan49d74cb2022-08-03 21:19:11 +000075 rc = ::wait(mSocket.fd.get(), &uevt, INFINITE_TIME);
Andrei Homescu74a54452021-12-10 05:30:21 +000076 if (rc < 0) {
77 return statusFromTrusty(rc);
78 }
79 if (uevt.event & IPC_HANDLE_POLL_HUP) {
80 return DEAD_OBJECT;
81 }
82 } while (!(uevt.event & IPC_HANDLE_POLL_SEND_UNBLOCKED));
83
84 // Retry the send, it should go through this time because
85 // sending is now unblocked
Pawan49d74cb2022-08-03 21:19:11 +000086 rc = send_msg(mSocket.fd.get(), &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +000087 }
88 if (rc < 0) {
89 return statusFromTrusty(rc);
90 }
91 LOG_ALWAYS_FATAL_IF(static_cast<size_t>(rc) != size,
Andrei Homescub14d3e52022-08-02 22:57:15 +000092 "Sent the wrong number of bytes %zd!=%zu", rc, size);
Andrei Homescu74a54452021-12-10 05:30:21 +000093
94 return OK;
95 }
96
97 status_t interruptableReadFully(
98 FdTrigger* fdTrigger, iovec* iovs, int niovs,
99 const std::optional<android::base::function_ref<status_t()>>& altPoll,
100 std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override {
101 if (niovs < 0) {
102 return BAD_VALUE;
103 }
104
105 // If iovs has one or more empty vectors at the end and
106 // we somehow advance past all the preceding vectors and
107 // pass some or all of the empty ones to sendmsg/recvmsg,
108 // the call will return processSize == 0. In that case
109 // we should be returning OK but instead return DEAD_OBJECT.
110 // To avoid this problem, we make sure here that the last
111 // vector at iovs[niovs - 1] has a non-zero length.
112 while (niovs > 0 && iovs[niovs - 1].iov_len == 0) {
113 niovs--;
114 }
115 if (niovs == 0) {
116 // The vectors are all empty, so we have nothing to read.
117 return OK;
118 }
119
120 while (true) {
121 auto status = ensureMessage(true);
122 if (status != OK) {
123 return status;
124 }
125
126 ipc_msg_t msg{
127 .num_iov = static_cast<uint32_t>(niovs),
128 .iov = iovs,
129 .num_handles = 0, // TODO: support ancillaryFds
130 .handles = nullptr,
131 };
Pawan49d74cb2022-08-03 21:19:11 +0000132 ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +0000133 if (rc < 0) {
134 return statusFromTrusty(rc);
135 }
136
137 size_t processSize = static_cast<size_t>(rc);
138 mMessageOffset += processSize;
139 LOG_ALWAYS_FATAL_IF(mMessageOffset > mMessageInfo.len,
140 "Message offset exceeds length %zu/%zu", mMessageOffset,
141 mMessageInfo.len);
142
143 // Release the message if all of it has been read
144 if (mMessageOffset == mMessageInfo.len) {
145 releaseMessage();
146 }
147
148 while (processSize > 0 && niovs > 0) {
149 auto& iov = iovs[0];
150 if (processSize < iov.iov_len) {
151 // Advance the base of the current iovec
152 iov.iov_base = reinterpret_cast<char*>(iov.iov_base) + processSize;
153 iov.iov_len -= processSize;
154 break;
155 }
156
157 // The current iovec was fully written
158 processSize -= iov.iov_len;
159 iovs++;
160 niovs--;
161 }
162 if (niovs == 0) {
163 LOG_ALWAYS_FATAL_IF(processSize > 0,
164 "Reached the end of iovecs "
165 "with %zd bytes remaining",
166 processSize);
167 return OK;
168 }
169 }
170 }
171
Pawan49d74cb2022-08-03 21:19:11 +0000172 bool isWaiting() override { return mSocket.isInPollingState(); }
173
Andrei Homescu74a54452021-12-10 05:30:21 +0000174private:
175 status_t ensureMessage(bool wait) {
176 int rc;
177 if (mHaveMessage) {
178 LOG_ALWAYS_FATAL_IF(mMessageOffset >= mMessageInfo.len, "No data left in message");
179 return OK;
180 }
181
182 /* TODO: interruptible wait, maybe with a timeout??? */
183 uevent uevt;
Pawan49d74cb2022-08-03 21:19:11 +0000184 rc = ::wait(mSocket.fd.get(), &uevt, wait ? INFINITE_TIME : 0);
Andrei Homescu74a54452021-12-10 05:30:21 +0000185 if (rc < 0) {
186 if (rc == ERR_TIMED_OUT && !wait) {
187 // If we timed out with wait==false, then there's no message
188 return OK;
189 }
190 return statusFromTrusty(rc);
191 }
192 if (!(uevt.event & IPC_HANDLE_POLL_MSG)) {
193 /* No message, terminate here and leave mHaveMessage false */
194 return OK;
195 }
196
Pawan49d74cb2022-08-03 21:19:11 +0000197 rc = get_msg(mSocket.fd.get(), &mMessageInfo);
Andrei Homescu74a54452021-12-10 05:30:21 +0000198 if (rc < 0) {
199 return statusFromTrusty(rc);
200 }
201
202 mHaveMessage = true;
203 mMessageOffset = 0;
204 return OK;
205 }
206
207 void releaseMessage() {
208 if (mHaveMessage) {
Pawan49d74cb2022-08-03 21:19:11 +0000209 put_msg(mSocket.fd.get(), mMessageInfo.id);
Andrei Homescu74a54452021-12-10 05:30:21 +0000210 mHaveMessage = false;
211 }
212 }
213
Pawan49d74cb2022-08-03 21:19:11 +0000214 android::TransportFd mSocket;
Andrei Homescu74a54452021-12-10 05:30:21 +0000215
216 bool mHaveMessage = false;
217 ipc_msg_info mMessageInfo;
218 size_t mMessageOffset;
219};
220
221// RpcTransportCtx for Trusty.
222class RpcTransportCtxTipcTrusty : public RpcTransportCtx {
223public:
Pawan49d74cb2022-08-03 21:19:11 +0000224 std::unique_ptr<RpcTransport> newTransport(android::TransportFd socket,
Andrei Homescu74a54452021-12-10 05:30:21 +0000225 FdTrigger*) const override {
Pawan49d74cb2022-08-03 21:19:11 +0000226 return std::make_unique<RpcTransportTipcTrusty>(std::move(socket));
Andrei Homescu74a54452021-12-10 05:30:21 +0000227 }
228 std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
229};
230
231} // namespace
232
233std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newServerCtx() const {
234 return std::make_unique<RpcTransportCtxTipcTrusty>();
235}
236
237std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newClientCtx() const {
238 return std::make_unique<RpcTransportCtxTipcTrusty>();
239}
240
241const char* RpcTransportCtxFactoryTipcTrusty::toCString() const {
242 return "trusty";
243}
244
245std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTipcTrusty::make() {
246 return std::unique_ptr<RpcTransportCtxFactoryTipcTrusty>(
247 new RpcTransportCtxFactoryTipcTrusty());
248}
249
250} // namespace android