xref: /xnu-8020.101.4/tests/unp_externalize_fd_alloc.c (revision e7776783b89a353188416a9a346c6cdb4928faad)
1 /*
2  * Copyright (c) 2021 Apple Inc. All rights reserved.
3  */
4 
5 #include <stdio.h>
6 #include <sys/socket.h>
7 #include <sys/resource.h>
8 #include <errno.h>
9 
10 #include <darwintest.h>
11 #include <darwintest_utils.h>
12 
13 #define SCM_RIGHTS                      0x01
14 
15 T_DECL(scm_rights_control_msg, "Test the fd alloc failure behavior with SCM_RIGHTS control msg")
16 {
17 	T_SETUPBEGIN;
18 	int res, sock[2];
19 
20 	int fd = open("/dev/null", O_RDWR);
21 	T_ASSERT_POSIX_SUCCESS(fd, "open(/dev/null)");
22 
23 	struct rlimit rlim = { 6, 6 };
24 	setrlimit(RLIMIT_NOFILE, &rlim);
25 
26 	res = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
27 	T_QUIET; T_ASSERT_TRUE(sock[0] >= 0, "failed to create socket");
28 
29 	struct iovec iovec[1];
30 	struct msghdr msg = {0};
31 	struct cmsghdr *cmsghdr;
32 	char buf[CMSG_SPACE(sizeof(int))];
33 
34 	iovec[0].iov_base = "";
35 	iovec[0].iov_len = 1;
36 
37 	msg.msg_iov = iovec;
38 	msg.msg_iovlen = 1;
39 	msg.msg_control = buf;
40 	msg.msg_controllen = CMSG_SPACE(sizeof(int));
41 
42 	cmsghdr = CMSG_FIRSTHDR(&msg);
43 	cmsghdr->cmsg_len = CMSG_LEN(sizeof(int));
44 	cmsghdr->cmsg_level = SOL_SOCKET;
45 	cmsghdr->cmsg_type = SCM_RIGHTS;
46 	memcpy(CMSG_DATA(cmsghdr), &fd, sizeof(fd));
47 
48 	T_SETUPEND;
49 
50 	sendmsg(sock[1], &msg, 0);
51 
52 	u_char c;
53 	struct iovec riovec[1];
54 	struct msghdr rmsg = { 0, };
55 	char rbuf[CMSG_SPACE(sizeof(int))];
56 
57 	riovec[0].iov_base = &c;
58 	riovec[0].iov_len = 1;
59 
60 	rmsg.msg_iov = riovec;
61 	rmsg.msg_iovlen = 1;
62 	rmsg.msg_control = rbuf;
63 	rmsg.msg_controllen = CMSG_SPACE(sizeof(int));
64 
65 	ssize_t ret = recvmsg(sock[0], &rmsg, 0);
66 	T_ASSERT_TRUE(ret == -1, "recvmsg should fail");
67 	T_ASSERT_TRUE(errno == 24, "the fail code is EMFILE");
68 
69 	close(fd);
70 	close(sock[0]);
71 	close(sock[1]);
72 }
73