diff --git a/bin/cheribsdtest/cheribsdtest_vm.c b/bin/cheribsdtest/cheribsdtest_vm.c index 8e991c918fdd..e539256d1b87 100644 --- a/bin/cheribsdtest/cheribsdtest_vm.c +++ b/bin/cheribsdtest/cheribsdtest_vm.c @@ -177,14 +177,17 @@ CHERIBSDTEST(vm_shm_open_anon_unix_surprise, cheribsdtest_failure_errx("Fork failed; errno=%d", errno); if (pid == 0) { - void * __capability * map; + void * __capability *map; void * __capability c; int fd, tag; struct msghdr msg = { 0 }; struct cmsghdr * cmsg; char cmsgbuf[CMSG_SPACE(sizeof(fd))] = { 0 } ; char iovbuf[16]; - struct iovec iov = { .iov_base = iovbuf, .iov_len = sizeof(iovbuf) }; + struct iovec iov = { + .iov_base = iovbuf, + .iov_len = sizeof(iovbuf) + }; close(sv[1]); @@ -196,15 +199,13 @@ CHERIBSDTEST(vm_shm_open_anon_unix_surprise, CHERIBSDTEST_CHECK_SYSCALL(recvmsg(sv[0], &msg, 0)); /* Deconstruct cmsg */ - /* XXX Doesn't compile: cmsg = CMSG_FIRSTHDR(&msg); */ - cmsg = msg.msg_control; - memmove(&fd, CMSG_DATA(cmsg), sizeof(fd)); + 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, MAP_SHARED, fd, - 0)); + PROT_READ, MAP_SHARED, fd, 0)); c = *map; if (verbose) @@ -219,14 +220,17 @@ CHERIBSDTEST(vm_shm_open_anon_unix_surprise, exit(tag); } else { - void * __capability * map; + void * __capability *map; void * __capability c; int fd, res; struct msghdr msg = { 0 }; struct cmsghdr * cmsg; char cmsgbuf[CMSG_SPACE(sizeof(fd))] = { 0 }; char iovbuf[16] = { 0 }; - struct iovec iov = { .iov_base = iovbuf, .iov_len = sizeof(iovbuf) }; + struct iovec iov = { + .iov_base = iovbuf, + .iov_len = sizeof(iovbuf) + }; close(sv[0]); @@ -252,12 +256,11 @@ CHERIBSDTEST(vm_shm_open_anon_unix_surprise, msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); - /* XXX cmsg = CMSG_FIRSTHDR(&msg); */ - cmsg = msg.msg_control; + 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)); + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); msg.msg_controllen = cmsg->cmsg_len; /* Send! */ @@ -2620,6 +2623,163 @@ CHERIBSDTEST(cheri_revoke_cow_mapping, cheribsdtest_success(); } + +CHERIBSDTEST(cheri_revoke_shm_anon_hoard_unmapped, + "Capability is revoked within an unmapped shm object", + .ct_xfail_reason = "unmapped part of shm objects aren't revoked") +{ + int fd; + void * volatile to_revoke; + void * volatile *map; + + fd = CHERIBSDTEST_CHECK_SYSCALL(shm_open(SHM_ANON, O_RDWR, 0600)); + 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)); + + munmap(__DEVOLATILE(void *, map), getpagesize()); + + free(to_revoke); + malloc_revoke(); + CHERIBSDTEST_VERIFY(check_revoked(to_revoke)); + + 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)); + + 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; + 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; + int fd, res; + struct msghdr msg = { 0 }; + struct cmsghdr * cmsg; + 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)); + 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__ */