@@ -602,3 +602,73 @@ cheribsdtest_vm_cow_write(const struct cheri_test *ctp __unused)
602
602
CHERIBSDTEST_CHECK_SYSCALL (close (fd ));
603
603
cheribsdtest_success ();
604
604
}
605
+
606
+ /*
607
+ * Store a cap to a page and check that mincore reports it CAPSTORE.
608
+ *
609
+ * Due to a shortage of bits in mincore()'s uint8_t reporting bit vector, this
610
+ * particular test is not able to distinguish CAPSTORE and CAPDIRTY and so is
611
+ * not sensitive to the vm.pmap.enter_capstore_as_capdirty sysctl.
612
+ *
613
+ * On the other hand, this test is sensitive to the vm.capstore_on_alloc sysctl:
614
+ * if that is asserted, our cap-capable anonymous memory will be installed
615
+ * CAPSTORE (and possibly even CAPDIRTY, in light of the above) whereas, if this
616
+ * sysctl is clear, our initial view of said memory will be !CAPSTORE.
617
+ */
618
+ void
619
+ cheribsdtest_vm_capdirty (const struct cheri_test * ctp __unused )
620
+ {
621
+ static const size_t npg = 2 ;
622
+ size_t sz = npg * getpagesize ();
623
+ uint8_t capstore_on_alloc ;
624
+ size_t capstore_on_alloc_sz = sizeof (capstore_on_alloc );
625
+
626
+ void * __capability * pg0 ;
627
+ unsigned char mcv [npg ] = { 0 };
628
+
629
+ CHERIBSDTEST_CHECK_SYSCALL (
630
+ sysctlbyname ("vm.capstore_on_alloc" , & capstore_on_alloc ,
631
+ & capstore_on_alloc_sz , NULL , 0 ));
632
+
633
+ pg0 = CHERIBSDTEST_CHECK_SYSCALL (
634
+ mmap (NULL , sz , PROT_READ | PROT_WRITE , MAP_ANON , -1 , 0 ));
635
+
636
+ void * __capability * pg1 = (void * )& ((char * )pg0 )[getpagesize ()];
637
+
638
+ /*
639
+ * Pages are ZFOD and so will not be CAPSTORE, or, really, anything
640
+ * else, either.
641
+ */
642
+ CHERIBSDTEST_CHECK_SYSCALL (mincore (pg0 , sz , & mcv [0 ]));
643
+ CHERIBSDTEST_VERIFY2 (mcv [0 ] == 0 , "page 0 status 0" );
644
+ CHERIBSDTEST_VERIFY2 (mcv [1 ] == 0 , "page 1 status 0" );
645
+
646
+ /*
647
+ * Write data to page 0, causing it to become allocated and MODIFIED.
648
+ * If vm.capstore_on_alloc, then it should be CAPSTORE as well, despite
649
+ * having never been the target of a capability store.
650
+ */
651
+ * (char * )pg0 = 0x42 ;
652
+
653
+ CHERIBSDTEST_CHECK_SYSCALL (mincore (pg0 , sz , & mcv [0 ]));
654
+ CHERIBSDTEST_VERIFY2 (
655
+ (mcv [0 ] & MINCORE_MODIFIED ) != 0 , "page 0 modified 1" );
656
+ CHERIBSDTEST_VERIFY2 (
657
+ !(mcv [0 ] & MINCORE_CAPSTORE ) == !capstore_on_alloc ,
658
+ "page 0 capstore 1" );
659
+
660
+ /*
661
+ * Write a capability to page 1 and check that it is MODIFIED and
662
+ * CAPSTORE regardless of vm.capstore_on_alloc.
663
+ */
664
+ * pg1 = (void * __capability )pg0 ;
665
+
666
+ CHERIBSDTEST_CHECK_SYSCALL (mincore (pg0 , sz , & mcv [0 ]));
667
+ CHERIBSDTEST_VERIFY2 (
668
+ (mcv [1 ] & MINCORE_MODIFIED ) != 0 , "page 1 modified 2" );
669
+ CHERIBSDTEST_VERIFY2 (
670
+ (mcv [1 ] & MINCORE_CAPSTORE ) != 0 , "page 1 capstore 2" );
671
+
672
+ CHERIBSDTEST_CHECK_SYSCALL (munmap (pg0 , sz ));
673
+ cheribsdtest_success ();
674
+ }
0 commit comments