1 #include <darwintest.h> 2 3 #include <stdlib.h> 4 5 #include <mach/mach_host.h> 6 #include <mach/mach_init.h> 7 #include <mach/mach_port.h> 8 #include <mach/mach_vm.h> 9 #include <mach/vm_map.h> 10 11 T_GLOBAL_META( 12 T_META_NAMESPACE("xnu.vm"), 13 T_META_RADAR_COMPONENT_NAME("xnu"), 14 T_META_RADAR_COMPONENT_VERSION("VM")); 15 16 T_DECL(vm_test_102067976, "Test dangling PTE due to mis-aligned memory entry") 17 { 18 kern_return_t kr; 19 mach_vm_size_t vm_named_entry_size, vm_map_entry_size; 20 mach_vm_offset_t vm_named_entry_offset, vm_map_entry_offset; 21 mach_port_t named_entry; 22 mach_vm_address_t address; 23 24 vm_named_entry_size = 2 * PAGE_SIZE + 1; /* misaligned! */ 25 vm_named_entry_offset = 0; 26 vm_map_entry_size = 2 * PAGE_SIZE; 27 vm_map_entry_offset = PAGE_SIZE; 28 29 named_entry = MACH_PORT_NULL; 30 kr = mach_memory_object_memory_entry(mach_host_self(), 31 1, (vm_size_t) vm_named_entry_size, 32 VM_PROT_READ | VM_PROT_WRITE, 33 MEMORY_OBJECT_NULL, &named_entry); 34 if (kr == MIG_BAD_ID) { 35 T_FAIL("mach_memory_object_memory_entry() returned MIG_BAD_ID"); 36 return; 37 } 38 #if __arm64__ && !__LP64__ 39 /* 40 * mach_memory_object_memory_entry() is broken on arm64_32. 41 */ 42 if (kr == MIG_BAD_ARGUMENTS) { 43 T_SKIP("mach_memory_object_memory_entry() returned MIG_BAD_ARGUMENTS (because broken on arm64_32)"); 44 return; 45 } 46 #endif /* __arm64__ && !__LP64__ */ 47 T_ASSERT_MACH_SUCCESS(kr, "mach_memory_object_memory_entry()"); 48 T_QUIET; T_ASSERT_NE(named_entry, MACH_PORT_NULL, "named_entry is not null"); 49 50 /* map the memory to our space */ 51 address = 0; 52 kr = mach_vm_map(mach_task_self(), 53 &address, 54 (-1), /* not 0 but rounds up to 0 */ 55 0, /* mask */ 56 VM_FLAGS_ANYWHERE, 57 named_entry, 58 vm_map_entry_offset, /* offset */ 59 FALSE, /* copy */ 60 VM_PROT_DEFAULT, 61 VM_PROT_DEFAULT, 62 VM_INHERIT_DEFAULT); 63 if (kr == KERN_INVALID_ARGUMENT) { 64 /* no longer vulnerable */ 65 T_PASS("mach_vm_map(size=-1) no longer succeeds"); 66 return; 67 } 68 T_ASSERT_MACH_SUCCESS(kr, "mach_vm_map()"); 69 70 /* fault in last page + dangling one */ 71 memset((char *)address, 'x', vm_map_entry_size); 72 73 /* unmap the memory */ 74 kr = mach_vm_deallocate(mach_task_self(), address, vm_map_entry_size); 75 T_ASSERT_MACH_SUCCESS(kr, "mach_vm_deallocate()"); 76 77 /* release named entry */ 78 kr = mach_port_deallocate(mach_task_self(), named_entry); 79 T_ASSERT_MACH_SUCCESS(kr, "mach_port_deallocate()"); 80 81 T_PASS("no panic!"); 82 } 83