apparmor/tests/regression/subdomain/unix_fd_server.c
Steve Beattie 6d3e74907d Import the rest of the core functionality of the internal apparmor
development tree (trunk branch). From svn repo version 6381.
2006-04-11 21:52:54 +00:00

158 lines
3.6 KiB
C

/* fd passing over unix sockets */
/*
* Copyright (C) 2002-2005 Novell/SUSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*/
/* this is very ugly */
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <alloca.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <sys/poll.h>
#include <errno.h>
#include <stdlib.h>
int main (int argc, char * argv[]) {
int sock, in_sock, fd;
struct sockaddr_un local, remote;
int len, exec_now, pfd_ret;
socklen_t len2;
char comparison_buffer[17];
char inbound_buffer[17];
struct iovec vect;
struct msghdr mesg;
struct cmsghdr *ctrl_mesg;
struct pollfd pfd;
exec_now = 0;
if (argc < 4 || argc > 5 || (argc == 5 && (strcmp(argv[4], "delete_file") != 0))) {
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
return(1);
}
if ((fd = open(argv[1], O_RDONLY)) < 0) {
fprintf(stderr, "FAIL - open failed: %s\n",
strerror(errno));
return(1);
}
if (pread(fd, comparison_buffer, 16,0) <= 0) {
fprintf(stderr, "FAIL - read failed: %s\n",
strerror(errno));
return(1);
}
if (argc == 5) {
if (unlink(argv[1]) == -1){
fprintf(stderr, "FAIL: unlink before passing fd - %s\n",
strerror(errno));
return 1;
}
}
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
fprintf(stderr, "FAIL - socket failed: %s\n",
strerror(errno));
return(1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, argv[2]);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(sock, (struct sockaddr *) &local, len) != 0) {
fprintf(stderr, "FAIL - bind failed: %s\n",
strerror(errno));
return(1);
}
if (listen(sock, 2) != 0) {
fprintf(stderr, "FAIL - listen failed: %s\n",
strerror(errno));
return(1);
}
/* exec the client */
int pid = fork();
if (!pid) {
execlp(argv[3], argv[3], argv[2], NULL);
exit(0);
}
len2 = sizeof(remote);
pfd.fd = sock;
pfd.events = POLLIN;
pfd_ret = poll(&pfd, 1, 500);
if (pfd_ret == 1) {
if ((in_sock = accept(sock, (struct sockaddr*)&remote, &len2)) == -1) {
fprintf(stderr, "FAIL - accept: %s\n",
strerror(errno));
exit(1);
}
vect.iov_base = argv[2];
vect.iov_len = strlen(argv[2]) + 1;
mesg.msg_name = NULL;
mesg.msg_namelen = 0;
mesg.msg_iov = &vect;
mesg.msg_iovlen = 1;
ctrl_mesg = alloca(sizeof(struct cmsghdr) + sizeof(fd));
ctrl_mesg->cmsg_len = sizeof(struct cmsghdr) + sizeof(fd);
ctrl_mesg->cmsg_level = SOL_SOCKET;
ctrl_mesg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(ctrl_mesg), &fd, sizeof(fd));
mesg.msg_control = ctrl_mesg;
mesg.msg_controllen = ctrl_mesg->cmsg_len;
/* try to send it */
if (sendmsg(in_sock, &mesg, 0) != vect.iov_len) {
fprintf(stderr, "FAIL - could not sendmsg\n");
exit(1);
}
/* Check for info re: reading the file */
if (recv(in_sock, inbound_buffer, 16,0) == -1 ) {
fprintf(stderr, "FAIL - recv %s\n",
strerror(errno));
exit(1);
}
if (strncmp(comparison_buffer, inbound_buffer,10) != 0) {
fprintf(stderr, "FAIL - buffer comparison. Got \"%s\", expected \"%s\"\n", inbound_buffer, comparison_buffer);
exit(1);
} else {
printf("PASS\n");
}
exit(0);
} else {
/* they timed out */
fprintf(stderr, "FAIL - poll() timed out\n");
exit(1);
}
}