Skip to content

Commit 903b3ca

Browse files
nwfbrettferdosi
authored andcommitted
capdirty: first, minimal test in cheritest
Co-authored-by: Brett Gutstein <[email protected]>
1 parent ba22185 commit 903b3ca

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

bin/cheribsdtest/cheribsdtest_vm.c

+69
Original file line numberDiff line numberDiff line change
@@ -616,3 +616,72 @@ CHERIBSDTEST(cheribsdtest_vm_cow_write,
616616
CHERIBSDTEST_CHECK_SYSCALL(close(fd));
617617
cheribsdtest_success();
618618
}
619+
620+
/*
621+
* Store a cap to a page and check that mincore reports it CAPSTORE.
622+
*
623+
* Due to a shortage of bits in mincore()'s uint8_t reporting bit vector, this
624+
* particular test is not able to distinguish CAPSTORE and CAPDIRTY and so is
625+
* not sensitive to the vm.pmap.enter_capstore_as_capdirty sysctl.
626+
*
627+
* On the other hand, this test is sensitive to the vm.capstore_on_alloc sysctl:
628+
* if that is asserted, our cap-capable anonymous memory will be installed
629+
* CAPSTORE (and possibly even CAPDIRTY, in light of the above) whereas, if this
630+
* sysctl is clear, our initial view of said memory will be !CAPSTORE.
631+
*/
632+
CHERIBSDTEST(cheribsdtest_vm_capdirty, "verify capdirty marking and mincore")
633+
{
634+
static const size_t npg = 2;
635+
size_t sz = npg * getpagesize();
636+
uint8_t capstore_on_alloc;
637+
size_t capstore_on_alloc_sz = sizeof(capstore_on_alloc);
638+
639+
void * __capability *pg0;
640+
unsigned char mcv[npg] = { 0 };
641+
642+
CHERIBSDTEST_CHECK_SYSCALL(
643+
sysctlbyname("vm.capstore_on_alloc", &capstore_on_alloc,
644+
&capstore_on_alloc_sz, NULL, 0));
645+
646+
pg0 = CHERIBSDTEST_CHECK_SYSCALL(
647+
mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0));
648+
649+
void * __capability *pg1 = (void *)&((char *)pg0)[getpagesize()];
650+
651+
/*
652+
* Pages are ZFOD and so will not be CAPSTORE, or, really, anything
653+
* else, either.
654+
*/
655+
CHERIBSDTEST_CHECK_SYSCALL(mincore(pg0, sz, &mcv[0]));
656+
CHERIBSDTEST_VERIFY2(mcv[0] == 0, "page 0 status 0");
657+
CHERIBSDTEST_VERIFY2(mcv[1] == 0, "page 1 status 0");
658+
659+
/*
660+
* Write data to page 0, causing it to become allocated and MODIFIED.
661+
* If vm.capstore_on_alloc, then it should be CAPSTORE as well, despite
662+
* having never been the target of a capability store.
663+
*/
664+
*(char *)pg0 = 0x42;
665+
666+
CHERIBSDTEST_CHECK_SYSCALL(mincore(pg0, sz, &mcv[0]));
667+
CHERIBSDTEST_VERIFY2(
668+
(mcv[0] & MINCORE_MODIFIED) != 0, "page 0 modified 1");
669+
CHERIBSDTEST_VERIFY2(
670+
!(mcv[0] & MINCORE_CAPSTORE) == !capstore_on_alloc,
671+
"page 0 capstore 1");
672+
673+
/*
674+
* Write a capability to page 1 and check that it is MODIFIED and
675+
* CAPSTORE regardless of vm.capstore_on_alloc.
676+
*/
677+
*pg1 = (__cheri_tocap void * __capability)pg0;
678+
679+
CHERIBSDTEST_CHECK_SYSCALL(mincore(pg0, sz, &mcv[0]));
680+
CHERIBSDTEST_VERIFY2(
681+
(mcv[1] & MINCORE_MODIFIED) != 0, "page 1 modified 2");
682+
CHERIBSDTEST_VERIFY2(
683+
(mcv[1] & MINCORE_CAPSTORE) != 0, "page 1 capstore 2");
684+
685+
CHERIBSDTEST_CHECK_SYSCALL(munmap(pg0, sz));
686+
cheribsdtest_success();
687+
}

0 commit comments

Comments
 (0)