1#!/bin/sh 2 3# 4# Test scenario by Tanaka Akira <akr@fsij.org> 5# from Bug 131876 - [socket] FD leak by receiving SCM_RIGHTS by recvmsg with 6# small control message buffer 7# Fixed by 337423 8 9. ../default.cfg 10 11dir=/tmp 12odir=`pwd` 13cd $dir 14sed '1,/^EOF/d' < $odir/$0 > $dir/sendmsg2.c 15mycc -o sendmsg2 -Wall -Wextra -O0 -g sendmsg2.c || exit 1 16rm -f sendmsg2.c 17cd $odir 18 19start=`date +%s` 20/tmp/sendmsg2 & 21while [ $((`date +%s` - start)) -lt 300 ]; do 22 kill -0 $! > /dev/null 2>&1 || break 23 sleep 2 24done 25if kill -0 $! > /dev/null 2>&1; then 26 echo FAIL 27 ps -lp $! 28 procstat -k $! 29 kill -9 $! 30fi 31while pkill sendmsg2; do :; done 32wait 33s=$? 34rm -f /tmp/sendmsg2 35exit $s 36EOF 37#include <sys/socket.h> 38#include <sys/types.h> 39#include <sys/uio.h> 40 41#include <stdio.h> 42#include <stdlib.h> 43#include <time.h> 44#include <unistd.h> 45 46#define MAX_FDS 10 47#define SEND_FDS 10 48#define RECV_FDS 3 49 50void 51test(void) 52{ 53 struct msghdr msg; 54 struct iovec iov; 55 union { 56 struct cmsghdr header; 57 char bytes[CMSG_SPACE(sizeof(int)*MAX_FDS)]; 58 } cmsg; 59 struct cmsghdr *cmh = &cmsg.header, *c; 60 int *fds; 61 int i; 62 int ret; 63 int sv[2]; 64 char buf[1024]; 65 char cmdline[1024]; 66 67 snprintf(cmdline, sizeof(cmdline), "fstat -p %u", (unsigned)getpid()); 68 69 ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv); 70 if (ret == -1) { perror("socketpair"); exit(1); } 71 72 iov.iov_base = "a"; 73 iov.iov_len = 1; 74 75 cmh->cmsg_len = CMSG_LEN(sizeof(int)*SEND_FDS); 76 cmh->cmsg_level = SOL_SOCKET; 77 cmh->cmsg_type = SCM_RIGHTS; 78 fds = (int *)CMSG_DATA(cmh); 79 for (i = 0; i < SEND_FDS; i++) { 80 fds[i] = 0; /* stdin */ 81 } 82 83 msg.msg_name = NULL; 84 msg.msg_namelen = 0; 85 msg.msg_iov = &iov; 86 msg.msg_iovlen = 1; 87 msg.msg_control = cmh; 88 msg.msg_controllen = CMSG_SPACE(sizeof(int)*SEND_FDS); 89 msg.msg_flags = 0; 90 91 ret = sendmsg(sv[0], &msg, 0); 92 if (ret == -1) { perror("sendmsg"); exit(1); } 93 94 iov.iov_base = buf; 95 iov.iov_len = sizeof(buf); 96 97 msg.msg_name = NULL; 98 msg.msg_namelen = 0; 99 msg.msg_iov = &iov; 100 msg.msg_iovlen = 1; 101 msg.msg_control = cmh; 102 msg.msg_controllen = CMSG_SPACE(sizeof(int)*RECV_FDS); 103 msg.msg_flags = 0; 104 105#if defined(DEBUG) 106 printf("before recvmsg: msg_controllen=%d\n", msg.msg_controllen); 107#endif 108 109 ret = recvmsg(sv[1], &msg, 0); 110 if (ret == -1) { perror("sendmsg"); exit(1); } 111 112#if defined(DEBUG) 113 printf("after recvmsg: msg_controllen=%d\n", msg.msg_controllen); 114#endif 115 116 for (c = CMSG_FIRSTHDR(&msg); c != NULL; c = CMSG_NXTHDR(&msg, c)) { 117 if (c->cmsg_len == 0) { printf("cmsg_len is zero\n"); exit(1); } 118 if (c->cmsg_level == SOL_SOCKET && c->cmsg_type == SCM_RIGHTS) { 119 int *fdp, *end; 120 printf("cmsg_len=%d\n", c->cmsg_len); 121 fdp = (int *)CMSG_DATA(c); 122 end = (int *)((char *)c + c->cmsg_len); 123 for (i = 0; fdp+i < end; i++) { 124 printf("fd[%d]=%d\n", i, fdp[i]); 125 } 126 } 127 } 128 /* Note the missing sockets close */ 129} 130 131int 132main(void) 133{ 134 time_t start; 135 136 alarm(600); 137 start = time(NULL); 138 while (time(NULL) - start < 300) 139 test(); 140 141 return (0); 142} 143