Skip to content

Commit

Permalink
cheribsdtest: hoarding by closed shm object
Browse files Browse the repository at this point in the history
Add cheri_revoke_shm_anon_hoard_closed which:
 - creates and maps a shared memory object
 - stores a pointer to malloced memory in the mapped object
 - unmaps the object
 - send the shared object file descriptor to a child process
 - closes the file descriptor
 - frees the pointer and triggers revocation
 - recieves the file descriptor back from the child process
 - remaps the object
 - checks that the stored pointer was revoked (it is not)

This demostrates the futility of scanning the descriptor table for
shared memory objects during revocation and the necessity to bind them
to an address space.  (Lest one think it's possible to walk the graph
of sockets to find the graph of processes that might have a shared
memory object to search, the child could be replaced by a completely
independent hoarder daemon running on a unix domain socket in the file
system.)
  • Loading branch information
brooksdavis committed Aug 28, 2024
1 parent e7d35a8 commit b4857a5
Showing 1 changed file with 142 additions and 0 deletions.
142 changes: 142 additions & 0 deletions bin/cheribsdtest/cheribsdtest_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2657,6 +2657,148 @@ CHERIBSDTEST(cheri_revoke_shm_anon_hoard_unmapped,
cheribsdtest_success();
}

CHERIBSDTEST(cheri_revoke_shm_anon_hoard_closed,
"Capability is revoked within an unmapped and closed shm object",
.ct_xfail_reason = "unmapped part of shm objects aren't revoked")
{
int sv[2];
int pid;

CHERIBSDTEST_CHECK_SYSCALL(socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) != 0);

pid = fork();
if (pid == -1)
cheribsdtest_failure_errx("Fork failed; errno=%d", errno);

if (pid == 0) {
int fd;
struct msghdr msg = { 0 };
struct cmsghdr * cmsg;

Check failure on line 2676 in bin/cheribsdtest/cheribsdtest_vm.c

View workflow job for this annotation

GitHub Actions / Style Checker

"foo * bar" should be "foo *bar"
char cmsgbuf[CMSG_SPACE(sizeof(fd))] = { 0 } ;
char iovbuf[16];
struct iovec iov = {
.iov_base = iovbuf,
.iov_len = sizeof(iovbuf)
};

close(sv[1]);

/* Read from socket */
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
CHERIBSDTEST_CHECK_SYSCALL(recvmsg(sv[0], &msg, 0));

/* Deconstruct cmsg */
cmsg = CMSG_FIRSTHDR(&msg);
memmove(&fd, CMSG_DATA(cmsg), sizeof(fd));

CHERIBSDTEST_VERIFY2(fd >= 0, "fd read OK");

/*
* Pack the fd up and send it back.
*/

/* Construct control message */
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof fd);
memmove(CMSG_DATA(cmsg), &fd, sizeof(fd));
msg.msg_controllen = cmsg->cmsg_len;

/* Send! */
CHERIBSDTEST_CHECK_SYSCALL(sendmsg(sv[0], &msg, 0));

close(sv[0]);
close(fd);

exit(0);
} else {
void * volatile to_revoke;
void * volatile * map;

Check failure on line 2724 in bin/cheribsdtest/cheribsdtest_vm.c

View workflow job for this annotation

GitHub Actions / Style Checker

"foo * volatile * bar" should be "foo * volatile *bar"

Check failure on line 2724 in bin/cheribsdtest/cheribsdtest_vm.c

View workflow job for this annotation

GitHub Actions / Style Checker

space prohibited after that '*' (ctx:WxW)
int fd, res;
struct msghdr msg = { 0 };
struct cmsghdr * cmsg;

Check failure on line 2727 in bin/cheribsdtest/cheribsdtest_vm.c

View workflow job for this annotation

GitHub Actions / Style Checker

"foo * bar" should be "foo *bar"
char cmsgbuf[CMSG_SPACE(sizeof(fd))] = { 0 };
char iovbuf[16] = { 0 };
struct iovec iov = {
.iov_base = iovbuf,
.iov_len = sizeof(iovbuf)
};

close(sv[0]);

fd = CHERIBSDTEST_CHECK_SYSCALL(shm_open(SHM_ANON, O_RDWR, 0600));

Check warning on line 2737 in bin/cheribsdtest/cheribsdtest_vm.c

View workflow job for this annotation

GitHub Actions / Style Checker

line over 80 characters
CHERIBSDTEST_CHECK_SYSCALL(ftruncate(fd, getpagesize()));

map = CHERIBSDTEST_CHECK_SYSCALL(mmap(NULL, getpagesize(),
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));

to_revoke = malloc(1);
*map = to_revoke;
CHERIBSDTEST_VERIFY(cheri_gettag(*map));

CHERIBSDTEST_CHECK_SYSCALL(munmap(__DEVOLATILE(void *, map),
getpagesize()));

/* Construct control message */
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof fd);
memmove(CMSG_DATA(cmsg), &fd, sizeof(fd));
msg.msg_controllen = cmsg->cmsg_len;

/* Send! */
CHERIBSDTEST_CHECK_SYSCALL(sendmsg(sv[1], &msg, 0));
close(fd);

/* Revoke the pointer */
free(to_revoke);
malloc_revoke();
CHERIBSDTEST_VERIFY(check_revoked(to_revoke));

/* Read from socket */
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
CHERIBSDTEST_CHECK_SYSCALL(recvmsg(sv[1], &msg, 0));

/* Deconstruct cmsg */
cmsg = CMSG_FIRSTHDR(&msg);
memmove(&fd, CMSG_DATA(cmsg), sizeof(fd));

CHERIBSDTEST_VERIFY2(fd >= 0, "fd read OK");

map = CHERIBSDTEST_CHECK_SYSCALL(mmap(NULL, getpagesize(),
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));

CHERIBSDTEST_VERIFY(to_revoke == *map);
CHERIBSDTEST_VERIFY(check_revoked(*map));

close(sv[1]);
close(fd);

waitpid(pid, &res, 0);
if (res == 0) {
cheribsdtest_success();
} else {
cheribsdtest_failure_errx("child failed");
}
}
}

#endif /* CHERIBSDTEST_CHERI_REVOKE_TESTS */

#endif /* __CHERI_PURE_CAPABILITY__ */

Check failure on line 2804 in bin/cheribsdtest/cheribsdtest_vm.c

View workflow job for this annotation

GitHub Actions / Style Checker

Missing Signed-off-by: line

0 comments on commit b4857a5

Please sign in to comment.