• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #include "OS.h"
18 #include "Utils.h"
19 #include "file.h"
20 
21 #include <binder/RpcTransportRaw.h>
22 #include <log/log.h>
23 #include <string.h>
24 #include <sys/socket.h>
25 
26 using android::binder::ReadFully;
27 
28 namespace android::binder::os {
29 
30 // Linux kernel supports up to 253 (from SCM_MAX_FD) for unix sockets.
31 constexpr size_t kMaxFdsPerMsg = 253;
32 
setNonBlocking(borrowed_fd fd)33 status_t setNonBlocking(borrowed_fd fd) {
34     int flags = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_GETFL));
35     if (flags == -1) {
36         PLOGE("Failed setNonBlocking: Could not get flags for fd");
37         return -errno;
38     }
39     if (int ret = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_SETFL, flags | O_NONBLOCK)); ret == -1) {
40         PLOGE("Failed setNonBlocking: Could not set non-blocking flag for fd");
41         return -errno;
42     }
43     return OK;
44 }
45 
getRandomBytes(uint8_t * data,size_t size)46 status_t getRandomBytes(uint8_t* data, size_t size) {
47     unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW)));
48     if (!fd.ok()) {
49         return -errno;
50     }
51 
52     if (!ReadFully(fd, data, size)) {
53         return -errno;
54     }
55     return OK;
56 }
57 
dupFileDescriptor(int oldFd,int * newFd)58 status_t dupFileDescriptor(int oldFd, int* newFd) {
59     int ret = fcntl(oldFd, F_DUPFD_CLOEXEC, 0);
60     if (ret < 0) {
61         return -errno;
62     }
63 
64     *newFd = ret;
65     return OK;
66 }
67 
makeDefaultRpcTransportCtxFactory()68 std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory() {
69     return RpcTransportCtxFactoryRaw::make();
70 }
71 
sendMessageOnSocket(const RpcTransportFd & socket,iovec * iovs,int niovs,const std::vector<std::variant<unique_fd,borrowed_fd>> * ancillaryFds)72 ssize_t sendMessageOnSocket(const RpcTransportFd& socket, iovec* iovs, int niovs,
73                             const std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds) {
74     if (ancillaryFds != nullptr && !ancillaryFds->empty()) {
75         if (ancillaryFds->size() > kMaxFdsPerMsg) {
76             errno = EINVAL;
77             return -1;
78         }
79 
80         // CMSG_DATA is not necessarily aligned, so we copy the FDs into a buffer and then
81         // use memcpy.
82         int fds[kMaxFdsPerMsg];
83         for (size_t i = 0; i < ancillaryFds->size(); i++) {
84             fds[i] = std::visit([](const auto& fd) { return fd.get(); }, ancillaryFds->at(i));
85         }
86         const size_t fdsByteSize = sizeof(int) * ancillaryFds->size();
87 
88         alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(int) * kMaxFdsPerMsg)];
89 
90         msghdr msg{
91                 .msg_iov = iovs,
92                 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
93                 .msg_control = msgControlBuf,
94                 .msg_controllen = sizeof(msgControlBuf),
95         };
96 
97         cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
98         cmsg->cmsg_level = SOL_SOCKET;
99         cmsg->cmsg_type = SCM_RIGHTS;
100         cmsg->cmsg_len = CMSG_LEN(fdsByteSize);
101         memcpy(CMSG_DATA(cmsg), fds, fdsByteSize);
102 
103         msg.msg_controllen = CMSG_SPACE(fdsByteSize);
104         return TEMP_FAILURE_RETRY(sendmsg(socket.fd.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
105     }
106 
107     msghdr msg{
108             .msg_iov = iovs,
109             // posix uses int, glibc uses size_t.  niovs is a
110             // non-negative int and can be cast to either.
111             .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
112     };
113     return TEMP_FAILURE_RETRY(sendmsg(socket.fd.get(), &msg, MSG_NOSIGNAL));
114 }
115 
receiveMessageFromSocket(const RpcTransportFd & socket,iovec * iovs,int niovs,std::vector<std::variant<unique_fd,borrowed_fd>> * ancillaryFds)116 ssize_t receiveMessageFromSocket(const RpcTransportFd& socket, iovec* iovs, int niovs,
117                                  std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds) {
118     if (ancillaryFds != nullptr) {
119         int fdBuffer[kMaxFdsPerMsg];
120         alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(fdBuffer))];
121 
122         msghdr msg{
123                 .msg_iov = iovs,
124                 .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
125                 .msg_control = msgControlBuf,
126                 .msg_controllen = sizeof(msgControlBuf),
127         };
128         ssize_t processSize = TEMP_FAILURE_RETRY(recvmsg(socket.fd.get(), &msg, MSG_NOSIGNAL));
129         if (processSize < 0) {
130             return -1;
131         }
132 
133         for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
134             if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
135                 // NOTE: It is tempting to reinterpret_cast, but cmsg(3) explicitly asks
136                 // application devs to memcpy the data to ensure memory alignment.
137                 size_t dataLen = cmsg->cmsg_len - CMSG_LEN(0);
138                 LOG_ALWAYS_FATAL_IF(dataLen > sizeof(fdBuffer)); // validity check
139                 memcpy(fdBuffer, CMSG_DATA(cmsg), dataLen);
140                 size_t fdCount = dataLen / sizeof(int);
141                 ancillaryFds->reserve(ancillaryFds->size() + fdCount);
142                 for (size_t i = 0; i < fdCount; i++) {
143                     ancillaryFds->emplace_back(unique_fd(fdBuffer[i]));
144                 }
145                 break;
146             }
147         }
148 
149         if (msg.msg_flags & MSG_CTRUNC) {
150             errno = EPIPE;
151             return -1;
152         }
153         return processSize;
154     }
155     msghdr msg{
156             .msg_iov = iovs,
157             // posix uses int, glibc uses size_t.  niovs is a
158             // non-negative int and can be cast to either.
159             .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
160     };
161 
162     return TEMP_FAILURE_RETRY(recvmsg(socket.fd.get(), &msg, MSG_NOSIGNAL));
163 }
164 
165 } // namespace android::binder::os
166