1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/posix/unix_domain_socket.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <errno.h>
8*635a8641SAndroid Build Coastguard Worker #include <sys/socket.h>
9*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL_NONSFI)
10*635a8641SAndroid Build Coastguard Worker #include <sys/un.h>
11*635a8641SAndroid Build Coastguard Worker #endif
12*635a8641SAndroid Build Coastguard Worker #include <unistd.h>
13*635a8641SAndroid Build Coastguard Worker
14*635a8641SAndroid Build Coastguard Worker #include <vector>
15*635a8641SAndroid Build Coastguard Worker
16*635a8641SAndroid Build Coastguard Worker #include "base/files/scoped_file.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/pickle.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/posix/eintr_wrapper.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/stl_util.h"
21*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
22*635a8641SAndroid Build Coastguard Worker
23*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL_NONSFI)
24*635a8641SAndroid Build Coastguard Worker #include <sys/uio.h>
25*635a8641SAndroid Build Coastguard Worker #endif
26*635a8641SAndroid Build Coastguard Worker
27*635a8641SAndroid Build Coastguard Worker namespace base {
28*635a8641SAndroid Build Coastguard Worker
29*635a8641SAndroid Build Coastguard Worker const size_t UnixDomainSocket::kMaxFileDescriptors = 16;
30*635a8641SAndroid Build Coastguard Worker
31*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL_NONSFI)
CreateSocketPair(ScopedFD * one,ScopedFD * two)32*635a8641SAndroid Build Coastguard Worker bool CreateSocketPair(ScopedFD* one, ScopedFD* two) {
33*635a8641SAndroid Build Coastguard Worker int raw_socks[2];
34*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
35*635a8641SAndroid Build Coastguard Worker // macOS does not support SEQPACKET.
36*635a8641SAndroid Build Coastguard Worker const int flags = SOCK_STREAM;
37*635a8641SAndroid Build Coastguard Worker #else
38*635a8641SAndroid Build Coastguard Worker const int flags = SOCK_SEQPACKET;
39*635a8641SAndroid Build Coastguard Worker #endif
40*635a8641SAndroid Build Coastguard Worker if (socketpair(AF_UNIX, flags, 0, raw_socks) == -1)
41*635a8641SAndroid Build Coastguard Worker return false;
42*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
43*635a8641SAndroid Build Coastguard Worker // On macOS, preventing SIGPIPE is done with socket option.
44*635a8641SAndroid Build Coastguard Worker const int no_sigpipe = 1;
45*635a8641SAndroid Build Coastguard Worker if (setsockopt(raw_socks[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
46*635a8641SAndroid Build Coastguard Worker sizeof(no_sigpipe)) != 0)
47*635a8641SAndroid Build Coastguard Worker return false;
48*635a8641SAndroid Build Coastguard Worker if (setsockopt(raw_socks[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
49*635a8641SAndroid Build Coastguard Worker sizeof(no_sigpipe)) != 0)
50*635a8641SAndroid Build Coastguard Worker return false;
51*635a8641SAndroid Build Coastguard Worker #endif
52*635a8641SAndroid Build Coastguard Worker one->reset(raw_socks[0]);
53*635a8641SAndroid Build Coastguard Worker two->reset(raw_socks[1]);
54*635a8641SAndroid Build Coastguard Worker return true;
55*635a8641SAndroid Build Coastguard Worker }
56*635a8641SAndroid Build Coastguard Worker
57*635a8641SAndroid Build Coastguard Worker // static
EnableReceiveProcessId(int fd)58*635a8641SAndroid Build Coastguard Worker bool UnixDomainSocket::EnableReceiveProcessId(int fd) {
59*635a8641SAndroid Build Coastguard Worker #if !defined(OS_MACOSX)
60*635a8641SAndroid Build Coastguard Worker const int enable = 1;
61*635a8641SAndroid Build Coastguard Worker return setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)) == 0;
62*635a8641SAndroid Build Coastguard Worker #else
63*635a8641SAndroid Build Coastguard Worker // SO_PASSCRED is not supported on macOS.
64*635a8641SAndroid Build Coastguard Worker return true;
65*635a8641SAndroid Build Coastguard Worker #endif // OS_MACOSX
66*635a8641SAndroid Build Coastguard Worker }
67*635a8641SAndroid Build Coastguard Worker #endif // !defined(OS_NACL_NONSFI)
68*635a8641SAndroid Build Coastguard Worker
69*635a8641SAndroid Build Coastguard Worker // static
SendMsg(int fd,const void * buf,size_t length,const std::vector<int> & fds)70*635a8641SAndroid Build Coastguard Worker bool UnixDomainSocket::SendMsg(int fd,
71*635a8641SAndroid Build Coastguard Worker const void* buf,
72*635a8641SAndroid Build Coastguard Worker size_t length,
73*635a8641SAndroid Build Coastguard Worker const std::vector<int>& fds) {
74*635a8641SAndroid Build Coastguard Worker struct msghdr msg = {};
75*635a8641SAndroid Build Coastguard Worker struct iovec iov = {const_cast<void*>(buf), length};
76*635a8641SAndroid Build Coastguard Worker msg.msg_iov = &iov;
77*635a8641SAndroid Build Coastguard Worker msg.msg_iovlen = 1;
78*635a8641SAndroid Build Coastguard Worker
79*635a8641SAndroid Build Coastguard Worker char* control_buffer = nullptr;
80*635a8641SAndroid Build Coastguard Worker if (fds.size()) {
81*635a8641SAndroid Build Coastguard Worker const unsigned control_len = CMSG_SPACE(sizeof(int) * fds.size());
82*635a8641SAndroid Build Coastguard Worker control_buffer = new char[control_len];
83*635a8641SAndroid Build Coastguard Worker
84*635a8641SAndroid Build Coastguard Worker struct cmsghdr* cmsg;
85*635a8641SAndroid Build Coastguard Worker msg.msg_control = control_buffer;
86*635a8641SAndroid Build Coastguard Worker msg.msg_controllen = control_len;
87*635a8641SAndroid Build Coastguard Worker cmsg = CMSG_FIRSTHDR(&msg);
88*635a8641SAndroid Build Coastguard Worker cmsg->cmsg_level = SOL_SOCKET;
89*635a8641SAndroid Build Coastguard Worker cmsg->cmsg_type = SCM_RIGHTS;
90*635a8641SAndroid Build Coastguard Worker cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds.size());
91*635a8641SAndroid Build Coastguard Worker memcpy(CMSG_DATA(cmsg), &fds[0], sizeof(int) * fds.size());
92*635a8641SAndroid Build Coastguard Worker msg.msg_controllen = cmsg->cmsg_len;
93*635a8641SAndroid Build Coastguard Worker }
94*635a8641SAndroid Build Coastguard Worker
95*635a8641SAndroid Build Coastguard Worker // Avoid a SIGPIPE if the other end breaks the connection.
96*635a8641SAndroid Build Coastguard Worker // Due to a bug in the Linux kernel (net/unix/af_unix.c) MSG_NOSIGNAL isn't
97*635a8641SAndroid Build Coastguard Worker // regarded for SOCK_SEQPACKET in the AF_UNIX domain, but it is mandated by
98*635a8641SAndroid Build Coastguard Worker // POSIX. On Mac MSG_NOSIGNAL is not supported, so we need to ensure that
99*635a8641SAndroid Build Coastguard Worker // SO_NOSIGPIPE is set during socket creation.
100*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
101*635a8641SAndroid Build Coastguard Worker const int flags = 0;
102*635a8641SAndroid Build Coastguard Worker int no_sigpipe = 0;
103*635a8641SAndroid Build Coastguard Worker socklen_t no_sigpipe_len = sizeof(no_sigpipe);
104*635a8641SAndroid Build Coastguard Worker DPCHECK(getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
105*635a8641SAndroid Build Coastguard Worker &no_sigpipe_len) == 0)
106*635a8641SAndroid Build Coastguard Worker << "Failed ot get socket option.";
107*635a8641SAndroid Build Coastguard Worker DCHECK(no_sigpipe) << "SO_NOSIGPIPE not set on the socket.";
108*635a8641SAndroid Build Coastguard Worker #else
109*635a8641SAndroid Build Coastguard Worker const int flags = MSG_NOSIGNAL;
110*635a8641SAndroid Build Coastguard Worker #endif // OS_MACOSX
111*635a8641SAndroid Build Coastguard Worker const ssize_t r = HANDLE_EINTR(sendmsg(fd, &msg, flags));
112*635a8641SAndroid Build Coastguard Worker const bool ret = static_cast<ssize_t>(length) == r;
113*635a8641SAndroid Build Coastguard Worker delete[] control_buffer;
114*635a8641SAndroid Build Coastguard Worker return ret;
115*635a8641SAndroid Build Coastguard Worker }
116*635a8641SAndroid Build Coastguard Worker
117*635a8641SAndroid Build Coastguard Worker // static
RecvMsg(int fd,void * buf,size_t length,std::vector<ScopedFD> * fds)118*635a8641SAndroid Build Coastguard Worker ssize_t UnixDomainSocket::RecvMsg(int fd,
119*635a8641SAndroid Build Coastguard Worker void* buf,
120*635a8641SAndroid Build Coastguard Worker size_t length,
121*635a8641SAndroid Build Coastguard Worker std::vector<ScopedFD>* fds) {
122*635a8641SAndroid Build Coastguard Worker return UnixDomainSocket::RecvMsgWithPid(fd, buf, length, fds, nullptr);
123*635a8641SAndroid Build Coastguard Worker }
124*635a8641SAndroid Build Coastguard Worker
125*635a8641SAndroid Build Coastguard Worker // static
RecvMsgWithPid(int fd,void * buf,size_t length,std::vector<ScopedFD> * fds,ProcessId * pid)126*635a8641SAndroid Build Coastguard Worker ssize_t UnixDomainSocket::RecvMsgWithPid(int fd,
127*635a8641SAndroid Build Coastguard Worker void* buf,
128*635a8641SAndroid Build Coastguard Worker size_t length,
129*635a8641SAndroid Build Coastguard Worker std::vector<ScopedFD>* fds,
130*635a8641SAndroid Build Coastguard Worker ProcessId* pid) {
131*635a8641SAndroid Build Coastguard Worker return UnixDomainSocket::RecvMsgWithFlags(fd, buf, length, 0, fds, pid);
132*635a8641SAndroid Build Coastguard Worker }
133*635a8641SAndroid Build Coastguard Worker
134*635a8641SAndroid Build Coastguard Worker // static
RecvMsgWithFlags(int fd,void * buf,size_t length,int flags,std::vector<ScopedFD> * fds,ProcessId * out_pid)135*635a8641SAndroid Build Coastguard Worker ssize_t UnixDomainSocket::RecvMsgWithFlags(int fd,
136*635a8641SAndroid Build Coastguard Worker void* buf,
137*635a8641SAndroid Build Coastguard Worker size_t length,
138*635a8641SAndroid Build Coastguard Worker int flags,
139*635a8641SAndroid Build Coastguard Worker std::vector<ScopedFD>* fds,
140*635a8641SAndroid Build Coastguard Worker ProcessId* out_pid) {
141*635a8641SAndroid Build Coastguard Worker fds->clear();
142*635a8641SAndroid Build Coastguard Worker
143*635a8641SAndroid Build Coastguard Worker struct msghdr msg = {};
144*635a8641SAndroid Build Coastguard Worker struct iovec iov = {buf, length};
145*635a8641SAndroid Build Coastguard Worker msg.msg_iov = &iov;
146*635a8641SAndroid Build Coastguard Worker msg.msg_iovlen = 1;
147*635a8641SAndroid Build Coastguard Worker
148*635a8641SAndroid Build Coastguard Worker const size_t kControlBufferSize =
149*635a8641SAndroid Build Coastguard Worker CMSG_SPACE(sizeof(int) * kMaxFileDescriptors)
150*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL_NONSFI) && !defined(OS_MACOSX)
151*635a8641SAndroid Build Coastguard Worker // The PNaCl toolchain for Non-SFI binary build and macOS do not support
152*635a8641SAndroid Build Coastguard Worker // ucred. macOS supports xucred, but this structure is insufficient.
153*635a8641SAndroid Build Coastguard Worker + CMSG_SPACE(sizeof(struct ucred))
154*635a8641SAndroid Build Coastguard Worker #endif // OS_NACL_NONSFI or OS_MACOSX
155*635a8641SAndroid Build Coastguard Worker ;
156*635a8641SAndroid Build Coastguard Worker char control_buffer[kControlBufferSize];
157*635a8641SAndroid Build Coastguard Worker msg.msg_control = control_buffer;
158*635a8641SAndroid Build Coastguard Worker msg.msg_controllen = sizeof(control_buffer);
159*635a8641SAndroid Build Coastguard Worker
160*635a8641SAndroid Build Coastguard Worker const ssize_t r = HANDLE_EINTR(recvmsg(fd, &msg, flags));
161*635a8641SAndroid Build Coastguard Worker if (r == -1)
162*635a8641SAndroid Build Coastguard Worker return -1;
163*635a8641SAndroid Build Coastguard Worker
164*635a8641SAndroid Build Coastguard Worker int* wire_fds = nullptr;
165*635a8641SAndroid Build Coastguard Worker unsigned wire_fds_len = 0;
166*635a8641SAndroid Build Coastguard Worker ProcessId pid = -1;
167*635a8641SAndroid Build Coastguard Worker
168*635a8641SAndroid Build Coastguard Worker if (msg.msg_controllen > 0) {
169*635a8641SAndroid Build Coastguard Worker struct cmsghdr* cmsg;
170*635a8641SAndroid Build Coastguard Worker for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
171*635a8641SAndroid Build Coastguard Worker const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
172*635a8641SAndroid Build Coastguard Worker if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
173*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(payload_len % sizeof(int), 0u);
174*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(wire_fds, static_cast<void*>(nullptr));
175*635a8641SAndroid Build Coastguard Worker wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
176*635a8641SAndroid Build Coastguard Worker wire_fds_len = payload_len / sizeof(int);
177*635a8641SAndroid Build Coastguard Worker }
178*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL_NONSFI) && !defined(OS_MACOSX)
179*635a8641SAndroid Build Coastguard Worker // The PNaCl toolchain for Non-SFI binary build and macOS do not support
180*635a8641SAndroid Build Coastguard Worker // SCM_CREDENTIALS.
181*635a8641SAndroid Build Coastguard Worker if (cmsg->cmsg_level == SOL_SOCKET &&
182*635a8641SAndroid Build Coastguard Worker cmsg->cmsg_type == SCM_CREDENTIALS) {
183*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(payload_len, sizeof(struct ucred));
184*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(pid, -1);
185*635a8641SAndroid Build Coastguard Worker pid = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg))->pid;
186*635a8641SAndroid Build Coastguard Worker }
187*635a8641SAndroid Build Coastguard Worker #endif // !defined(OS_NACL_NONSFI) && !defined(OS_MACOSX)
188*635a8641SAndroid Build Coastguard Worker }
189*635a8641SAndroid Build Coastguard Worker }
190*635a8641SAndroid Build Coastguard Worker
191*635a8641SAndroid Build Coastguard Worker if (msg.msg_flags & MSG_TRUNC || msg.msg_flags & MSG_CTRUNC) {
192*635a8641SAndroid Build Coastguard Worker if (msg.msg_flags & MSG_CTRUNC) {
193*635a8641SAndroid Build Coastguard Worker // Extraordinary case, not caller fixable. Log something.
194*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "recvmsg returned MSG_CTRUNC flag, buffer len is "
195*635a8641SAndroid Build Coastguard Worker << msg.msg_controllen;
196*635a8641SAndroid Build Coastguard Worker }
197*635a8641SAndroid Build Coastguard Worker for (unsigned i = 0; i < wire_fds_len; ++i)
198*635a8641SAndroid Build Coastguard Worker close(wire_fds[i]);
199*635a8641SAndroid Build Coastguard Worker errno = EMSGSIZE;
200*635a8641SAndroid Build Coastguard Worker return -1;
201*635a8641SAndroid Build Coastguard Worker }
202*635a8641SAndroid Build Coastguard Worker
203*635a8641SAndroid Build Coastguard Worker if (wire_fds) {
204*635a8641SAndroid Build Coastguard Worker for (unsigned i = 0; i < wire_fds_len; ++i)
205*635a8641SAndroid Build Coastguard Worker fds->push_back(ScopedFD(wire_fds[i])); // TODO(mdempsky): emplace_back
206*635a8641SAndroid Build Coastguard Worker }
207*635a8641SAndroid Build Coastguard Worker
208*635a8641SAndroid Build Coastguard Worker if (out_pid) {
209*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
210*635a8641SAndroid Build Coastguard Worker socklen_t pid_size = sizeof(pid);
211*635a8641SAndroid Build Coastguard Worker if (getsockopt(fd, SOL_LOCAL, LOCAL_PEERPID, &pid, &pid_size) != 0)
212*635a8641SAndroid Build Coastguard Worker pid = -1;
213*635a8641SAndroid Build Coastguard Worker #else
214*635a8641SAndroid Build Coastguard Worker // |pid| will legitimately be -1 if we read EOF, so only DCHECK if we
215*635a8641SAndroid Build Coastguard Worker // actually received a message. Unfortunately, Linux allows sending zero
216*635a8641SAndroid Build Coastguard Worker // length messages, which are indistinguishable from EOF, so this check
217*635a8641SAndroid Build Coastguard Worker // has false negatives.
218*635a8641SAndroid Build Coastguard Worker if (r > 0 || msg.msg_controllen > 0)
219*635a8641SAndroid Build Coastguard Worker DCHECK_GE(pid, 0);
220*635a8641SAndroid Build Coastguard Worker #endif
221*635a8641SAndroid Build Coastguard Worker
222*635a8641SAndroid Build Coastguard Worker *out_pid = pid;
223*635a8641SAndroid Build Coastguard Worker }
224*635a8641SAndroid Build Coastguard Worker
225*635a8641SAndroid Build Coastguard Worker return r;
226*635a8641SAndroid Build Coastguard Worker }
227*635a8641SAndroid Build Coastguard Worker
228*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL_NONSFI)
229*635a8641SAndroid Build Coastguard Worker // static
SendRecvMsg(int fd,uint8_t * reply,unsigned max_reply_len,int * result_fd,const Pickle & request)230*635a8641SAndroid Build Coastguard Worker ssize_t UnixDomainSocket::SendRecvMsg(int fd,
231*635a8641SAndroid Build Coastguard Worker uint8_t* reply,
232*635a8641SAndroid Build Coastguard Worker unsigned max_reply_len,
233*635a8641SAndroid Build Coastguard Worker int* result_fd,
234*635a8641SAndroid Build Coastguard Worker const Pickle& request) {
235*635a8641SAndroid Build Coastguard Worker return UnixDomainSocket::SendRecvMsgWithFlags(fd, reply, max_reply_len,
236*635a8641SAndroid Build Coastguard Worker 0, /* recvmsg_flags */
237*635a8641SAndroid Build Coastguard Worker result_fd, request);
238*635a8641SAndroid Build Coastguard Worker }
239*635a8641SAndroid Build Coastguard Worker
240*635a8641SAndroid Build Coastguard Worker // static
SendRecvMsgWithFlags(int fd,uint8_t * reply,unsigned max_reply_len,int recvmsg_flags,int * result_fd,const Pickle & request)241*635a8641SAndroid Build Coastguard Worker ssize_t UnixDomainSocket::SendRecvMsgWithFlags(int fd,
242*635a8641SAndroid Build Coastguard Worker uint8_t* reply,
243*635a8641SAndroid Build Coastguard Worker unsigned max_reply_len,
244*635a8641SAndroid Build Coastguard Worker int recvmsg_flags,
245*635a8641SAndroid Build Coastguard Worker int* result_fd,
246*635a8641SAndroid Build Coastguard Worker const Pickle& request) {
247*635a8641SAndroid Build Coastguard Worker // This socketpair is only used for the IPC and is cleaned up before
248*635a8641SAndroid Build Coastguard Worker // returning.
249*635a8641SAndroid Build Coastguard Worker ScopedFD recv_sock, send_sock;
250*635a8641SAndroid Build Coastguard Worker if (!CreateSocketPair(&recv_sock, &send_sock))
251*635a8641SAndroid Build Coastguard Worker return -1;
252*635a8641SAndroid Build Coastguard Worker
253*635a8641SAndroid Build Coastguard Worker {
254*635a8641SAndroid Build Coastguard Worker std::vector<int> send_fds;
255*635a8641SAndroid Build Coastguard Worker send_fds.push_back(send_sock.get());
256*635a8641SAndroid Build Coastguard Worker if (!SendMsg(fd, request.data(), request.size(), send_fds))
257*635a8641SAndroid Build Coastguard Worker return -1;
258*635a8641SAndroid Build Coastguard Worker }
259*635a8641SAndroid Build Coastguard Worker
260*635a8641SAndroid Build Coastguard Worker // Close the sending end of the socket right away so that if our peer closes
261*635a8641SAndroid Build Coastguard Worker // it before sending a response (e.g., from exiting), RecvMsgWithFlags() will
262*635a8641SAndroid Build Coastguard Worker // return EOF instead of hanging.
263*635a8641SAndroid Build Coastguard Worker send_sock.reset();
264*635a8641SAndroid Build Coastguard Worker
265*635a8641SAndroid Build Coastguard Worker std::vector<ScopedFD> recv_fds;
266*635a8641SAndroid Build Coastguard Worker // When porting to OSX keep in mind it doesn't support MSG_NOSIGNAL, so the
267*635a8641SAndroid Build Coastguard Worker // sender might get a SIGPIPE.
268*635a8641SAndroid Build Coastguard Worker const ssize_t reply_len = RecvMsgWithFlags(
269*635a8641SAndroid Build Coastguard Worker recv_sock.get(), reply, max_reply_len, recvmsg_flags, &recv_fds, nullptr);
270*635a8641SAndroid Build Coastguard Worker recv_sock.reset();
271*635a8641SAndroid Build Coastguard Worker if (reply_len == -1)
272*635a8641SAndroid Build Coastguard Worker return -1;
273*635a8641SAndroid Build Coastguard Worker
274*635a8641SAndroid Build Coastguard Worker // If we received more file descriptors than caller expected, then we treat
275*635a8641SAndroid Build Coastguard Worker // that as an error.
276*635a8641SAndroid Build Coastguard Worker if (recv_fds.size() > (result_fd != nullptr ? 1 : 0)) {
277*635a8641SAndroid Build Coastguard Worker NOTREACHED();
278*635a8641SAndroid Build Coastguard Worker return -1;
279*635a8641SAndroid Build Coastguard Worker }
280*635a8641SAndroid Build Coastguard Worker
281*635a8641SAndroid Build Coastguard Worker if (result_fd)
282*635a8641SAndroid Build Coastguard Worker *result_fd = recv_fds.empty() ? -1 : recv_fds[0].release();
283*635a8641SAndroid Build Coastguard Worker
284*635a8641SAndroid Build Coastguard Worker return reply_len;
285*635a8641SAndroid Build Coastguard Worker }
286*635a8641SAndroid Build Coastguard Worker #endif // !defined(OS_NACL_NONSFI)
287*635a8641SAndroid Build Coastguard Worker
288*635a8641SAndroid Build Coastguard Worker } // namespace base
289