xref: /xnu-8796.101.5/tests/vm/vm_test_90774260.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
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_vm.h>
8 #include <mach/vm_map.h>
9 
10 T_GLOBAL_META(
11 	T_META_NAMESPACE("xnu.vm"),
12 	T_META_RADAR_COMPONENT_NAME("xnu"),
13 	T_META_RADAR_COMPONENT_VERSION("VM"));
14 
15 void
test_90774260(void)16 test_90774260(void)
17 {
18 	kern_return_t kr;
19 	mach_vm_size_t vm_size = 1024 * 1024;
20 	int fail = 0;
21 	int original_value;
22 
23 	uint64_t first_layer_addr = 0;
24 	mach_port_t first_layer_entry_port = 0;
25 	kr = mach_memory_object_memory_entry(mach_host_self(),
26 	    1, (vm_size_t) vm_size,
27 	    VM_PROT_READ | VM_PROT_WRITE,
28 	    0, &first_layer_entry_port);
29 	if (kr == MIG_BAD_ID) {
30 		T_FAIL("mach_memory_object_memory_entry() returned MIG_BAD_ID");
31 		return;
32 	}
33 #if __arm64__ && !__LP64__
34 	/*
35 	 * mach_memory_object_memory_entry() is broken on arm64_32.
36 	 * Use mach_make_memory_entry_64(MAP_MEM_NAMED_CREATE) instead.
37 	 */
38 	if (kr == MIG_BAD_ARGUMENTS) {
39 		T_LOG("mach_memory_object_memory_entry() returned MIG_BAD_ARGUMENTS (because broken on arm64_32)");
40 
41 		memory_object_size_t me_size = vm_size;
42 		kr = mach_make_memory_entry_64(mach_task_self(),
43 		    &me_size,
44 		    0,
45 		    VM_PROT_READ | VM_PROT_WRITE | MAP_MEM_NAMED_CREATE,
46 		    &first_layer_entry_port,
47 		    MACH_PORT_NULL);
48 		T_ASSERT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(MAP_MEM_NAMED_CREATE)");
49 	} else
50 #endif /* __arm64__ && !__LP64__ */
51 	{
52 		T_ASSERT_MACH_SUCCESS(kr, "mach_memory_object_memory_entry()");
53 	}
54 
55 	// map the memory to our space
56 	kr = mach_vm_map(mach_task_self(),
57 	    &first_layer_addr,
58 	    vm_size,
59 	    0,                           /* mask */
60 	    VM_FLAGS_ANYWHERE,
61 	    first_layer_entry_port,
62 	    0,                           /* offset */
63 	    0,                           /* copy */
64 	    VM_PROT_READ | VM_PROT_WRITE,
65 	    VM_PROT_READ | VM_PROT_WRITE,
66 	    VM_INHERIT_DEFAULT);
67 	T_ASSERT_MACH_SUCCESS(kr, "mach_vm_map(first_layer_addr)");
68 
69 	original_value = 0xabcd;
70 	*(int*)first_layer_addr = original_value;
71 
72 	// create a COW port
73 	mach_port_t cow_port = MACH_PORT_NULL;
74 	mach_vm_size_t me_size = vm_size;
75 	kr = mach_make_memory_entry_64(mach_task_self(),
76 	    &me_size,
77 	    first_layer_addr,
78 	    (VM_PROT_READ | VM_PROT_WRITE | MAP_MEM_VM_COPY),
79 	    &cow_port,
80 	    0);
81 	T_ASSERT_MACH_SUCCESS(kr, "mach_make_memory_entry_64()");
82 	T_QUIET; T_ASSERT_EQ(me_size, vm_size, "incomplete memory entry");
83 
84 	// map cow port to a new address in the shared way
85 	uint64_t shared_addr = 0;
86 	kr = mach_vm_map(mach_task_self(),
87 	    &shared_addr,
88 	    vm_size,
89 	    0,              /* mask */
90 	    VM_FLAGS_ANYWHERE,
91 	    cow_port,
92 	    0,              /* offset */
93 	    0,              /* copy */
94 	    VM_PROT_READ | VM_PROT_WRITE,
95 	    VM_PROT_READ | VM_PROT_WRITE,
96 	    VM_INHERIT_DEFAULT);
97 	T_ASSERT_MACH_SUCCESS(kr, "mach_vm_map(shared_addr)");
98 
99 	// map cow port to a new address in the COW way
100 	uint64_t cow_addr = 0;
101 	kr = mach_vm_map(mach_task_self(),
102 	    &cow_addr,
103 	    vm_size,
104 	    0,              /* mask */
105 	    VM_FLAGS_ANYWHERE,
106 	    cow_port,
107 	    0,              /* offset */
108 	    1,              /* copy */
109 	    VM_PROT_READ | VM_PROT_WRITE,
110 	    VM_PROT_READ | VM_PROT_WRITE,
111 	    VM_INHERIT_DEFAULT);
112 	T_ASSERT_MACH_SUCCESS(kr, "mach_vm_map(cow_addr)");
113 
114 //	T_LOG("first_layer_addr = 0x%llx", first_layer_addr);
115 //	T_LOG("shared_addr = 0x%llx\n", shared_addr);
116 //	T_LOG("cow_addr = 0x%llx\n", cow_addr);
117 
118 //	T_LOG("*(int*)first_layer_addr = 0x%x", *(int*)first_layer_addr);
119 //	T_LOG("*(int*)shared_addr = 0x%x\n", *(int*)shared_addr);
120 //	T_LOG("*(int*)shared_addr2 = 0x%x\n", *(int*)shared_addr2);
121 //	T_LOG("*(int*)cow_addr = 0x%x\n", *(int*)cow_addr);
122 
123 	T_LOG("write 0x%x to *(int*)shared_addr", 0x1234);
124 	*(int*)shared_addr = 0x1234;
125 
126 	T_LOG("*(int*)first_layer_addr = 0x%x", *(int*)first_layer_addr);
127 	T_LOG("*(int*)shared_addr = 0x%x\n", *(int*)shared_addr);
128 	T_LOG("*(int*)cow_addr = 0x%x\n", *(int*)cow_addr);
129 
130 	if (*(int*)first_layer_addr != original_value) {
131 		T_FAIL("first_layer_addr should not have changed");
132 		fail++;
133 	}
134 	if (*(int *)shared_addr != 0x1234) {
135 		T_FAIL("shared_addr should have changed");
136 		fail++;
137 	}
138 	if (*(int*)cow_addr != original_value) {
139 		T_FAIL("cow_addr should not have changed");
140 		fail++;
141 	}
142 //	T_LOG("pause...");
143 //	getchar();
144 }
145 
146 T_DECL(vm_test_90774260, "Test MAP_MEM_VM_COPY security")
147 {
148 	test_90774260();
149 }
150