Deleted Added
full compact
unix_passfd_test.c (292814) unix_passfd_test.c (292914)
1/*-
2 * Copyright (c) 2005 Robert N. M. Watson
3 * Copyright (c) 2015 Mark Johnston
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 10 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
1/*-
2 * Copyright (c) 2005 Robert N. M. Watson
3 * Copyright (c) 2015 Mark Johnston
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 10 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/tools/regression/sockets/unix_passfd/unix_passfd.c 292814 2015-12-28 00:53:37Z ngie $
27 * $FreeBSD: head/tests/sys/kern/unix_passfd_test.c 292914 2015-12-30 11:15:07Z ngie $
28 */
29
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <sys/stat.h>
33#include <sys/sysctl.h>
34#include <sys/un.h>
35
28 */
29
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <sys/stat.h>
33#include <sys/sysctl.h>
34#include <sys/un.h>
35
36#include
36#include <errno.h>
37#include <fcntl.h>
38#include <limits.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
37#include <fcntl.h>
38#include <limits.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
44#include <atf-c.h>
45
44/*
45 * UNIX domain sockets allow file descriptors to be passed via "ancillary
46 * data", or control messages. This regression test is intended to exercise
47 * this facility, both performing some basic tests that it operates, and also
48 * causing some kernel edge cases to execute, such as garbage collection when
49 * there are cyclic file descriptor references. Right now we test only with
50 * stream sockets, but ideally we'd also test with datagram sockets.
51 */
52
53static void
46/*
47 * UNIX domain sockets allow file descriptors to be passed via "ancillary
48 * data", or control messages. This regression test is intended to exercise
49 * this facility, both performing some basic tests that it operates, and also
50 * causing some kernel edge cases to execute, such as garbage collection when
51 * there are cyclic file descriptor references. Right now we test only with
52 * stream sockets, but ideally we'd also test with datagram sockets.
53 */
54
55static void
54domainsocketpair(const char *test, int *fdp)
56domainsocketpair(int *fdp)
55{
56
57{
58
57 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdp) < 0)
58 err(-1, "%s: socketpair(PF_UNIX, SOCK_STREAM)", test);
59 ATF_REQUIRE_MSG(socketpair(PF_UNIX, SOCK_STREAM, 0, fdp) != -1,
60 "socketpair(PF_UNIX, SOCK_STREAM) failed: %s", strerror(errno));
59}
60
61static void
62closesocketpair(int *fdp)
63{
64
65 close(fdp[0]);
66 close(fdp[1]);
67}
68
69static void
61}
62
63static void
64closesocketpair(int *fdp)
65{
66
67 close(fdp[0]);
68 close(fdp[1]);
69}
70
71static void
70devnull(const char *test, int *fdp)
72devnull(int *fdp)
71{
72 int fd;
73
74 fd = open("/dev/null", O_RDONLY);
73{
74 int fd;
75
76 fd = open("/dev/null", O_RDONLY);
75 if (fd < 0)
76 err(-1, "%s: open(/dev/null)", test);
77 ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
77 *fdp = fd;
78}
79
80static void
78 *fdp = fd;
79}
80
81static void
81tempfile(const char *test, int *fdp)
82tempfile(int *fdp)
82{
83 char path[PATH_MAX];
84 int fd;
85
83{
84 char path[PATH_MAX];
85 int fd;
86
86 snprintf(path, PATH_MAX, "/tmp/unix_passfd.XXXXXXXXXXXXXXX");
87 snprintf(path, PATH_MAX, "%s/unix_passfd.XXXXXXXXXXXXXXX",
88 getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"));
87 fd = mkstemp(path);
89 fd = mkstemp(path);
88 if (fd < 0)
89 err(-1, "%s: mkstemp(%s)", test, path);
90 ATF_REQUIRE_MSG(fd != -1, "mkstemp(%s) failed", path);
90 (void)unlink(path);
91 *fdp = fd;
92}
93
94static void
91 (void)unlink(path);
92 *fdp = fd;
93}
94
95static void
95dofstat(const char *test, int fd, struct stat *sb)
96dofstat(int fd, struct stat *sb)
96{
97
97{
98
98 if (fstat(fd, sb) < 0)
99 err(-1, "%s: fstat", test);
99 ATF_REQUIRE_MSG(fstat(fd, sb) == 0,
100 "fstat failed: %s", strerror(errno));
100}
101
102static void
101}
102
103static void
103samefile(const char *test, struct stat *sb1, struct stat *sb2)
104samefile(struct stat *sb1, struct stat *sb2)
104{
105
105{
106
106 if (sb1->st_dev != sb2->st_dev)
107 errx(-1, "%s: samefile: different device", test);
108 if (sb1->st_ino != sb2->st_ino)
109 errx(-1, "%s: samefile: different inode", test);
107 ATF_REQUIRE_MSG(sb1->st_dev == sb2->st_dev, "different device");
108 ATF_REQUIRE_MSG(sb1->st_ino == sb2->st_ino, "different inode");
110}
111
112static void
109}
110
111static void
113sendfd_payload(const char *test, int sockfd, int sendfd,
114 void *payload, size_t paylen)
112sendfd_payload(int sockfd, int sendfd, void *payload, size_t paylen)
115{
116 struct iovec iovec;
117 char message[CMSG_SPACE(sizeof(int))];
118 struct cmsghdr *cmsghdr;
119 struct msghdr msghdr;
120 ssize_t len;
121
122 bzero(&msghdr, sizeof(msghdr));
123 bzero(&message, sizeof(message));
124
125 msghdr.msg_control = message;
126 msghdr.msg_controllen = sizeof(message);
127
128 iovec.iov_base = payload;
129 iovec.iov_len = paylen;
130
131 msghdr.msg_iov = &iovec;
132 msghdr.msg_iovlen = 1;
133
113{
114 struct iovec iovec;
115 char message[CMSG_SPACE(sizeof(int))];
116 struct cmsghdr *cmsghdr;
117 struct msghdr msghdr;
118 ssize_t len;
119
120 bzero(&msghdr, sizeof(msghdr));
121 bzero(&message, sizeof(message));
122
123 msghdr.msg_control = message;
124 msghdr.msg_controllen = sizeof(message);
125
126 iovec.iov_base = payload;
127 iovec.iov_len = paylen;
128
129 msghdr.msg_iov = &iovec;
130 msghdr.msg_iovlen = 1;
131
134 cmsghdr = (struct cmsghdr *)message;
132 cmsghdr = (struct cmsghdr *)(void*)message;
135 cmsghdr->cmsg_len = CMSG_LEN(sizeof(int));
136 cmsghdr->cmsg_level = SOL_SOCKET;
137 cmsghdr->cmsg_type = SCM_RIGHTS;
133 cmsghdr->cmsg_len = CMSG_LEN(sizeof(int));
134 cmsghdr->cmsg_level = SOL_SOCKET;
135 cmsghdr->cmsg_type = SCM_RIGHTS;
138 *(int *)CMSG_DATA(cmsghdr) = sendfd;
136 memcpy(CMSG_DATA(cmsghdr), &sendfd, sizeof(int));
139
140 len = sendmsg(sockfd, &msghdr, 0);
137
138 len = sendmsg(sockfd, &msghdr, 0);
141 if (len < 0)
142 err(-1, "%s: sendmsg", test);
143 if ((size_t)len != paylen)
144 errx(-1, "%s: sendmsg: %zd bytes sent", test, len);
139 ATF_REQUIRE_MSG(len != -1, "sendmsg failed: %s", strerror(errno));
140 ATF_REQUIRE_MSG((size_t)len == paylen,
141 "sendmsg: %zd messages sent; expected: %zu; %s", len, paylen,
142 strerror(errno));
145}
146
147static void
143}
144
145static void
148sendfd(const char *test, int sockfd, int sendfd)
146sendfd(int sockfd, int sendfd)
149{
150 char ch = 0;
151
147{
148 char ch = 0;
149
152 return (sendfd_payload(test, sockfd, sendfd, &ch, sizeof(ch)));
150 return (sendfd_payload(sockfd, sendfd, &ch, sizeof(ch)));
153}
154
155static void
151}
152
153static void
156recvfd_payload(const char *test, int sockfd, int *recvfd,
157 void *buf, size_t buflen)
154recvfd_payload(int sockfd, int *recvfd, void *buf, size_t buflen)
158{
159 struct cmsghdr *cmsghdr;
160 char message[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + sizeof(int)];
161 struct msghdr msghdr;
162 struct iovec iovec;
163 ssize_t len;
164
165 bzero(&msghdr, sizeof(msghdr));
166
167 msghdr.msg_control = message;
168 msghdr.msg_controllen = sizeof(message);
169
170 iovec.iov_base = buf;
171 iovec.iov_len = buflen;
172
173 msghdr.msg_iov = &iovec;
174 msghdr.msg_iovlen = 1;
175
176 len = recvmsg(sockfd, &msghdr, 0);
155{
156 struct cmsghdr *cmsghdr;
157 char message[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + sizeof(int)];
158 struct msghdr msghdr;
159 struct iovec iovec;
160 ssize_t len;
161
162 bzero(&msghdr, sizeof(msghdr));
163
164 msghdr.msg_control = message;
165 msghdr.msg_controllen = sizeof(message);
166
167 iovec.iov_base = buf;
168 iovec.iov_len = buflen;
169
170 msghdr.msg_iov = &iovec;
171 msghdr.msg_iovlen = 1;
172
173 len = recvmsg(sockfd, &msghdr, 0);
177 if (len < 0)
178 err(-1, "%s: recvmsg", test);
179 if ((size_t)len != buflen)
180 errx(-1, "%s: recvmsg: %zd bytes received", test, len);
174 ATF_REQUIRE_MSG(len != -1, "recvmsg failed: %s", strerror(errno));
175 ATF_REQUIRE_MSG((size_t)len == buflen,
176 "recvmsg: %zd bytes received; expected %zd", len, buflen);
181
182 cmsghdr = CMSG_FIRSTHDR(&msghdr);
177
178 cmsghdr = CMSG_FIRSTHDR(&msghdr);
183 if (cmsghdr == NULL)
184 errx(-1, "%s: recvmsg: did not receive control message", test);
179 ATF_REQUIRE_MSG(cmsghdr != NULL,
180 "recvmsg: did not receive control message");
185 *recvfd = -1;
186 for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) {
187 if (cmsghdr->cmsg_level == SOL_SOCKET &&
188 cmsghdr->cmsg_type == SCM_RIGHTS &&
189 cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) {
181 *recvfd = -1;
182 for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) {
183 if (cmsghdr->cmsg_level == SOL_SOCKET &&
184 cmsghdr->cmsg_type == SCM_RIGHTS &&
185 cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) {
190 *recvfd = *(int *)CMSG_DATA(cmsghdr);
191 if (*recvfd == -1)
192 errx(-1, "%s: recvmsg: received fd -1", test);
186 memcpy(recvfd, CMSG_DATA(cmsghdr), sizeof(int));
187 ATF_REQUIRE(*recvfd != -1);
193 }
194 }
188 }
189 }
195 if (*recvfd == -1)
196 errx(-1, "%s: recvmsg: did not receive single-fd message",
197 test);
190 ATF_REQUIRE_MSG(*recvfd != -1,
191 "recvmsg: did not receive single-fd message");
198}
199
200static void
192}
193
194static void
201recvfd(const char *test, int sockfd, int *recvfd)
195recvfd(int sockfd, int *recvfd)
202{
203 char ch = 0;
204
196{
197 char ch = 0;
198
205 return (recvfd_payload(test, sockfd, recvfd, &ch, sizeof(ch)));
199 return (recvfd_payload(sockfd, recvfd, &ch, sizeof(ch)));
206}
207
200}
201
208int
209main(void)
202/*
203 * Put a temporary file into a UNIX domain socket, then take it out and make
204 * sure it's the same file. First time around, don't close the reference
205 * after sending.
206 */
207ATF_TC_WITHOUT_HEAD(simple_send_fd);
208ATF_TC_BODY(simple_send_fd, tc)
210{
209{
211 struct stat putfd_1_stat, putfd_2_stat, getfd_1_stat, getfd_2_stat;
212 int fd[2], putfd_1, putfd_2, getfd_1, getfd_2;
213 const char *test;
210 struct stat getfd_stat, putfd_stat;
211 int fd[2], getfd, putfd;
214
212
215 /*
216 * First test: put a temporary file into a UNIX domain socket, then
217 * take it out and make sure it's the same file. First time around,
218 * don't close the reference after sending.
219 */
220 test = "test1-simplesendfd";
221 printf("beginning %s\n", test);
222
223 domainsocketpair(test, fd);
224 tempfile(test, &putfd_1);
225 dofstat(test, putfd_1, &putfd_1_stat);
226 sendfd(test, fd[0], putfd_1);
227 recvfd(test, fd[1], &getfd_1);
228 dofstat(test, getfd_1, &getfd_1_stat);
229 samefile(test, &putfd_1_stat, &getfd_1_stat);
230 close(putfd_1);
231 close(getfd_1);
213 domainsocketpair(fd);
214 tempfile(&putfd);
215 dofstat(putfd, &putfd_stat);
216 sendfd(fd[0], putfd);
217 recvfd(fd[1], &getfd);
218 dofstat(getfd, &getfd_stat);
219 samefile(&putfd_stat, &getfd_stat);
220 close(putfd);
221 close(getfd);
232 closesocketpair(fd);
222 closesocketpair(fd);
223}
233
224
234 printf("%s passed\n", test);
225/*
226 * Same as simple_send_fd, only close the file reference after sending, so that
227 * the only reference is the descriptor in the UNIX domain socket buffer.
228 */
229ATF_TC_WITHOUT_HEAD(send_and_close);
230ATF_TC_BODY(send_and_close, tc)
231{
232 struct stat getfd_stat, putfd_stat;
233 int fd[2], getfd, putfd;
235
234
236 /*
237 * Second test: same as first, only close the file reference after
238 * sending, so that the only reference is the descriptor in the UNIX
239 * domain socket buffer.
240 */
241 test = "test2-sendandclose";
242 printf("beginning %s\n", test);
243
244 domainsocketpair(test, fd);
245 tempfile(test, &putfd_1);
246 dofstat(test, putfd_1, &putfd_1_stat);
247 sendfd(test, fd[0], putfd_1);
248 close(putfd_1);
249 recvfd(test, fd[1], &getfd_1);
250 dofstat(test, getfd_1, &getfd_1_stat);
251 samefile(test, &putfd_1_stat, &getfd_1_stat);
252 close(getfd_1);
235 domainsocketpair(fd);
236 tempfile(&putfd);
237 dofstat(putfd, &putfd_stat);
238 sendfd(fd[0], putfd);
239 close(putfd);
240 recvfd(fd[1], &getfd);
241 dofstat(getfd, &getfd_stat);
242 samefile(&putfd_stat, &getfd_stat);
243 close(getfd);
253 closesocketpair(fd);
244 closesocketpair(fd);
245}
254
246
255 printf("%s passed\n", test);
247/*
248 * Put a temporary file into a UNIX domain socket, then close both endpoints
249 * causing garbage collection to kick off.
250 */
251ATF_TC_WITHOUT_HEAD(send_and_cancel);
252ATF_TC_BODY(send_and_cancel, tc)
253{
254 int fd[2], putfd;
256
255
257 /*
258 * Third test: put a temporary file into a UNIX domain socket, then
259 * close both endpoints causing garbage collection to kick off.
260 */
261 test = "test3-sendandcancel";
262 printf("beginning %s\n", test);
263
264 domainsocketpair(test, fd);
265 tempfile(test, &putfd_1);
266 sendfd(test, fd[0], putfd_1);
267 close(putfd_1);
256 domainsocketpair(fd);
257 tempfile(&putfd);
258 sendfd(fd[0], putfd);
259 close(putfd);
268 closesocketpair(fd);
260 closesocketpair(fd);
261}
269
262
270 printf("%s passed\n", test);
263/*
264 * Send two files. Then receive them. Make sure they are returned in the
265 * right order, and both get there.
266 */
267ATF_TC_WITHOUT_HEAD(two_files);
268ATF_TC_BODY(two_files, tc)
269{
270 struct stat getfd_1_stat, getfd_2_stat, putfd_1_stat, putfd_2_stat;
271 int fd[2], getfd_1, getfd_2, putfd_1, putfd_2;
271
272
272 /*
273 * Send two files. Then receive them. Make sure they are returned
274 * in the right order, and both get there.
275 */
276
277 test = "test4-twofile";
278 printf("beginning %s\n", test);
279
280 domainsocketpair(test, fd);
281 tempfile(test, &putfd_1);
282 tempfile(test, &putfd_2);
283 dofstat(test, putfd_1, &putfd_1_stat);
284 dofstat(test, putfd_2, &putfd_2_stat);
285 sendfd(test, fd[0], putfd_1);
286 sendfd(test, fd[0], putfd_2);
273 domainsocketpair(fd);
274 tempfile(&putfd_1);
275 tempfile(&putfd_2);
276 dofstat(putfd_1, &putfd_1_stat);
277 dofstat(putfd_2, &putfd_2_stat);
278 sendfd(fd[0], putfd_1);
279 sendfd(fd[0], putfd_2);
287 close(putfd_1);
288 close(putfd_2);
280 close(putfd_1);
281 close(putfd_2);
289 recvfd(test, fd[1], &getfd_1);
290 recvfd(test, fd[1], &getfd_2);
291 dofstat(test, getfd_1, &getfd_1_stat);
292 dofstat(test, getfd_2, &getfd_2_stat);
293 samefile(test, &putfd_1_stat, &getfd_1_stat);
294 samefile(test, &putfd_2_stat, &getfd_2_stat);
282 recvfd(fd[1], &getfd_1);
283 recvfd(fd[1], &getfd_2);
284 dofstat(getfd_1, &getfd_1_stat);
285 dofstat(getfd_2, &getfd_2_stat);
286 samefile(&putfd_1_stat, &getfd_1_stat);
287 samefile(&putfd_2_stat, &getfd_2_stat);
295 close(getfd_1);
296 close(getfd_2);
297 closesocketpair(fd);
288 close(getfd_1);
289 close(getfd_2);
290 closesocketpair(fd);
291}
298
292
299 printf("%s passed\n", test);
293/*
294 * Big bundling test. Send an endpoint of the UNIX domain socket over itself,
295 * closing the door behind it.
296 */
297ATF_TC_WITHOUT_HEAD(bundle);
298ATF_TC_BODY(bundle, tc)
299{
300 int fd[2], getfd;
300
301
301 /*
302 * Big bundling test. Send an endpoint of the UNIX domain socket
303 * over itself, closing the door behind it.
304 */
302 domainsocketpair(fd);
305
303
306 test = "test5-bundle";
307 printf("beginning %s\n", test);
308
309 domainsocketpair(test, fd);
310
311 sendfd(test, fd[0], fd[0]);
304 sendfd(fd[0], fd[0]);
312 close(fd[0]);
305 close(fd[0]);
313 recvfd(test, fd[1], &getfd_1);
314 close(getfd_1);
306 recvfd(fd[1], &getfd);
307 close(getfd);
315 close(fd[1]);
308 close(fd[1]);
309}
316
310
317 printf("%s passed\n", test);
311/*
312 * Big bundling test part two: Send an endpoint of the UNIX domain socket over
313 * itself, close the door behind it, and never remove it from the other end.
314 */
315ATF_TC_WITHOUT_HEAD(bundle_cancel);
316ATF_TC_BODY(bundle_cancel, tc)
317{
318 int fd[2];
318
319
319 /*
320 * Big bundling test part two: Send an endpoint of the UNIX domain
321 * socket over itself, close the door behind it, and never remove it
322 * from the other end.
323 */
324
325 test = "test6-bundlecancel";
326 printf("beginning %s\n", test);
327
328 domainsocketpair(test, fd);
329 sendfd(test, fd[0], fd[0]);
330 sendfd(test, fd[1], fd[0]);
320 domainsocketpair(fd);
321 sendfd(fd[0], fd[0]);
322 sendfd(fd[1], fd[0]);
331 closesocketpair(fd);
323 closesocketpair(fd);
324}
332
325
333 printf("%s passed\n", test);
326/*
327 * Test for PR 151758: Send an character device over the UNIX domain socket
328 * and then close both sockets to orphan the device.
329 */
330ATF_TC_WITHOUT_HEAD(devfs_orphan);
331ATF_TC_BODY(devfs_orphan, tc)
332{
333 int fd[2], putfd;
334
334
335 /*
336 * Test for PR 151758: Send an character device over the UNIX
337 * domain socket and then close both sockets to orphan the
338 * device.
339 */
340
341 test = "test7-devfsorphan";
342 printf("beginning %s\n", test);
343
344 domainsocketpair(test, fd);
345 devnull(test, &putfd_1);
346 sendfd(test, fd[0], putfd_1);
347 close(putfd_1);
335 domainsocketpair(fd);
336 devnull(&putfd);
337 sendfd(fd[0], putfd);
338 close(putfd);
348 closesocketpair(fd);
339 closesocketpair(fd);
340}
349
341
350 printf("%s passed\n", test);
342#define LOCAL_SENDSPACE_SYSCTL "net.local.stream.sendspace"
351
343
352 /*
353 * Test for PR 181741. Receiver sets LOCAL_CREDS, and kernel
354 * prepends a control message to the data. Sender sends large
355 * payload. Payload + SCM_RIGHTS + LOCAL_CREDS hit socket buffer
356 * limit, and receiver receives truncated data.
357 */
358 test = "test8-rights+creds+payload";
359 printf("beginning %s\n", test);
344/*
345 * Test for PR 181741. Receiver sets LOCAL_CREDS, and kernel prepends a
346 * control message to the data. Sender sends large payload.
347 * Payload + SCM_RIGHTS + LOCAL_CREDS hit socket buffer limit, and receiver
348 * receives truncated data.
349 */
350ATF_TC_WITHOUT_HEAD(rights_creds_payload);
351ATF_TC_BODY(rights_creds_payload, tc)
352{
353 const int on = 1;
354 u_long sendspace;
355 size_t len;
356 void *buf;
357 int fd[2], getfd, putfd, rc;
360
358
361 {
362 const int on = 1;
363 u_long sendspace;
364 size_t len;
365 void *buf;
359 atf_tc_expect_fail("PR 181741: Packet loss when 'control' messages "
360 "are present with large data");
366
361
367 len = sizeof(sendspace);
368 if (sysctlbyname("net.local.stream.sendspace", &sendspace,
369 &len, NULL, 0) < 0)
370 err(-1, "%s: sysctlbyname(net.local.stream.sendspace)",
371 test);
362 len = sizeof(sendspace);
363 rc = sysctlbyname(LOCAL_SENDSPACE_SYSCTL, &sendspace,
364 &len, NULL, 0);
365 ATF_REQUIRE_MSG(rc != -1,
366 "sysctl %s failed: %s", LOCAL_SENDSPACE_SYSCTL, strerror(errno));
372
367
373 if ((buf = calloc(1, sendspace)) == NULL)
374 err(-1, "%s: calloc", test);
368 buf = calloc(1, sendspace);
369 ATF_REQUIRE(buf != NULL);
375
370
376 domainsocketpair(test, fd);
377 if (setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on)) < 0)
378 err(-1, "%s: setsockopt(LOCAL_CREDS)", test);
379 tempfile(test, &putfd_1);
380 sendfd_payload(test, fd[0], putfd_1, buf, sendspace);
381 recvfd_payload(test, fd[1], &getfd_1, buf, sendspace);
382 close(putfd_1);
383 close(getfd_1);
384 closesocketpair(fd);
385 }
371 domainsocketpair(fd);
372 rc = setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on));
373 ATF_REQUIRE_MSG(rc != -1, "setsockopt(LOCAL_CREDS) failed: %s",
374 strerror(errno));
375 tempfile(&putfd);
376 sendfd_payload(fd[0], putfd, buf, sendspace);
377 recvfd_payload(fd[1], &getfd, buf, sendspace);
378 close(putfd);
379 close(getfd);
380 closesocketpair(fd);
381}
386
382
387 printf("%s passed\n", test);
383ATF_TP_ADD_TCS(tp)
384{
388
385
389 return (0);
386 ATF_TP_ADD_TC(tp, simple_send_fd);
387 ATF_TP_ADD_TC(tp, send_and_close);
388 ATF_TP_ADD_TC(tp, send_and_cancel);
389 ATF_TP_ADD_TC(tp, two_files);
390 ATF_TP_ADD_TC(tp, bundle);
391 ATF_TP_ADD_TC(tp, bundle_cancel);
392 ATF_TP_ADD_TC(tp, devfs_orphan);
393 ATF_TP_ADD_TC(tp, rights_creds_payload);
394
395 return (atf_no_error());
390}
396}