blob: 59e6869a1e39b706acaa0a59fce1e6788abfe2c4 [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"
Andrei Homescu9b404192022-07-21 00:55:10 +000027#include "RpcTransportUtils.h"
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070028
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070029namespace android {
30
31namespace {
32
Frederick Mayle69a0c992022-05-26 20:38:39 +000033// Linux kernel supports up to 253 (from SCM_MAX_FD) for unix sockets.
34constexpr size_t kMaxFdsPerMsg = 253;
35
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070036// RpcTransport with TLS disabled.
37class RpcTransportRaw : public RpcTransport {
38public:
Pawan49d74cb2022-08-03 21:19:11 +000039 explicit RpcTransportRaw(android::TransportFd socket) : mSocket(std::move(socket)) {}
Andrei Homescu1975aaa2022-03-19 02:34:57 +000040 status_t pollRead(void) override {
41 uint8_t buf;
42 ssize_t ret = TEMP_FAILURE_RETRY(
Pawan49d74cb2022-08-03 21:19:11 +000043 ::recv(mSocket.fd.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT));
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070044 if (ret < 0) {
Andrei Homescu5ad71b52022-03-11 03:49:12 +000045 int savedErrno = errno;
46 if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) {
47 return WOULD_BLOCK;
48 }
49
Andrei Homescu1975aaa2022-03-19 02:34:57 +000050 LOG_RPC_DETAIL("RpcTransport poll(): %s", strerror(savedErrno));
Andrei Homescu5ad71b52022-03-11 03:49:12 +000051 return -savedErrno;
Andrei Homescu1975aaa2022-03-19 02:34:57 +000052 } else if (ret == 0) {
53 return DEAD_OBJECT;
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070054 }
Andrei Homescu5ad71b52022-03-11 03:49:12 +000055
Andrei Homescu5ad71b52022-03-11 03:49:12 +000056 return OK;
Yifan Hongf6b4d5c2021-06-23 19:12:32 -070057 }
Yifan Hong8c950422021-08-05 17:13:55 -070058
Devin Moore695368f2022-06-03 22:29:14 +000059 status_t interruptableWriteFully(
60 FdTrigger* fdTrigger, iovec* iovs, int niovs,
Frederick Mayle69a0c992022-05-26 20:38:39 +000061 const std::optional<android::base::function_ref<status_t()>>& altPoll,
62 const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds)
63 override {
64 bool sentFds = false;
65 auto send = [&](iovec* iovs, int niovs) -> ssize_t {
66 if (ancillaryFds != nullptr && !ancillaryFds->empty() && !sentFds) {
67 if (ancillaryFds->size() > kMaxFdsPerMsg) {
68 // This shouldn't happen because we check the FD count in RpcState.
69 ALOGE("Saw too many file descriptors in RpcTransportCtxRaw: %zu (max is %zu). "
70 "Aborting session.",
71 ancillaryFds->size(), kMaxFdsPerMsg);
72 errno = EINVAL;
73 return -1;
74 }
75
76 // CMSG_DATA is not necessarily aligned, so we copy the FDs into a buffer and then
77 // use memcpy.
78 int fds[kMaxFdsPerMsg];
79 for (size_t i = 0; i < ancillaryFds->size(); i++) {
80 fds[i] = std::visit([](const auto& fd) { return fd.get(); },
81 ancillaryFds->at(i));
82 }
83 const size_t fdsByteSize = sizeof(int) * ancillaryFds->size();
84
85 alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(int) * kMaxFdsPerMsg)];
86
87 msghdr msg{
88 .msg_iov = iovs,
89 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
90 .msg_control = msgControlBuf,
91 .msg_controllen = sizeof(msgControlBuf),
92 };
93
94 cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
95 cmsg->cmsg_level = SOL_SOCKET;
96 cmsg->cmsg_type = SCM_RIGHTS;
97 cmsg->cmsg_len = CMSG_LEN(fdsByteSize);
98 memcpy(CMSG_DATA(cmsg), fds, fdsByteSize);
99
100 msg.msg_controllen = CMSG_SPACE(fdsByteSize);
101
102 ssize_t processedSize = TEMP_FAILURE_RETRY(
Pawan49d74cb2022-08-03 21:19:11 +0000103 sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
Frederick Mayle69a0c992022-05-26 20:38:39 +0000104 if (processedSize > 0) {
105 sentFds = true;
106 }
107 return processedSize;
108 }
109
110 msghdr msg{
111 .msg_iov = iovs,
112 // posix uses int, glibc uses size_t. niovs is a
113 // non-negative int and can be cast to either.
114 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
115 };
Pawan49d74cb2022-08-03 21:19:11 +0000116 return TEMP_FAILURE_RETRY(sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
Frederick Mayle69a0c992022-05-26 20:38:39 +0000117 };
Pawan49d74cb2022-08-03 21:19:11 +0000118 return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, send, "sendmsg", POLLOUT,
119 altPoll);
Steven Moreland301c3f02021-09-14 17:49:04 -0700120 }
121
Devin Moore695368f2022-06-03 22:29:14 +0000122 status_t interruptableReadFully(
123 FdTrigger* fdTrigger, iovec* iovs, int niovs,
Frederick Mayle69a0c992022-05-26 20:38:39 +0000124 const std::optional<android::base::function_ref<status_t()>>& altPoll,
Frederick Mayleffe9ac22022-06-30 02:07:36 +0000125 std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override {
Frederick Mayle69a0c992022-05-26 20:38:39 +0000126 auto recv = [&](iovec* iovs, int niovs) -> ssize_t {
Frederick Mayleffe9ac22022-06-30 02:07:36 +0000127 if (ancillaryFds != nullptr) {
Frederick Mayle69a0c992022-05-26 20:38:39 +0000128 int fdBuffer[kMaxFdsPerMsg];
129 alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(fdBuffer))];
130
131 msghdr msg{
132 .msg_iov = iovs,
133 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
134 .msg_control = msgControlBuf,
135 .msg_controllen = sizeof(msgControlBuf),
136 };
137 ssize_t processSize =
Pawan49d74cb2022-08-03 21:19:11 +0000138 TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
Frederick Mayle69a0c992022-05-26 20:38:39 +0000139 if (processSize < 0) {
140 return -1;
141 }
142
143 for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr;
144 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
145 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
146 // NOTE: It is tempting to reinterpret_cast, but cmsg(3) explicitly asks
147 // application devs to memcpy the data to ensure memory alignment.
148 size_t dataLen = cmsg->cmsg_len - CMSG_LEN(0);
Frederick Mayleffe9ac22022-06-30 02:07:36 +0000149 LOG_ALWAYS_FATAL_IF(dataLen > sizeof(fdBuffer)); // sanity check
Frederick Mayle69a0c992022-05-26 20:38:39 +0000150 memcpy(fdBuffer, CMSG_DATA(cmsg), dataLen);
151 size_t fdCount = dataLen / sizeof(int);
Frederick Mayleffe9ac22022-06-30 02:07:36 +0000152 ancillaryFds->reserve(ancillaryFds->size() + fdCount);
Frederick Mayle69a0c992022-05-26 20:38:39 +0000153 for (size_t i = 0; i < fdCount; i++) {
Frederick Mayleffe9ac22022-06-30 02:07:36 +0000154 ancillaryFds->emplace_back(base::unique_fd(fdBuffer[i]));
Frederick Mayle69a0c992022-05-26 20:38:39 +0000155 }
156 break;
157 }
158 }
159
160 if (msg.msg_flags & MSG_CTRUNC) {
161 ALOGE("msg was truncated. Aborting session.");
162 errno = EPIPE;
163 return -1;
164 }
165
166 return processSize;
167 }
168 msghdr msg{
169 .msg_iov = iovs,
170 // posix uses int, glibc uses size_t. niovs is a
171 // non-negative int and can be cast to either.
172 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
173 };
Pawan49d74cb2022-08-03 21:19:11 +0000174 return TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
Frederick Mayle69a0c992022-05-26 20:38:39 +0000175 };
Pawan49d74cb2022-08-03 21:19:11 +0000176 return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN,
177 altPoll);
Frederick Mayle69a0c992022-05-26 20:38:39 +0000178 }
179
Pawan49d74cb2022-08-03 21:19:11 +0000180 virtual bool isWaiting() { return mSocket.isInPollingState(); }
181
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700182private:
Pawan49d74cb2022-08-03 21:19:11 +0000183 android::TransportFd mSocket;
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700184};
185
186// RpcTransportCtx with TLS disabled.
187class RpcTransportCtxRaw : public RpcTransportCtx {
188public:
Pawan49d74cb2022-08-03 21:19:11 +0000189 std::unique_ptr<RpcTransport> newTransport(android::TransportFd socket, FdTrigger*) const {
190 return std::make_unique<RpcTransportRaw>(std::move(socket));
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700191 }
Yifan Hong9734cfc2021-09-13 16:14:09 -0700192 std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700193};
Yifan Hong588d59c2021-08-16 17:13:58 -0700194
Yifan Hongf6b4d5c2021-06-23 19:12:32 -0700195} // namespace
196
197std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryRaw::newServerCtx() const {
198 return std::make_unique<RpcTransportCtxRaw>();
199}
200
201std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryRaw::newClientCtx() const {
202 return std::make_unique<RpcTransportCtxRaw>();
203}
204
205const char *RpcTransportCtxFactoryRaw::toCString() const {
206 return "raw";
207}
208
209std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryRaw::make() {
210 return std::unique_ptr<RpcTransportCtxFactoryRaw>(new RpcTransportCtxFactoryRaw());
211}
212
213} // namespace android