1*8f0ba417SAndroid Build Coastguard Worker /*
2*8f0ba417SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*8f0ba417SAndroid Build Coastguard Worker *
4*8f0ba417SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8f0ba417SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8f0ba417SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8f0ba417SAndroid Build Coastguard Worker *
8*8f0ba417SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8f0ba417SAndroid Build Coastguard Worker *
10*8f0ba417SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8f0ba417SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8f0ba417SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8f0ba417SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8f0ba417SAndroid Build Coastguard Worker * limitations under the License.
15*8f0ba417SAndroid Build Coastguard Worker */
16*8f0ba417SAndroid Build Coastguard Worker
17*8f0ba417SAndroid Build Coastguard Worker #pragma once
18*8f0ba417SAndroid Build Coastguard Worker
19*8f0ba417SAndroid Build Coastguard Worker #include <sys/stat.h>
20*8f0ba417SAndroid Build Coastguard Worker #include <sys/types.h>
21*8f0ba417SAndroid Build Coastguard Worker
22*8f0ba417SAndroid Build Coastguard Worker #include <type_traits>
23*8f0ba417SAndroid Build Coastguard Worker #include <vector>
24*8f0ba417SAndroid Build Coastguard Worker
25*8f0ba417SAndroid Build Coastguard Worker #include <android-base/collections.h>
26*8f0ba417SAndroid Build Coastguard Worker #include <android-base/macros.h>
27*8f0ba417SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
28*8f0ba417SAndroid Build Coastguard Worker
29*8f0ba417SAndroid Build Coastguard Worker namespace android {
30*8f0ba417SAndroid Build Coastguard Worker namespace base {
31*8f0ba417SAndroid Build Coastguard Worker
32*8f0ba417SAndroid Build Coastguard Worker #if !defined(_WIN32)
33*8f0ba417SAndroid Build Coastguard Worker
34*8f0ba417SAndroid Build Coastguard Worker // Helpers for sending and receiving file descriptors across Unix domain sockets.
35*8f0ba417SAndroid Build Coastguard Worker //
36*8f0ba417SAndroid Build Coastguard Worker // The cmsg(3) API is very hard to get right, with multiple landmines that can
37*8f0ba417SAndroid Build Coastguard Worker // lead to death. Almost all of the uses of cmsg in Android make at least one of
38*8f0ba417SAndroid Build Coastguard Worker // the following mistakes:
39*8f0ba417SAndroid Build Coastguard Worker //
40*8f0ba417SAndroid Build Coastguard Worker // - not aligning the cmsg buffer
41*8f0ba417SAndroid Build Coastguard Worker // - leaking fds if more fds are received than expected
42*8f0ba417SAndroid Build Coastguard Worker // - blindly dereferencing CMSG_DATA without checking the header
43*8f0ba417SAndroid Build Coastguard Worker // - using CMSG_SPACE instead of CMSG_LEN for .cmsg_len
44*8f0ba417SAndroid Build Coastguard Worker // - using CMSG_LEN instead of CMSG_SPACE for .msg_controllen
45*8f0ba417SAndroid Build Coastguard Worker // - using a length specified in number of fds instead of bytes
46*8f0ba417SAndroid Build Coastguard Worker //
47*8f0ba417SAndroid Build Coastguard Worker // These functions wrap the hard-to-use cmsg API with an easier to use abstraction.
48*8f0ba417SAndroid Build Coastguard Worker
49*8f0ba417SAndroid Build Coastguard Worker // Send file descriptors across a Unix domain socket.
50*8f0ba417SAndroid Build Coastguard Worker //
51*8f0ba417SAndroid Build Coastguard Worker // Note that the write can return short if the socket type is SOCK_STREAM. When
52*8f0ba417SAndroid Build Coastguard Worker // this happens, file descriptors are still sent to the other end, but with
53*8f0ba417SAndroid Build Coastguard Worker // truncated data. For this reason, using SOCK_SEQPACKET or SOCK_DGRAM is recommended.
54*8f0ba417SAndroid Build Coastguard Worker ssize_t SendFileDescriptorVector(borrowed_fd sock, const void* data, size_t len,
55*8f0ba417SAndroid Build Coastguard Worker const std::vector<int>& fds);
56*8f0ba417SAndroid Build Coastguard Worker
57*8f0ba417SAndroid Build Coastguard Worker // Receive file descriptors from a Unix domain socket.
58*8f0ba417SAndroid Build Coastguard Worker //
59*8f0ba417SAndroid Build Coastguard Worker // If more FDs (or bytes, for datagram sockets) are received than expected,
60*8f0ba417SAndroid Build Coastguard Worker // -1 is returned with errno set to EMSGSIZE, and all received FDs are thrown away.
61*8f0ba417SAndroid Build Coastguard Worker ssize_t ReceiveFileDescriptorVector(borrowed_fd sock, void* data, size_t len, size_t max_fds,
62*8f0ba417SAndroid Build Coastguard Worker std::vector<android::base::unique_fd>* fds);
63*8f0ba417SAndroid Build Coastguard Worker
64*8f0ba417SAndroid Build Coastguard Worker // Helper for SendFileDescriptorVector that constructs a std::vector for you, e.g.:
65*8f0ba417SAndroid Build Coastguard Worker // SendFileDescriptors(sock, "foo", 3, std::move(fd1), std::move(fd2))
66*8f0ba417SAndroid Build Coastguard Worker template <typename... Args>
SendFileDescriptors(borrowed_fd sock,const void * data,size_t len,Args &&...sent_fds)67*8f0ba417SAndroid Build Coastguard Worker ssize_t SendFileDescriptors(borrowed_fd sock, const void* data, size_t len, Args&&... sent_fds) {
68*8f0ba417SAndroid Build Coastguard Worker // Do not allow implicit conversion to int: people might try to do something along the lines of:
69*8f0ba417SAndroid Build Coastguard Worker // SendFileDescriptors(..., std::move(a_unique_fd))
70*8f0ba417SAndroid Build Coastguard Worker // and be surprised when the unique_fd isn't closed afterwards.
71*8f0ba417SAndroid Build Coastguard Worker AssertType<int>(std::forward<Args>(sent_fds)...);
72*8f0ba417SAndroid Build Coastguard Worker std::vector<int> fds;
73*8f0ba417SAndroid Build Coastguard Worker Append(fds, std::forward<Args>(sent_fds)...);
74*8f0ba417SAndroid Build Coastguard Worker return SendFileDescriptorVector(sock, data, len, fds);
75*8f0ba417SAndroid Build Coastguard Worker }
76*8f0ba417SAndroid Build Coastguard Worker
77*8f0ba417SAndroid Build Coastguard Worker // Helper for ReceiveFileDescriptorVector that receives an exact number of file descriptors.
78*8f0ba417SAndroid Build Coastguard Worker // If more file descriptors are received than requested, -1 is returned with errno set to EMSGSIZE.
79*8f0ba417SAndroid Build Coastguard Worker // If fewer file descriptors are received than requested, -1 is returned with errno set to ENOMSG.
80*8f0ba417SAndroid Build Coastguard Worker // In both cases, all arguments are cleared and any received FDs are thrown away.
81*8f0ba417SAndroid Build Coastguard Worker template <typename... Args>
ReceiveFileDescriptors(borrowed_fd sock,void * data,size_t len,Args &&...received_fds)82*8f0ba417SAndroid Build Coastguard Worker ssize_t ReceiveFileDescriptors(borrowed_fd sock, void* data, size_t len, Args&&... received_fds) {
83*8f0ba417SAndroid Build Coastguard Worker std::vector<unique_fd*> fds;
84*8f0ba417SAndroid Build Coastguard Worker Append(fds, std::forward<Args>(received_fds)...);
85*8f0ba417SAndroid Build Coastguard Worker
86*8f0ba417SAndroid Build Coastguard Worker std::vector<unique_fd> result;
87*8f0ba417SAndroid Build Coastguard Worker ssize_t rc = ReceiveFileDescriptorVector(sock, data, len, fds.size(), &result);
88*8f0ba417SAndroid Build Coastguard Worker if (rc == -1 || result.size() != fds.size()) {
89*8f0ba417SAndroid Build Coastguard Worker int err = rc == -1 ? errno : ENOMSG;
90*8f0ba417SAndroid Build Coastguard Worker for (unique_fd* fd : fds) {
91*8f0ba417SAndroid Build Coastguard Worker fd->reset();
92*8f0ba417SAndroid Build Coastguard Worker }
93*8f0ba417SAndroid Build Coastguard Worker errno = err;
94*8f0ba417SAndroid Build Coastguard Worker return -1;
95*8f0ba417SAndroid Build Coastguard Worker }
96*8f0ba417SAndroid Build Coastguard Worker
97*8f0ba417SAndroid Build Coastguard Worker for (size_t i = 0; i < fds.size(); ++i) {
98*8f0ba417SAndroid Build Coastguard Worker *fds[i] = std::move(result[i]);
99*8f0ba417SAndroid Build Coastguard Worker }
100*8f0ba417SAndroid Build Coastguard Worker return rc;
101*8f0ba417SAndroid Build Coastguard Worker }
102*8f0ba417SAndroid Build Coastguard Worker
103*8f0ba417SAndroid Build Coastguard Worker #endif
104*8f0ba417SAndroid Build Coastguard Worker
105*8f0ba417SAndroid Build Coastguard Worker } // namespace base
106*8f0ba417SAndroid Build Coastguard Worker } // namespace android
107