blob: 0b67b9fb12806b2a859dff7bdac5a936c56e86d2 [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:
Pawan3e0061c2022-08-26 21:08:34 +000036 explicit RpcTransportTipcTrusty(android::RpcTransportFd 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(
Andrei Homescu875996f2022-08-24 04:25:11 +000048 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*/)
Andrei Homescu74a54452021-12-10 05:30:21 +000051 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(
Andrei Homescu875996f2022-08-24 04:25:11 +000098 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*/)
101 override {
Andrei Homescu74a54452021-12-10 05:30:21 +0000102 if (niovs < 0) {
103 return BAD_VALUE;
104 }
105
106 // If iovs has one or more empty vectors at the end and
107 // we somehow advance past all the preceding vectors and
108 // pass some or all of the empty ones to sendmsg/recvmsg,
109 // the call will return processSize == 0. In that case
110 // we should be returning OK but instead return DEAD_OBJECT.
111 // To avoid this problem, we make sure here that the last
112 // vector at iovs[niovs - 1] has a non-zero length.
113 while (niovs > 0 && iovs[niovs - 1].iov_len == 0) {
114 niovs--;
115 }
116 if (niovs == 0) {
117 // The vectors are all empty, so we have nothing to read.
118 return OK;
119 }
120
121 while (true) {
122 auto status = ensureMessage(true);
123 if (status != OK) {
124 return status;
125 }
126
127 ipc_msg_t msg{
128 .num_iov = static_cast<uint32_t>(niovs),
129 .iov = iovs,
130 .num_handles = 0, // TODO: support ancillaryFds
131 .handles = nullptr,
132 };
Pawan49d74cb2022-08-03 21:19:11 +0000133 ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg);
Andrei Homescu74a54452021-12-10 05:30:21 +0000134 if (rc < 0) {
135 return statusFromTrusty(rc);
136 }
137
138 size_t processSize = static_cast<size_t>(rc);
139 mMessageOffset += processSize;
140 LOG_ALWAYS_FATAL_IF(mMessageOffset > mMessageInfo.len,
141 "Message offset exceeds length %zu/%zu", mMessageOffset,
142 mMessageInfo.len);
143
144 // Release the message if all of it has been read
145 if (mMessageOffset == mMessageInfo.len) {
146 releaseMessage();
147 }
148
149 while (processSize > 0 && niovs > 0) {
150 auto& iov = iovs[0];
151 if (processSize < iov.iov_len) {
152 // Advance the base of the current iovec
153 iov.iov_base = reinterpret_cast<char*>(iov.iov_base) + processSize;
154 iov.iov_len -= processSize;
155 break;
156 }
157
158 // The current iovec was fully written
159 processSize -= iov.iov_len;
160 iovs++;
161 niovs--;
162 }
163 if (niovs == 0) {
164 LOG_ALWAYS_FATAL_IF(processSize > 0,
165 "Reached the end of iovecs "
166 "with %zd bytes remaining",
167 processSize);
168 return OK;
169 }
170 }
171 }
172
Pawan49d74cb2022-08-03 21:19:11 +0000173 bool isWaiting() override { return mSocket.isInPollingState(); }
174
Andrei Homescu74a54452021-12-10 05:30:21 +0000175private:
176 status_t ensureMessage(bool wait) {
177 int rc;
178 if (mHaveMessage) {
179 LOG_ALWAYS_FATAL_IF(mMessageOffset >= mMessageInfo.len, "No data left in message");
180 return OK;
181 }
182
183 /* TODO: interruptible wait, maybe with a timeout??? */
184 uevent uevt;
Pawan49d74cb2022-08-03 21:19:11 +0000185 rc = ::wait(mSocket.fd.get(), &uevt, wait ? INFINITE_TIME : 0);
Andrei Homescu74a54452021-12-10 05:30:21 +0000186 if (rc < 0) {
187 if (rc == ERR_TIMED_OUT && !wait) {
188 // If we timed out with wait==false, then there's no message
189 return OK;
190 }
191 return statusFromTrusty(rc);
192 }
193 if (!(uevt.event & IPC_HANDLE_POLL_MSG)) {
194 /* No message, terminate here and leave mHaveMessage false */
195 return OK;
196 }
197
Pawan49d74cb2022-08-03 21:19:11 +0000198 rc = get_msg(mSocket.fd.get(), &mMessageInfo);
Andrei Homescu74a54452021-12-10 05:30:21 +0000199 if (rc < 0) {
200 return statusFromTrusty(rc);
201 }
202
203 mHaveMessage = true;
204 mMessageOffset = 0;
205 return OK;
206 }
207
208 void releaseMessage() {
209 if (mHaveMessage) {
Pawan49d74cb2022-08-03 21:19:11 +0000210 put_msg(mSocket.fd.get(), mMessageInfo.id);
Andrei Homescu74a54452021-12-10 05:30:21 +0000211 mHaveMessage = false;
212 }
213 }
214
Pawan3e0061c2022-08-26 21:08:34 +0000215 android::RpcTransportFd mSocket;
Andrei Homescu74a54452021-12-10 05:30:21 +0000216
217 bool mHaveMessage = false;
218 ipc_msg_info mMessageInfo;
219 size_t mMessageOffset;
220};
221
222// RpcTransportCtx for Trusty.
223class RpcTransportCtxTipcTrusty : public RpcTransportCtx {
224public:
Pawan3e0061c2022-08-26 21:08:34 +0000225 std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket,
Andrei Homescu74a54452021-12-10 05:30:21 +0000226 FdTrigger*) const override {
Pawan49d74cb2022-08-03 21:19:11 +0000227 return std::make_unique<RpcTransportTipcTrusty>(std::move(socket));
Andrei Homescu74a54452021-12-10 05:30:21 +0000228 }
229 std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
230};
231
232} // namespace
233
234std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newServerCtx() const {
235 return std::make_unique<RpcTransportCtxTipcTrusty>();
236}
237
238std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newClientCtx() const {
239 return std::make_unique<RpcTransportCtxTipcTrusty>();
240}
241
242const char* RpcTransportCtxFactoryTipcTrusty::toCString() const {
243 return "trusty";
244}
245
246std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTipcTrusty::make() {
247 return std::unique_ptr<RpcTransportCtxFactoryTipcTrusty>(
248 new RpcTransportCtxFactoryTipcTrusty());
249}
250
251} // namespace android