diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index 39326c729..83cc5bec0 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -487,6 +487,7 @@ TST_DIR = \ sk-unix-mntns \ sk-unix01 \ sk-unix01-seqpacket \ + sk-unix-dgram-cred \ sk-unix-dgram-ghost \ unsupported_children_collision \ shared_slave_mount_children \ diff --git a/test/zdtm/static/sk-unix-dgram-cred.c b/test/zdtm/static/sk-unix-dgram-cred.c new file mode 100644 index 000000000..e0f4713f2 --- /dev/null +++ b/test/zdtm/static/sk-unix-dgram-cred.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "zdtmtst.h" + +const char *test_doc = "Test SCM_CREDENTIALS checkpoint/restore in unix socket queue\n"; +const char *test_author = "Ahmed Elaidy "; + +char *dirname; +TEST_OPTION(dirname, string, "directory name", 1); + +int main(int argc, char *argv[]) +{ + int sk[2]; + struct msghdr msg = {}; + struct iovec iov; + char buf[64]; + char cmsg_buf[CMSG_SPACE(sizeof(struct ucred))]; + struct cmsghdr *cmsg; + struct ucred *cred; + struct ucred send_cred; + int opt = 1; + + test_init(argc, argv); + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sk) < 0) + return pr_perror("socketpair"); + + if (setsockopt(sk[1], SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)) < 0) + return pr_perror("setsockopt SO_PASSCRED"); + + /* Send a message with SCM_CREDENTIALS */ + send_cred.pid = getpid(); + send_cred.uid = getuid(); + send_cred.gid = getgid(); + + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + + memset(cmsg_buf, 0, sizeof(cmsg_buf)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsg_buf; + msg.msg_controllen = sizeof(cmsg_buf); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + memcpy(CMSG_DATA(cmsg), &send_cred, sizeof(struct ucred)); + + strcpy(buf, "hello"); + if (sendmsg(sk[0], &msg, 0) < 0) + return pr_perror("sendmsg"); + + test_daemon(); + test_waitsig(); + + /* Receive and verify credentials after restore */ + memset(buf, 0, sizeof(buf)); + memset(cmsg_buf, 0, sizeof(cmsg_buf)); + msg.msg_control = cmsg_buf; + msg.msg_controllen = sizeof(cmsg_buf); + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + + if (recvmsg(sk[1], &msg, 0) < 0) + return pr_perror("recvmsg"); + + cmsg = CMSG_FIRSTHDR(&msg); + if (!cmsg) { + fail("no cmsg after restore"); + return 1; + } + + if (cmsg->cmsg_type != SCM_CREDENTIALS) { + fail("wrong cmsg type after restore"); + return 1; + } + + cred = (struct ucred *)CMSG_DATA(cmsg); + + if (cred->uid != send_cred.uid || cred->gid != send_cred.gid) { + fail("credentials mismatch after restore: " + "uid %d/%d gid %d/%d", + cred->uid, send_cred.uid, + cred->gid, send_cred.gid); + return 1; + } + + close(sk[0]); + close(sk[1]); + + pass(); + return 0; +} \ No newline at end of file