Changeset View
Changeset View
Standalone View
Standalone View
contrib/capsicum-test/capability-fd.cc
Show First 20 Lines • Show All 1,014 Lines • ▼ Show 20 Lines | FORK_TEST_ON(Capability, SocketTransfer, TmpFile("cap_fd_transfer")) { | ||||
cap_rights_t r_rs; | cap_rights_t r_rs; | ||||
cap_rights_init(&r_rs, CAP_READ, CAP_SEEK); | cap_rights_init(&r_rs, CAP_READ, CAP_SEEK); | ||||
pid_t child = fork(); | pid_t child = fork(); | ||||
if (child == 0) { | if (child == 0) { | ||||
// Child: enter cap mode | // Child: enter cap mode | ||||
EXPECT_OK(cap_enter()); | EXPECT_OK(cap_enter()); | ||||
// Child: send startup notification | |||||
int msg = 1234; | |||||
EXPECT_EQ(sizeof(int), (size_t)write(sock_fds[0], &msg, sizeof(msg))); | |||||
// Child: wait to receive FD over socket | // Child: wait to receive FD over socket | ||||
int rc = recvmsg(sock_fds[0], &mh, 0); | int rc = recvmsg(sock_fds[0], &mh, 0); | ||||
EXPECT_OK(rc); | EXPECT_OK(rc); | ||||
EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen); | EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen); | ||||
cmptr = CMSG_FIRSTHDR(&mh); | cmptr = CMSG_FIRSTHDR(&mh); | ||||
int cap_fd = *(int*)CMSG_DATA(cmptr); | int cap_fd = *(int*)CMSG_DATA(cmptr); | ||||
EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len); | EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len); | ||||
cmptr = CMSG_NXTHDR(&mh, cmptr); | cmptr = CMSG_NXTHDR(&mh, cmptr); | ||||
EXPECT_TRUE(cmptr == NULL); | EXPECT_TRUE(cmptr == NULL); | ||||
// Child: confirm we can do the right operations on the capability | // Child: confirm we can do the right operations on the capability | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
EXPECT_OK(cap_rights_get(cap_fd, &rights)); | EXPECT_OK(cap_rights_get(cap_fd, &rights)); | ||||
EXPECT_RIGHTS_EQ(&r_rs, &rights); | EXPECT_RIGHTS_EQ(&r_rs, &rights); | ||||
TryReadWrite(cap_fd); | TryReadWrite(cap_fd); | ||||
// Child: acknowledge that we have received and tested the file descriptor | |||||
msg = 4321; | |||||
EXPECT_EQ(sizeof(int), (size_t)write(sock_fds[0], &msg, sizeof(msg))); | |||||
// Child: wait for a normal read | // Child: wait for a normal read | ||||
int val; | EXPECT_EQ(sizeof(int), (size_t)read(sock_fds[0], &msg, sizeof(msg))); | ||||
read(sock_fds[0], &val, sizeof(val)); | EXPECT_EQ(0, msg); | ||||
exit(0); | exit(testing::Test::HasFailure()); | ||||
} | } | ||||
int fd = open(TmpFile("cap_fd_transfer"), O_RDWR | O_CREAT, 0644); | int fd = open(TmpFile("cap_fd_transfer"), O_RDWR | O_CREAT, 0644); | ||||
EXPECT_OK(fd); | EXPECT_OK(fd); | ||||
if (fd < 0) return; | if (fd < 0) return; | ||||
int cap_fd = dup(fd); | int cap_fd = dup(fd); | ||||
EXPECT_OK(cap_fd); | EXPECT_OK(cap_fd); | ||||
EXPECT_OK(cap_rights_limit(cap_fd, &r_rs)); | EXPECT_OK(cap_rights_limit(cap_fd, &r_rs)); | ||||
EXPECT_OK(cap_enter()); // Enter capability mode. | EXPECT_OK(cap_enter()); // Enter capability mode. | ||||
// Confirm we can do the right operations on the capability | // Confirm we can do the right operations on the capability | ||||
TryReadWrite(cap_fd); | TryReadWrite(cap_fd); | ||||
// Wait for child to start up: | |||||
int msg; | |||||
EXPECT_EQ(sizeof(int), (size_t)read(sock_fds[1], &msg, sizeof(msg))); | |||||
EXPECT_EQ(1234, msg); | |||||
// Send the file descriptor over the pipe to the sub-process | // Send the file descriptor over the pipe to the sub-process | ||||
mh.msg_controllen = CMSG_LEN(sizeof(int)); | mh.msg_controllen = CMSG_LEN(sizeof(int)); | ||||
cmptr = CMSG_FIRSTHDR(&mh); | cmptr = CMSG_FIRSTHDR(&mh); | ||||
cmptr->cmsg_level = SOL_SOCKET; | cmptr->cmsg_level = SOL_SOCKET; | ||||
cmptr->cmsg_type = SCM_RIGHTS; | cmptr->cmsg_type = SCM_RIGHTS; | ||||
cmptr->cmsg_len = CMSG_LEN(sizeof(int)); | cmptr->cmsg_len = CMSG_LEN(sizeof(int)); | ||||
*(int *)CMSG_DATA(cmptr) = cap_fd; | *(int *)CMSG_DATA(cmptr) = cap_fd; | ||||
buffer1[0] = 0; | buffer1[0] = 0; | ||||
iov[0].iov_len = 1; | iov[0].iov_len = 1; | ||||
sleep(3); | |||||
int rc = sendmsg(sock_fds[1], &mh, 0); | int rc = sendmsg(sock_fds[1], &mh, 0); | ||||
EXPECT_OK(rc); | EXPECT_OK(rc); | ||||
sleep(1); // Ensure subprocess runs | // Check that the child received the message | ||||
int zero = 0; | EXPECT_EQ(sizeof(int), (size_t)read(sock_fds[1], &msg, sizeof(msg))); | ||||
write(sock_fds[1], &zero, sizeof(zero)); | EXPECT_EQ(4321, msg); | ||||
// Tell the child to exit | |||||
msg = 0; | |||||
EXPECT_EQ(sizeof(int), (size_t)write(sock_fds[1], &msg, sizeof(msg))); | |||||
} | } | ||||
TEST(Capability, SyscallAt) { | TEST(Capability, SyscallAt) { | ||||
int rc = mkdir(TmpFile("cap_at_topdir"), 0755); | int rc = mkdir(TmpFile("cap_at_topdir"), 0755); | ||||
EXPECT_OK(rc); | EXPECT_OK(rc); | ||||
if (rc < 0 && errno != EEXIST) return; | if (rc < 0 && errno != EEXIST) return; | ||||
cap_rights_t r_all; | cap_rights_t r_all; | ||||
▲ Show 20 Lines • Show All 255 Lines • Show Last 20 Lines |