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
 - receives 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 30, 2024
1 parent 071b76c commit a9235c1
Showing 1 changed file with 123 additions and 0 deletions.
123 changes: 123 additions & 0 deletions bin/cheribsdtest/cheribsdtest_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2657,6 +2657,129 @@ 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);
memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));

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

/* Send the fd back. */
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 2708 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 2708 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 2711 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 2721 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);
memcpy(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));

/* Receive the fd back */
msg.msg_controllen = sizeof(cmsgbuf);
CHERIBSDTEST_CHECK_SYSCALL(recvmsg(sv[1], &msg, 0));

/* Deconstruct cmsg */
cmsg = CMSG_FIRSTHDR(&msg);
memcpy(&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 warning on line 2785 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 a9235c1

Please sign in to comment.