diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index f5e0230d3..2cf264719 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -170,6 +170,7 @@ TST_NOFILE := \ scm02 \ scm03 \ scm04 \ + scm05 \ aio00 \ aio01 \ fd \ diff --git a/test/zdtm/static/scm05.c b/test/zdtm/static/scm05.c new file mode 100644 index 000000000..c17bddda3 --- /dev/null +++ b/test/zdtm/static/scm05.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include +#include + +#include "zdtmtst.h" + +const char *test_doc = "Check that SCM_RIGHTS are preserved"; +const char *test_author = "Kirill Tkhai "; + +static int send_fd(int via, int fd) +{ + struct msghdr h = {}; + struct cmsghdr *ch; + struct iovec iov; + char buf[CMSG_SPACE(sizeof(int))]; + char c = '\0'; + int *fdp; + + memset(buf, 0, sizeof(buf)); + h.msg_control = buf; + h.msg_controllen = sizeof(buf); + ch = CMSG_FIRSTHDR(&h); + ch->cmsg_level = SOL_SOCKET; + ch->cmsg_type = SCM_RIGHTS; + ch->cmsg_len = CMSG_LEN(sizeof(int)); + fdp = (int *)CMSG_DATA(ch); + fdp[0] = fd; + + h.msg_iov = &iov; + h.msg_iovlen = 1; + iov.iov_base = &c; + iov.iov_len = sizeof(c); + + if (sendmsg(via, &h, 0) <= 0) + return -1; + + return 0; +} + +static int recv_fd(int via, int *fd) +{ + struct msghdr h = {}; + struct cmsghdr *ch; + struct iovec iov; + char buf[CMSG_SPACE(sizeof(int))]; + char c; + int *fdp; + + h.msg_control = buf; + h.msg_controllen = sizeof(buf); + h.msg_iov = &iov; + h.msg_iovlen = 1; + iov.iov_base = &c; + iov.iov_len = sizeof(c); + + if (recvmsg(via, &h, 0) <= 0) + return -1; + + if (h.msg_flags & MSG_CTRUNC) { + test_msg("CTR\n"); + return -2; + } + + /* No 2 SCM-s here, kernel merges them upon send */ + ch = CMSG_FIRSTHDR(&h); + if (h.msg_flags & MSG_TRUNC) + return -2; + if (ch == NULL) + return -3; + if (ch->cmsg_type != SCM_RIGHTS) + return -4; + + fdp = (int *)CMSG_DATA(ch); + *fd = fdp[0]; + return 0; +} + +int main(int argc, char **argv) +{ + struct epoll_event event = { + .events = EPOLLIN, + }; + int sk[2], ep, ret; + + test_init(argc, argv); + + if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sk) < 0) { + pr_perror("Can't make unix pair"); + exit(1); + } + + ep = epoll_create(1); + if (ep < 0) { + perror("Can't create epoll"); + exit(1); + } + + event.data.fd = sk[1]; + if (epoll_ctl(ep, EPOLL_CTL_ADD, sk[1], &event) < 0) { + perror("Can't add fd"); + exit(1); + } + + if (send_fd(sk[0], ep) < 0) { + pr_perror("Can't send epoll"); + exit(1); + } + if (send_fd(sk[0], ep) < 0) { + pr_perror("Can't send epoll"); + exit(1); + } + + close(ep); + memset(&event, 0, sizeof(event)); + + test_daemon(); + test_waitsig(); + + if (recv_fd(sk[1], &ep) < 0) { + fail("Can't recv epoll back"); + ret = -1; + goto out; + } + + ret = epoll_wait(ep, &event, 1, 0); + if (ret != 1) { + fail("Can't get epoll event"); + ret = -1; + goto out; + } + + pass(); + ret = 0; +out: + return ret; +}