unix_passfd_test.c (228371) | unix_passfd_test.c (261550) |
---|---|
1/*- 2 * Copyright (c) 2005 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 2005 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/tools/regression/sockets/unix_passfd/unix_passfd.c 228371 2011-12-09 19:24:17Z jhb $ | 26 * $FreeBSD: head/tools/regression/sockets/unix_passfd/unix_passfd.c 261550 2014-02-06 13:18:10Z glebius $ |
27 */ 28 29#include <sys/types.h> 30#include <sys/socket.h> 31#include <sys/stat.h> | 27 */ 28 29#include <sys/types.h> 30#include <sys/socket.h> 31#include <sys/stat.h> |
32#include <sys/sysctl.h> 33#include <sys/un.h> |
|
32 33#include <err.h> 34#include <fcntl.h> 35#include <limits.h> 36#include <stdio.h> | 34 35#include <err.h> 36#include <fcntl.h> 37#include <limits.h> 38#include <stdio.h> |
39#include <stdlib.h> |
|
37#include <string.h> 38#include <unistd.h> 39 40/* 41 * UNIX domain sockets allow file descriptors to be passed via "ancillary 42 * data", or control messages. This regression test is intended to exercise 43 * this facility, both performing some basic tests that it operates, and also 44 * causing some kernel edge cases to execute, such as garbage collection when --- 56 unchanged lines hidden (view full) --- 101 102 if (sb1->st_dev != sb2->st_dev) 103 errx(-1, "%s: samefile: different device", test); 104 if (sb1->st_ino != sb2->st_ino) 105 errx(-1, "%s: samefile: different inode", test); 106} 107 108static void | 40#include <string.h> 41#include <unistd.h> 42 43/* 44 * UNIX domain sockets allow file descriptors to be passed via "ancillary 45 * data", or control messages. This regression test is intended to exercise 46 * this facility, both performing some basic tests that it operates, and also 47 * causing some kernel edge cases to execute, such as garbage collection when --- 56 unchanged lines hidden (view full) --- 104 105 if (sb1->st_dev != sb2->st_dev) 106 errx(-1, "%s: samefile: different device", test); 107 if (sb1->st_ino != sb2->st_ino) 108 errx(-1, "%s: samefile: different inode", test); 109} 110 111static void |
109sendfd(const char *test, int sockfd, int sendfd) | 112sendfd_payload(const char *test, int sockfd, int sendfd, 113 void *payload, size_t paylen) |
110{ 111 struct iovec iovec; | 114{ 115 struct iovec iovec; |
112 char ch; 113 | |
114 char message[CMSG_SPACE(sizeof(int))]; 115 struct cmsghdr *cmsghdr; 116 struct msghdr msghdr; 117 ssize_t len; 118 119 bzero(&msghdr, sizeof(msghdr)); 120 bzero(&message, sizeof(message)); | 116 char message[CMSG_SPACE(sizeof(int))]; 117 struct cmsghdr *cmsghdr; 118 struct msghdr msghdr; 119 ssize_t len; 120 121 bzero(&msghdr, sizeof(msghdr)); 122 bzero(&message, sizeof(message)); |
121 ch = 0; | |
122 123 msghdr.msg_control = message; 124 msghdr.msg_controllen = sizeof(message); 125 | 123 124 msghdr.msg_control = message; 125 msghdr.msg_controllen = sizeof(message); 126 |
126 iovec.iov_base = &ch; 127 iovec.iov_len = sizeof(ch); | 127 iovec.iov_base = payload; 128 iovec.iov_len = paylen; |
128 129 msghdr.msg_iov = &iovec; 130 msghdr.msg_iovlen = 1; 131 132 cmsghdr = (struct cmsghdr *)message; 133 cmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); 134 cmsghdr->cmsg_level = SOL_SOCKET; 135 cmsghdr->cmsg_type = SCM_RIGHTS; 136 *(int *)CMSG_DATA(cmsghdr) = sendfd; 137 138 len = sendmsg(sockfd, &msghdr, 0); 139 if (len < 0) 140 err(-1, "%s: sendmsg", test); | 129 130 msghdr.msg_iov = &iovec; 131 msghdr.msg_iovlen = 1; 132 133 cmsghdr = (struct cmsghdr *)message; 134 cmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); 135 cmsghdr->cmsg_level = SOL_SOCKET; 136 cmsghdr->cmsg_type = SCM_RIGHTS; 137 *(int *)CMSG_DATA(cmsghdr) = sendfd; 138 139 len = sendmsg(sockfd, &msghdr, 0); 140 if (len < 0) 141 err(-1, "%s: sendmsg", test); |
141 if (len != sizeof(ch)) | 142 if (len != paylen) |
142 errx(-1, "%s: sendmsg: %zd bytes sent", test, len); 143} 144 145static void | 143 errx(-1, "%s: sendmsg: %zd bytes sent", test, len); 144} 145 146static void |
146recvfd(const char *test, int sockfd, int *recvfd) | 147sendfd(const char *test, int sockfd, int sendfd) |
147{ | 148{ |
149 char ch; 150 151 return (sendfd_payload(test, sockfd, sendfd, &ch, sizeof(ch))); 152} 153 154static void 155recvfd_payload(const char *test, int sockfd, int *recvfd, 156 void *buf, size_t buflen) 157{ |
|
148 struct cmsghdr *cmsghdr; | 158 struct cmsghdr *cmsghdr; |
149 char message[CMSG_SPACE(sizeof(int))]; | 159 char message[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + sizeof(int)]; |
150 struct msghdr msghdr; 151 struct iovec iovec; 152 ssize_t len; | 160 struct msghdr msghdr; 161 struct iovec iovec; 162 ssize_t len; |
153 char ch; | |
154 155 bzero(&msghdr, sizeof(msghdr)); | 163 164 bzero(&msghdr, sizeof(msghdr)); |
156 ch = 0; | |
157 158 msghdr.msg_control = message; 159 msghdr.msg_controllen = sizeof(message); 160 | 165 166 msghdr.msg_control = message; 167 msghdr.msg_controllen = sizeof(message); 168 |
161 iovec.iov_base = &ch; 162 iovec.iov_len = sizeof(ch); | 169 iovec.iov_base = buf; 170 iovec.iov_len = buflen; |
163 164 msghdr.msg_iov = &iovec; 165 msghdr.msg_iovlen = 1; 166 | 171 172 msghdr.msg_iov = &iovec; 173 msghdr.msg_iovlen = 1; 174 |
167 iovec.iov_len = sizeof(ch); 168 169 msghdr.msg_iov = &iovec; 170 msghdr.msg_iovlen = 1; 171 | |
172 len = recvmsg(sockfd, &msghdr, 0); 173 if (len < 0) 174 err(-1, "%s: recvmsg", test); | 175 len = recvmsg(sockfd, &msghdr, 0); 176 if (len < 0) 177 err(-1, "%s: recvmsg", test); |
175 if (len != sizeof(ch)) | 178 if (len != buflen) |
176 errx(-1, "%s: recvmsg: %zd bytes received", test, len); | 179 errx(-1, "%s: recvmsg: %zd bytes received", test, len); |
180 |
|
177 cmsghdr = CMSG_FIRSTHDR(&msghdr); 178 if (cmsghdr == NULL) 179 errx(-1, "%s: recvmsg: did not receive control message", test); | 181 cmsghdr = CMSG_FIRSTHDR(&msghdr); 182 if (cmsghdr == NULL) 183 errx(-1, "%s: recvmsg: did not receive control message", test); |
180 if (cmsghdr->cmsg_len != CMSG_LEN(sizeof(int)) || 181 cmsghdr->cmsg_level != SOL_SOCKET || 182 cmsghdr->cmsg_type != SCM_RIGHTS) | 184 *recvfd = -1; 185 for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) { 186 if (cmsghdr->cmsg_level == SOL_SOCKET && 187 cmsghdr->cmsg_type == SCM_RIGHTS && 188 cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) { 189 *recvfd = *(int *)CMSG_DATA(cmsghdr); 190 if (*recvfd == -1) 191 errx(-1, "%s: recvmsg: received fd -1", test); 192 } 193 } 194 if (*recvfd == -1) |
183 errx(-1, "%s: recvmsg: did not receive single-fd message", 184 test); | 195 errx(-1, "%s: recvmsg: did not receive single-fd message", 196 test); |
185 *recvfd = *(int *)CMSG_DATA(cmsghdr); 186 if (*recvfd == -1) 187 errx(-1, "%s: recvmsg: received fd -1", test); | |
188} 189 | 197} 198 |
199static void 200recvfd(const char *test, int sockfd, int *recvfd) 201{ 202 char ch; 203 204 return (recvfd_payload(test, sockfd, recvfd, &ch, sizeof(ch))); 205} 206 |
|
190int 191main(int argc, char *argv[]) 192{ 193 struct stat putfd_1_stat, putfd_2_stat, getfd_1_stat, getfd_2_stat; 194 int fd[2], putfd_1, putfd_2, getfd_1, getfd_2; 195 const char *test; 196 197 /* --- 127 unchanged lines hidden (view full) --- 325 326 domainsocketpair(test, fd); 327 devnull(test, &putfd_1); 328 sendfd(test, fd[0], putfd_1); 329 close(putfd_1); 330 closesocketpair(fd); 331 332 printf("%s passed\n", test); | 207int 208main(int argc, char *argv[]) 209{ 210 struct stat putfd_1_stat, putfd_2_stat, getfd_1_stat, getfd_2_stat; 211 int fd[2], putfd_1, putfd_2, getfd_1, getfd_2; 212 const char *test; 213 214 /* --- 127 unchanged lines hidden (view full) --- 342 343 domainsocketpair(test, fd); 344 devnull(test, &putfd_1); 345 sendfd(test, fd[0], putfd_1); 346 close(putfd_1); 347 closesocketpair(fd); 348 349 printf("%s passed\n", test); |
350 351 /* 352 * Test for PR 181741. Receiver sets LOCAL_CREDS, and kernel 353 * prepends a control message to the data. Sender sends large 354 * payload. Payload + SCM_RIGHTS + LOCAL_CREDS hit socket buffer 355 * limit, and receiver receives truncated data. 356 */ 357 test = "test8-rigths+creds+payload"; 358 printf("beginning %s\n", test); 359 360 { 361 const int on = 1; 362 u_long sendspace; 363 size_t len; 364 void *buf; 365 366 len = sizeof(sendspace); 367 if (sysctlbyname("net.local.stream.sendspace", &sendspace, 368 &len, NULL, 0) < 0) 369 err(-1, "%s: sysctlbyname(net.local.stream.sendspace)", 370 test); 371 372 if ((buf = malloc(sendspace)) == NULL) 373 err(-1, "%s: malloc", test); 374 375 domainsocketpair(test, fd); 376 if (setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on)) < 0) 377 err(-1, "%s: setsockopt(LOCAL_CREDS)", test); 378 tempfile(test, &putfd_1); 379 sendfd_payload(test, fd[0], putfd_1, buf, sendspace); 380 recvfd_payload(test, fd[1], &getfd_1, buf, sendspace); 381 close(putfd_1); 382 close(getfd_1); 383 closesocketpair(fd); 384 } 385 386 printf("%s passed\n", test); |
|
333 334 return (0); 335} | 387 388 return (0); 389} |