blob: dc27eb929c782874257170547211ff64d2c5d107 [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:
36 explicit RpcTransportTipcTrusty(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
37 ~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 };
Andrei Homescub14d3e52022-08-02 22:57:15 +000067 ssize_t rc = send_msg(mSocket.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 {
75 rc = ::wait(mSocket.get(), &uevt, INFINITE_TIME);
76 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
86 rc = send_msg(mSocket.get(), &msg);
87 }
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 };
Andrei Homescub14d3e52022-08-02 22:57:15 +0000132 ssize_t rc = read_msg(mSocket.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
172private:
173 status_t ensureMessage(bool wait) {
174 int rc;
175 if (mHaveMessage) {
176 LOG_ALWAYS_FATAL_IF(mMessageOffset >= mMessageInfo.len, "No data left in message");
177 return OK;
178 }
179
180 /* TODO: interruptible wait, maybe with a timeout??? */
181 uevent uevt;
182 rc = ::wait(mSocket.get(), &uevt, wait ? INFINITE_TIME : 0);
183 if (rc < 0) {
184 if (rc == ERR_TIMED_OUT && !wait) {
185 // If we timed out with wait==false, then there's no message
186 return OK;
187 }
188 return statusFromTrusty(rc);
189 }
190 if (!(uevt.event & IPC_HANDLE_POLL_MSG)) {
191 /* No message, terminate here and leave mHaveMessage false */
192 return OK;
193 }
194
195 rc = get_msg(mSocket.get(), &mMessageInfo);
196 if (rc < 0) {
197 return statusFromTrusty(rc);
198 }
199
200 mHaveMessage = true;
201 mMessageOffset = 0;
202 return OK;
203 }
204
205 void releaseMessage() {
206 if (mHaveMessage) {
207 put_msg(mSocket.get(), mMessageInfo.id);
208 mHaveMessage = false;
209 }
210 }
211
212 base::unique_fd mSocket;
213
214 bool mHaveMessage = false;
215 ipc_msg_info mMessageInfo;
216 size_t mMessageOffset;
217};
218
219// RpcTransportCtx for Trusty.
220class RpcTransportCtxTipcTrusty : public RpcTransportCtx {
221public:
222 std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
223 FdTrigger*) const override {
224 return std::make_unique<RpcTransportTipcTrusty>(std::move(fd));
225 }
226 std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
227};
228
229} // namespace
230
231std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newServerCtx() const {
232 return std::make_unique<RpcTransportCtxTipcTrusty>();
233}
234
235std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newClientCtx() const {
236 return std::make_unique<RpcTransportCtxTipcTrusty>();
237}
238
239const char* RpcTransportCtxFactoryTipcTrusty::toCString() const {
240 return "trusty";
241}
242
243std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTipcTrusty::make() {
244 return std::unique_ptr<RpcTransportCtxFactoryTipcTrusty>(
245 new RpcTransportCtxFactoryTipcTrusty());
246}
247
248} // namespace android