2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2013 The FreeBSD Foundation
5 * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org>
8 * This software was developed by Pawel Jakub Dawidek under sponsorship from
9 * the FreeBSD Foundation.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/cdefs.h>
34 #include <sys/param.h>
35 #include <sys/socket.h>
36 #include <sys/select.h>
50 #include "common_impl.h"
55 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
56 #define PJDLOG_RASSERT(expr, ...) assert(expr)
57 #define PJDLOG_ABORT(...) abort()
61 /* Linux: arbitrary size, but must be lower than SCM_MAX_FD. */
62 #define PKG_MAX_SIZE ((64U - 1) * CMSG_SPACE(sizeof(int)))
65 * To work around limitations in 32-bit emulation on 64-bit kernels, use a
66 * machine-independent limit on the number of FDs per message. Each control
67 * message contains 1 FD and requires 12 bytes for the header, 4 pad bytes,
68 * 4 bytes for the descriptor, and another 4 pad bytes.
70 #define PKG_MAX_SIZE (MCLBYTES / 24)
74 msghdr_add_fd(struct cmsghdr *cmsg, int fd)
77 PJDLOG_ASSERT(fd >= 0);
79 cmsg->cmsg_level = SOL_SOCKET;
80 cmsg->cmsg_type = SCM_RIGHTS;
81 cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
82 bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd));
88 fd_wait(int fd, bool doread)
92 PJDLOG_ASSERT(fd >= 0);
96 (void)select(fd + 1, doread ? &fds : NULL, doread ? NULL : &fds,
101 msg_recv(int sock, struct msghdr *msg)
105 PJDLOG_ASSERT(sock >= 0);
107 #ifdef MSG_CMSG_CLOEXEC
108 flags = MSG_CMSG_CLOEXEC;
115 if (recvmsg(sock, msg, flags) == -1) {
127 msg_send(int sock, const struct msghdr *msg)
130 PJDLOG_ASSERT(sock >= 0);
133 fd_wait(sock, false);
134 if (sendmsg(sock, msg, 0) == -1) {
149 unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))];
151 struct cmsghdr *cmsg;
155 bzero(credbuf, sizeof(credbuf));
156 bzero(&msg, sizeof(msg));
157 bzero(&iov, sizeof(iov));
160 * XXX: We send one byte along with the control message, because
161 * setting msg_iov to NULL only works if this is the first
162 * packet send over the socket. Once we send some data we
163 * won't be able to send credentials anymore. This is most
164 * likely a kernel bug.
167 iov.iov_base = &dummy;
168 iov.iov_len = sizeof(dummy);
172 msg.msg_control = credbuf;
173 msg.msg_controllen = sizeof(credbuf);
175 cmsg = CMSG_FIRSTHDR(&msg);
176 cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
177 cmsg->cmsg_level = SOL_SOCKET;
178 cmsg->cmsg_type = SCM_CREDS;
180 if (msg_send(sock, &msg) == -1)
187 cred_recv(int sock, struct cmsgcred *cred)
189 unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))];
191 struct cmsghdr *cmsg;
195 bzero(credbuf, sizeof(credbuf));
196 bzero(&msg, sizeof(msg));
197 bzero(&iov, sizeof(iov));
199 iov.iov_base = &dummy;
200 iov.iov_len = sizeof(dummy);
204 msg.msg_control = credbuf;
205 msg.msg_controllen = sizeof(credbuf);
207 if (msg_recv(sock, &msg) == -1)
210 cmsg = CMSG_FIRSTHDR(&msg);
212 cmsg->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred)) ||
213 cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDS) {
217 bcopy(CMSG_DATA(cmsg), cred, sizeof(*cred));
224 fd_package_send(int sock, const int *fds, size_t nfds)
227 struct cmsghdr *cmsg;
233 PJDLOG_ASSERT(sock >= 0);
234 PJDLOG_ASSERT(fds != NULL);
235 PJDLOG_ASSERT(nfds > 0);
237 bzero(&msg, sizeof(msg));
240 * XXX: Look into cred_send function for more details.
243 iov.iov_base = &dummy;
244 iov.iov_len = sizeof(dummy);
248 msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int));
249 msg.msg_control = calloc(1, msg.msg_controllen);
250 if (msg.msg_control == NULL)
255 for (i = 0, cmsg = CMSG_FIRSTHDR(&msg); i < nfds && cmsg != NULL;
256 i++, cmsg = CMSG_NXTHDR(&msg, cmsg)) {
257 if (msghdr_add_fd(cmsg, fds[i]) == -1)
261 if (msg_send(sock, &msg) == -1)
267 free(msg.msg_control);
273 fd_package_recv(int sock, int *fds, size_t nfds)
276 struct cmsghdr *cmsg;
282 PJDLOG_ASSERT(sock >= 0);
283 PJDLOG_ASSERT(nfds > 0);
284 PJDLOG_ASSERT(fds != NULL);
286 bzero(&msg, sizeof(msg));
287 bzero(&iov, sizeof(iov));
290 * XXX: Look into cred_send function for more details.
292 iov.iov_base = &dummy;
293 iov.iov_len = sizeof(dummy);
297 msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int));
298 msg.msg_control = calloc(1, msg.msg_controllen);
299 if (msg.msg_control == NULL)
304 if (msg_recv(sock, &msg) == -1)
308 cmsg = CMSG_FIRSTHDR(&msg);
309 while (cmsg && i < nfds) {
312 if (cmsg->cmsg_level != SOL_SOCKET ||
313 cmsg->cmsg_type != SCM_RIGHTS) {
317 n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
322 bcopy(CMSG_DATA(cmsg), fds + i, sizeof(int) * n);
323 cmsg = CMSG_NXTHDR(&msg, cmsg);
327 if (cmsg != NULL || i < nfds) {
331 * We need to close all received descriptors, even if we have
332 * different control message (eg. SCM_CREDS) in between.
335 for (i = 0; i < last; i++) {
344 #ifndef MSG_CMSG_CLOEXEC
346 * If the MSG_CMSG_CLOEXEC flag is not available we cannot set the
347 * close-on-exec flag atomically, but we still want to set it for
350 for (i = 0; i < nfds; i++) {
351 (void) fcntl(fds[i], F_SETFD, FD_CLOEXEC);
358 free(msg.msg_control);
364 fd_recv(int sock, int *fds, size_t nfds)
366 unsigned int i, step, j;
369 if (nfds == 0 || fds == NULL) {
376 if (PKG_MAX_SIZE < nfds - i)
380 ret = fd_package_recv(sock, fds + i, step);
382 /* Close all received descriptors. */
384 for (j = 0; j < i; j++)
396 fd_send(int sock, const int *fds, size_t nfds)
398 unsigned int i, step;
401 if (nfds == 0 || fds == NULL) {
408 if (PKG_MAX_SIZE < nfds - i)
412 ret = fd_package_send(sock, fds + i, step);
422 buf_send(int sock, void *buf, size_t size)
427 PJDLOG_ASSERT(sock >= 0);
428 PJDLOG_ASSERT(size > 0);
429 PJDLOG_ASSERT(buf != NULL);
433 fd_wait(sock, false);
434 done = send(sock, ptr, size, 0);
439 } else if (done == 0) {
451 buf_recv(int sock, void *buf, size_t size, int flags)
456 PJDLOG_ASSERT(sock >= 0);
457 PJDLOG_ASSERT(buf != NULL);
462 done = recv(sock, ptr, size, flags);
467 } else if (done == 0) {