@@ -616,3 +616,72 @@ CHERIBSDTEST(cheribsdtest_vm_cow_write,
616
616
CHERIBSDTEST_CHECK_SYSCALL (close (fd ));
617
617
cheribsdtest_success ();
618
618
}
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