mirror of
				https://github.com/Cisco-Talos/clamav.git
				synced 2025-10-31 16:10:54 +00:00 
			
		
		
		
	
		
			
	
	
		
			148 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			148 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | #ifdef HAVE_SYS_TYPES_H
 | ||
|  | #include <sys/types.h>
 | ||
|  | #endif
 | ||
|  | #include <sys/wait.h>
 | ||
|  | #include <stdio.h>
 | ||
|  | #include <stdlib.h>
 | ||
|  | #include <unistd.h>
 | ||
|  | #include <string.h>
 | ||
|  | #ifdef HAVE_SYS_UIO_H
 | ||
|  | #include <sys/uio.h>
 | ||
|  | #endif
 | ||
|  | #include <signal.h>
 | ||
|  | #include <sys/socket.h>
 | ||
|  | 
 | ||
|  | #if !defined CMSG_SPACE || !defined CMSG_LEN
 | ||
|  | #ifndef ALIGN
 | ||
|  | #define ALIGN(len) len
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifndef CMSG_SPACE
 | ||
|  | #define CMSG_SPACE(len) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(len))
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifndef CMSG_LEN
 | ||
|  | #define CMSG_LEN(len) (ALIGN(sizeof(struct cmsghdr)) + len)
 | ||
|  | #endif
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #define TEST "test"
 | ||
|  | 
 | ||
|  | static int send_fd(int s, int fd) | ||
|  | { | ||
|  |     struct msghdr msg; | ||
|  |     struct cmsghdr *cmsg; | ||
|  |     unsigned char fdbuf[CMSG_SPACE(sizeof(int))]; | ||
|  |     struct iovec iov[1]; | ||
|  |     char dummy[] = ""; | ||
|  | 
 | ||
|  |     iov[0].iov_base = dummy; | ||
|  |     iov[0].iov_len  = 1; | ||
|  | 
 | ||
|  |     memset(&msg, 0, sizeof(msg)); | ||
|  |     msg.msg_control = fdbuf; | ||
|  |     /* must send/receive at least one byte */ | ||
|  |     msg.msg_iov        = iov; | ||
|  |     msg.msg_iovlen     = 1; | ||
|  |     msg.msg_controllen = CMSG_LEN(sizeof(int)); | ||
|  | 
 | ||
|  |     cmsg                    = CMSG_FIRSTHDR(&msg); | ||
|  |     cmsg->cmsg_len          = CMSG_LEN(sizeof(int)); | ||
|  |     cmsg->cmsg_level        = SOL_SOCKET; | ||
|  |     cmsg->cmsg_type         = SCM_RIGHTS; | ||
|  |     *(int *)CMSG_DATA(cmsg) = fd; | ||
|  | 
 | ||
|  |     if (sendmsg(s, &msg, 0) == -1) { | ||
|  |         perror("sendmsg"); | ||
|  |         close(s); | ||
|  |         return -1; | ||
|  |     } | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | static int testfd(int desc) | ||
|  | { | ||
|  |     char buf[256]; | ||
|  |     if (read(desc, buf, sizeof(buf)) != sizeof(TEST)) { | ||
|  |         fprintf(stderr, "test data not received correctly!"); | ||
|  |         return 1; | ||
|  |     } | ||
|  |     return memcmp(buf, TEST, sizeof(TEST)); | ||
|  | } | ||
|  | 
 | ||
|  | static int recv_fd(int desc) | ||
|  | { | ||
|  |     unsigned char buf[CMSG_SPACE(sizeof(int))]; | ||
|  |     struct msghdr msg; | ||
|  |     struct cmsghdr *cmsg; | ||
|  |     struct iovec iov[1]; | ||
|  |     char dummy; | ||
|  |     int ret = 2; | ||
|  | 
 | ||
|  |     memset(&msg, 0, sizeof(msg)); | ||
|  |     iov[0].iov_base    = &dummy; | ||
|  |     iov[0].iov_len     = 1; | ||
|  |     msg.msg_iov        = iov; | ||
|  |     msg.msg_iovlen     = 1; | ||
|  |     msg.msg_control    = buf; | ||
|  |     msg.msg_controllen = sizeof(buf); | ||
|  | 
 | ||
|  |     if (recvmsg(desc, &msg, 0) == -1) { | ||
|  |         perror("recvmsg failed!"); | ||
|  |         return -1; | ||
|  |     } | ||
|  |     if ((msg.msg_flags & MSG_TRUNC) || (msg.msg_flags & MSG_CTRUNC)) { | ||
|  |         fprintf(stderr, "control message truncated"); | ||
|  |         return -1; | ||
|  |     } | ||
|  |     for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; | ||
|  |          cmsg = CMSG_NXTHDR(&msg, cmsg)) { | ||
|  |         if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && | ||
|  |             cmsg->cmsg_level == SOL_SOCKET && | ||
|  |             cmsg->cmsg_type == SCM_RIGHTS) { | ||
|  |             int fd = *(int *)CMSG_DATA(cmsg); | ||
|  |             ret    = testfd(fd); | ||
|  |             close(fd); | ||
|  |         } | ||
|  |     } | ||
|  |     return ret; | ||
|  | } | ||
|  | 
 | ||
|  | int main(void) | ||
|  | { | ||
|  |     int fd[2]; | ||
|  |     int pip[2]; | ||
|  |     pid_t pid; | ||
|  |     int status; | ||
|  | 
 | ||
|  |     if (pipe(pip)) { | ||
|  |         perror("pipe"); | ||
|  |         return 1; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) { | ||
|  |         perror("socketpair"); | ||
|  |         return 1; | ||
|  |     } | ||
|  | 
 | ||
|  |     if ((pid = fork()) < 0) { | ||
|  |         perror("fork"); | ||
|  |     } else if (!pid) { | ||
|  |         exit(recv_fd(fd[1])); | ||
|  |     } else { | ||
|  |         /* parent */ | ||
|  |         if (send_fd(fd[0], pip[0]) == -1) { | ||
|  |             kill(pid, 9); | ||
|  |             waitpid(pid, NULL, 0); | ||
|  |             return 2; | ||
|  |         } | ||
|  |         if (write(pip[1], TEST, sizeof(TEST)) != sizeof(TEST)) { | ||
|  |             close(pip[1]); | ||
|  |             return -1; | ||
|  |         } | ||
|  |         close(pip[1]); | ||
|  |         waitpid(pid, &status, 0); | ||
|  |     } | ||
|  |     return status; | ||
|  | } |