Following update on Ubuntu Xenial, the following test case fails: #include <gtest/gtest.h> #include <gmock/gmock.h> #include <sys/socket.h> #include <sys/stat.h> TEST(IsItBroken, recvmsg) { using namespace testing; enum { server, client, size }; int socket_fd[size]; int const opt = 1; ASSERT_THAT(socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fd), Eq(0)); auto const msg = "A random message"; send(socket_fd[client], msg, sizeof msg, MSG_DONTWAIT | MSG_NOSIGNAL); ASSERT_THAT(setsockopt(socket_fd[server], SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)), Ne(-1)); union { struct cmsghdr cmh; char control[CMSG_SPACE(sizeof(ucred))]; } control_un; control_un.cmh.cmsg_len = CMSG_LEN(sizeof(ucred)); control_un.cmh.cmsg_level = SOL_SOCKET; control_un.cmh.cmsg_type = SCM_CREDENTIALS; msghdr msgh; msgh.msg_name = nullptr; msgh.msg_namelen = 0; msgh.msg_iov = nullptr; msgh.msg_iovlen = 0; msgh.msg_control = control_un.control; msgh.msg_controllen = sizeof(control_un.control); errno = 0; EXPECT_THAT(recvmsg(socket_fd[server], &msgh, MSG_PEEK), Ne(-1)) << "Error: " << strerror(errno); for (auto socket : socket_fd) close(socket); }
Can you post a test case which does not need an external test framework, the output you get, and the output you expect?
Additional information: this happens with the latest Xenial 4.4.0-2-generic kernel, but not with the previous 4.3.0-7-generic kernel. Revised test case: #include <stdlib.h> #include <stdio.h> #include <sys/socket.h> #include <sys/stat.h> #include <assert.h> #include <errno.h> #include <string.h> int main() { enum { server, client, size }; int socket_fd[size]; int const opt = 1; assert(socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fd) == 0); char const msg[] = "A random message"; send(socket_fd[client], msg, sizeof msg, MSG_DONTWAIT | MSG_NOSIGNAL); assert(setsockopt(socket_fd[server], SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)) != -1); union { struct cmsghdr cmh; char control[CMSG_SPACE(sizeof(ucred))]; } control_un; control_un.cmh.cmsg_len = CMSG_LEN(sizeof(ucred)); control_un.cmh.cmsg_level = SOL_SOCKET; control_un.cmh.cmsg_type = SCM_CREDENTIALS; msghdr msgh; msgh.msg_name = NULL; msgh.msg_namelen = 0; msgh.msg_iov = NULL; msgh.msg_iovlen = 0; msgh.msg_control = control_un.control; msgh.msg_controllen = sizeof(control_un.control); errno = 0; if (recvmsg(socket_fd[server], &msgh, MSG_PEEK) == -1) { printf("Error: %s\n", strerror(errno)); exit(EXIT_FAILURE); } else { printf("Success!\n"); exit(EXIT_FAILURE); } } Expected: $ g++ test.c -o test && ./test Success! Actual: $ g++ test.c -o test && ./test Error: Operation not supported
Thanks. This happens with kernel-4.5.0-0.rc1.git2.1.fc24.x86_64 as well. strace shows: socketpair(PF_LOCAL, SOCK_STREAM, 0, [3, 4]) = 0 sendto(4, "A random message\0", 17, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 17 setsockopt(3, SOL_SOCKET, SO_PASSCRED, [1], 4) = 0 recvmsg(3, 0x7ffdd7e17400, MSG_PEEK) = -1 EOPNOTSUPP (Operation not supported) This looks like a kernel regression. Please report it to the kernel developers.