blob: d9059e9a3431b7ce6b9725fa445726e2761c6f2a [file] [log] [blame]
Yifan Hongf6b4d5c2021-06-23 19:12:32 -07001/*
2 * Copyright (C) 2021 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 "RpcRawTransport"
18#include <log/log.h>
19
Yifan Hong8c950422021-08-05 17:13:55 -070020#include <poll.h>
Frederick Mayle69a0c992022-05-26 20:38:39 +000021#include <stddef.h>
Yifan Hong8c950422021-08-05 17:13:55 -070022
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070023#include <binder/RpcTransportRaw.h>
24
Yifan Hong8c950422021-08-05 17:13:55 -070025#include "FdTrigger.h"
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070026#include "RpcState.h"
27
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070028namespace android {
29
30namespace {
31
Frederick Mayle69a0c992022-05-26 20:38:39 +000032// Linux kernel supports up to 253 (from SCM_MAX_FD) for unix sockets.
33constexpr size_t kMaxFdsPerMsg = 253;
34
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070035// RpcTransport with TLS disabled.
36class RpcTransportRaw : public RpcTransport {
37public:
38 explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
Andrei Homescu1975aaa2022-03-19 02:34:57 +000039 status_t pollRead(void) override {
40 uint8_t buf;
41 ssize_t ret = TEMP_FAILURE_RETRY(
42 ::recv(mSocket.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT));
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070043 if (ret < 0) {
Andrei Homescu5ad71b52022-03-11 03:49:12 +000044 int savedErrno = errno;
45 if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) {
46 return WOULD_BLOCK;
47 }
48
Andrei Homescu1975aaa2022-03-19 02:34:57 +000049 LOG_RPC_DETAIL("RpcTransport poll(): %s", strerror(savedErrno));
Andrei Homescu5ad71b52022-03-11 03:49:12 +000050 return -savedErrno;
Andrei Homescu1975aaa2022-03-19 02:34:57 +000051 } else if (ret == 0) {
52 return DEAD_OBJECT;
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070053 }
Andrei Homescu5ad71b52022-03-11 03:49:12 +000054
Andrei Homescu5ad71b52022-03-11 03:49:12 +000055 return OK;
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070056 }
Yifan Hong8c950422021-08-05 17:13:55 -070057
Andrei Homescua39e4ed2021-12-10 08:41:54 +000058 template <typename SendOrReceive>
Devin Moore695368f2022-06-03 22:29:14 +000059 status_t interruptableReadOrWrite(
60 FdTrigger* fdTrigger, iovec* iovs, int niovs, SendOrReceive sendOrReceiveFun,
61 const char* funName, int16_t event,
62 const std::optional<android::base::function_ref<status_t()>>& altPoll) {
Yifan Hong8c950422021-08-05 17:13:55 -070063 MAYBE_WAIT_IN_FLAKE_MODE;
64
Colin Cross9adfeaf2022-01-21 17:22:09 -080065 if (niovs < 0) {
66 return BAD_VALUE;
67 }
68
Steven Moreland301c3f02021-09-14 17:49:04 -070069 // Since we didn't poll, we need to manually check to see if it was triggered. Otherwise, we
70 // may never know we should be shutting down.
71 if (fdTrigger->isTriggered()) {
72 return DEAD_OBJECT;
73 }
74
Andrei Homescua39e4ed2021-12-10 08:41:54 +000075 // If iovs has one or more empty vectors at the end and
76 // we somehow advance past all the preceding vectors and
77 // pass some or all of the empty ones to sendmsg/recvmsg,
78 // the call will return processSize == 0. In that case
79 // we should be returning OK but instead return DEAD_OBJECT.
80 // To avoid this problem, we make sure here that the last
81 // vector at iovs[niovs - 1] has a non-zero length.
82 while (niovs > 0 && iovs[niovs - 1].iov_len == 0) {
83 niovs--;
84 }
85 if (niovs == 0) {
86 // The vectors are all empty, so we have nothing to send.
87 return OK;
88 }
89
Steven Moreland43921d52021-09-27 17:15:56 -070090 bool havePolled = false;
91 while (true) {
Frederick Mayle69a0c992022-05-26 20:38:39 +000092 ssize_t processSize = sendOrReceiveFun(iovs, niovs);
Steven Moreland301c3f02021-09-14 17:49:04 -070093 if (processSize < 0) {
Steven Moreland5252e752021-09-14 14:06:03 -070094 int savedErrno = errno;
Steven Moreland301c3f02021-09-14 17:49:04 -070095
96 // Still return the error on later passes, since it would expose
97 // a problem with polling
Andrei Homescua39e4ed2021-12-10 08:41:54 +000098 if (havePolled || (savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)) {
Steven Moreland301c3f02021-09-14 17:49:04 -070099 LOG_RPC_DETAIL("RpcTransport %s(): %s", funName, strerror(savedErrno));
100 return -savedErrno;
101 }
102 } else if (processSize == 0) {
103 return DEAD_OBJECT;
104 } else {
Andrei Homescua39e4ed2021-12-10 08:41:54 +0000105 while (processSize > 0 && niovs > 0) {
106 auto& iov = iovs[0];
107 if (static_cast<size_t>(processSize) < iov.iov_len) {
108 // Advance the base of the current iovec
109 iov.iov_base = reinterpret_cast<char*>(iov.iov_base) + processSize;
110 iov.iov_len -= processSize;
111 break;
112 }
113
114 // The current iovec was fully written
115 processSize -= iov.iov_len;
116 iovs++;
117 niovs--;
118 }
119 if (niovs == 0) {
120 LOG_ALWAYS_FATAL_IF(processSize > 0,
121 "Reached the end of iovecs "
122 "with %zd bytes remaining",
123 processSize);
Steven Moreland301c3f02021-09-14 17:49:04 -0700124 return OK;
125 }
Yifan Hong8c950422021-08-05 17:13:55 -0700126 }
127
Steven Moreland43921d52021-09-27 17:15:56 -0700128 if (altPoll) {
Devin Moore695368f2022-06-03 22:29:14 +0000129 if (status_t status = (*altPoll)(); status != OK) return status;
Steven Moreland43921d52021-09-27 17:15:56 -0700130 if (fdTrigger->isTriggered()) {
131 return DEAD_OBJECT;
132 }
133 } else {
134 if (status_t status = fdTrigger->triggerablePoll(mSocket.get(), event);
135 status != OK)
136 return status;
137 if (!havePolled) havePolled = true;
138 }
139 }
Yifan Hong8c950422021-08-05 17:13:55 -0700140 }
141
Devin Moore695368f2022-06-03 22:29:14 +0000142 status_t interruptableWriteFully(
143 FdTrigger* fdTrigger, iovec* iovs, int niovs,
Frederick Mayle69a0c992022-05-26 20:38:39 +0000144 const std::optional<android::base::function_ref<status_t()>>& altPoll,
145 const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds)
146 override {
147 bool sentFds = false;
148 auto send = [&](iovec* iovs, int niovs) -> ssize_t {
149 if (ancillaryFds != nullptr && !ancillaryFds->empty() && !sentFds) {
150 if (ancillaryFds->size() > kMaxFdsPerMsg) {
151 // This shouldn't happen because we check the FD count in RpcState.
152 ALOGE("Saw too many file descriptors in RpcTransportCtxRaw: %zu (max is %zu). "
153 "Aborting session.",
154 ancillaryFds->size(), kMaxFdsPerMsg);
155 errno = EINVAL;
156 return -1;
157 }
158
159 // CMSG_DATA is not necessarily aligned, so we copy the FDs into a buffer and then
160 // use memcpy.
161 int fds[kMaxFdsPerMsg];
162 for (size_t i = 0; i < ancillaryFds->size(); i++) {
163 fds[i] = std::visit([](const auto& fd) { return fd.get(); },
164 ancillaryFds->at(i));
165 }
166 const size_t fdsByteSize = sizeof(int) * ancillaryFds->size();
167
168 alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(int) * kMaxFdsPerMsg)];
169
170 msghdr msg{
171 .msg_iov = iovs,
172 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
173 .msg_control = msgControlBuf,
174 .msg_controllen = sizeof(msgControlBuf),
175 };
176
177 cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
178 cmsg->cmsg_level = SOL_SOCKET;
179 cmsg->cmsg_type = SCM_RIGHTS;
180 cmsg->cmsg_len = CMSG_LEN(fdsByteSize);
181 memcpy(CMSG_DATA(cmsg), fds, fdsByteSize);
182
183 msg.msg_controllen = CMSG_SPACE(fdsByteSize);
184
185 ssize_t processedSize = TEMP_FAILURE_RETRY(
186 sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
187 if (processedSize > 0) {
188 sentFds = true;
189 }
190 return processedSize;
191 }
192
193 msghdr msg{
194 .msg_iov = iovs,
195 // posix uses int, glibc uses size_t. niovs is a
196 // non-negative int and can be cast to either.
197 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
198 };
199 return TEMP_FAILURE_RETRY(sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
200 };
201 return interruptableReadOrWrite(fdTrigger, iovs, niovs, send, "sendmsg", POLLOUT, altPoll);
Steven Moreland301c3f02021-09-14 17:49:04 -0700202 }
203
Devin Moore695368f2022-06-03 22:29:14 +0000204 status_t interruptableReadFully(
205 FdTrigger* fdTrigger, iovec* iovs, int niovs,
Frederick Mayle69a0c992022-05-26 20:38:39 +0000206 const std::optional<android::base::function_ref<status_t()>>& altPoll,
207 bool enableAncillaryFds) override {
208 auto recv = [&](iovec* iovs, int niovs) -> ssize_t {
209 if (enableAncillaryFds) {
210 int fdBuffer[kMaxFdsPerMsg];
211 alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(fdBuffer))];
212
213 msghdr msg{
214 .msg_iov = iovs,
215 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
216 .msg_control = msgControlBuf,
217 .msg_controllen = sizeof(msgControlBuf),
218 };
219 ssize_t processSize =
220 TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
221 if (processSize < 0) {
222 return -1;
223 }
224
225 for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr;
226 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
227 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
228 // NOTE: It is tempting to reinterpret_cast, but cmsg(3) explicitly asks
229 // application devs to memcpy the data to ensure memory alignment.
230 size_t dataLen = cmsg->cmsg_len - CMSG_LEN(0);
231 memcpy(fdBuffer, CMSG_DATA(cmsg), dataLen);
232 size_t fdCount = dataLen / sizeof(int);
233 for (size_t i = 0; i < fdCount; i++) {
234 mFdsPendingRead.emplace_back(fdBuffer[i]);
235 }
236 break;
237 }
238 }
239
240 if (msg.msg_flags & MSG_CTRUNC) {
241 ALOGE("msg was truncated. Aborting session.");
242 errno = EPIPE;
243 return -1;
244 }
245
246 return processSize;
247 }
248 msghdr msg{
249 .msg_iov = iovs,
250 // posix uses int, glibc uses size_t. niovs is a
251 // non-negative int and can be cast to either.
252 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
253 };
254 return TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
255 };
256 return interruptableReadOrWrite(fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN, altPoll);
257 }
258
259 status_t consumePendingAncillaryData(std::vector<base::unique_fd>* fds) override {
260 fds->reserve(fds->size() + mFdsPendingRead.size());
261 for (auto& fd : mFdsPendingRead) {
262 fds->emplace_back(std::move(fd));
263 }
264 mFdsPendingRead.clear();
265 return OK;
Yifan Hong8c950422021-08-05 17:13:55 -0700266 }
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700267
268private:
Steven Moreland301c3f02021-09-14 17:49:04 -0700269 base::unique_fd mSocket;
Frederick Mayle69a0c992022-05-26 20:38:39 +0000270 std::vector<base::unique_fd> mFdsPendingRead;
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700271};
272
273// RpcTransportCtx with TLS disabled.
274class RpcTransportCtxRaw : public RpcTransportCtx {
275public:
Yifan Hongf6d42292021-08-05 23:43:05 -0700276 std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, FdTrigger*) const {
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700277 return std::make_unique<RpcTransportRaw>(std::move(fd));
278 }
Yifan Hong9734cfc2021-09-13 16:14:09 -0700279 std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700280};
Yifan Hong588d59c2021-08-16 17:13:58 -0700281
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700282} // namespace
283
284std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryRaw::newServerCtx() const {
285 return std::make_unique<RpcTransportCtxRaw>();
286}
287
288std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryRaw::newClientCtx() const {
289 return std::make_unique<RpcTransportCtxRaw>();
290}
291
292const char *RpcTransportCtxFactoryRaw::toCString() const {
293 return "raw";
294}
295
296std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryRaw::make() {
297 return std::unique_ptr<RpcTransportCtxFactoryRaw>(new RpcTransportCtxFactoryRaw());
298}
299
300} // namespace android