]> git.saurik.com Git - apple/xnu.git/blob - tests/sysctl_get_owned_vmobjects.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tests / sysctl_get_owned_vmobjects.c
1 #include <darwintest.h>
2 #include <darwintest_utils.h>
3 #include <mach/mach.h>
4 #include <mach/task_info.h>
5 #include <mach/vm_region.h>
6 #include <mach/mach_vm.h>
7 #include <sys/kern_sysctl.h>
8 #include <errno.h>
9
10 static const char* g_sysctl_name = "vm.get_owned_vmobjects";
11
12 static void
13 main_test(void)
14 {
15 int ret;
16 mach_port_name_t task_name;
17 vmobject_list_output_t out_buffer;
18 size_t out_size;
19 size_t output_size;
20 const vm_size_t tmp_size = 16 * 1024 * 1024; /* arbitrary size */
21 vm_address_t tmp_buf;
22 vm_address_t tmp_buf2;
23 mach_vm_size_t addr_size;
24 mach_vm_address_t addr;
25 kern_return_t kr;
26 mach_port_t __self = mach_task_self();
27 vm_region_submap_info_data_64_t regionInfo;
28 uint32_t nestingDepth;
29 mach_msg_type_number_t count;
30
31 /* allocate a temporary buffer */
32 kr = vm_allocate(__self, &tmp_buf, tmp_size, VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
33 T_QUIET;
34 T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_allocate(%zu) error 0x%x (%s)",
35 (size_t) tmp_size, kr, mach_error_string(kr));
36 T_QUIET;
37 T_EXPECT_NE(tmp_buf, (vm_address_t) 0, "failed to allocate temporary purgable buffer\n");
38
39 kr = vm_allocate(__self, &tmp_buf2, tmp_size, VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
40 T_QUIET;
41 T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_allocate(%zu) error 0x%x (%s)",
42 (size_t) tmp_size, kr, mach_error_string(kr));
43 T_QUIET;
44 T_EXPECT_NE(tmp_buf2, (vm_address_t) 0, "failed to allocate temporary purgable buffer\n");
45
46 /* expected failures */
47 out_size = tmp_size;
48 ret = sysctlbyname(g_sysctl_name, NULL, 0, NULL, 0);
49 T_EXPECT_EQ(ret, -1, "expected failure with 0 parameters\n");
50 T_EXPECT_EQ(errno, EINVAL, "expected EINVAL with 0 parameters\n");
51
52 ret = sysctlbyname(g_sysctl_name, (void*) tmp_buf, &out_size, NULL, 0);
53 T_EXPECT_EQ(ret, -1, "expected failure with no new parameters\n");
54 T_EXPECT_EQ(errno, EINVAL, "expected EINVAL with 0 new parameters\n");
55
56 out_size = tmp_size;
57 ret = sysctlbyname(g_sysctl_name, NULL, 0, (void*) tmp_buf, out_size);
58 T_EXPECT_EQ(ret, -1, "expected failure with no old parameters\n");
59 T_EXPECT_EQ(errno, EINVAL, "expected EINVAL with 0 old parameters\n");
60
61 task_name = MACH_PORT_NULL;
62 ret = sysctlbyname(g_sysctl_name, (void*) tmp_buf, &out_size, &task_name, sizeof(task_name));
63 T_EXPECT_EQ(ret, -1, "expected failure with task_name == MACH_PORT_NULL in new parameters\n");
64 T_EXPECT_EQ(errno, ESRCH, "expected ESRCH with invalid task port name\n");
65
66 /* we should get the number of entries we should allocate for */
67 out_size = 0;
68 output_size = 0;
69 task_name = mach_task_self();
70 ret = sysctlbyname(g_sysctl_name, NULL, &out_size, &task_name, sizeof(task_name));
71 T_QUIET;
72 T_EXPECT_EQ(ret, 0, "failed getting the number of entries\n");
73 T_EXPECT_EQ(out_size, 2 * sizeof(vm_object_query_data_t) + sizeof(int64_t), "expeccted one entry\n");
74
75 /* calculcate and allocate the proper sized output buffer */
76 output_size = out_size;
77 out_buffer = (vmobject_list_output_t)calloc(output_size, 1);
78 T_QUIET;
79 T_EXPECT_NE(out_buffer, NULL, "failed to allocate the output buffer for sysctlbyname\n");
80
81 /* get the truncated list for the current process */
82 memset(out_buffer, 0, output_size);
83 out_size = 1 * sizeof(vm_object_query_data_t) + sizeof(int64_t);
84 ret = sysctlbyname(g_sysctl_name, out_buffer, &out_size, &task_name, sizeof(task_name));
85
86 T_QUIET;
87 T_EXPECT_EQ(ret, 0, "sysctlbyname failed\n");
88 T_EXPECT_EQ(out_size, 1 * sizeof(vm_object_query_data_t) + sizeof(int64_t), "sysctl return size is incorrect\n");
89 T_EXPECT_EQ(out_buffer->entries, 1ULL, "should have 1 vm object\n");
90 T_EXPECT_NE(out_buffer->data[0].object_id, 0ULL, "vm_object_id should not be 0\n");
91
92 /* get the list for the current process with an overly large size */
93 out_size = SIZE_MAX;
94 memset(out_buffer, 0, output_size);
95 ret = sysctlbyname(g_sysctl_name, out_buffer, &out_size, &task_name, sizeof(task_name));
96
97 T_QUIET;
98 T_EXPECT_EQ(ret, 0, "sysctlbyname failed\n");
99 T_EXPECT_EQ(out_size, 2 * sizeof(vm_object_query_data_t) + sizeof(int64_t), "sysctl return size is incorrect\n");
100 T_EXPECT_EQ(out_buffer->entries, 2ULL, "should have 2 vm objects\n");
101 T_EXPECT_NE(out_buffer->data[0].object_id, 0ULL, "vm_object_id should not be 0\n");
102
103 /* get the list for the current process with the correct output size */
104 out_size = output_size;
105 memset(out_buffer, 0, output_size);
106 ret = sysctlbyname(g_sysctl_name, out_buffer, &out_size, &task_name, sizeof(task_name));
107
108 T_QUIET;
109 T_EXPECT_EQ(ret, 0, "sysctlbyname failed\n");
110 T_EXPECT_EQ(out_size, 2 * sizeof(vm_object_query_data_t) + sizeof(int64_t), "sysctl return size is incorrect\n");
111 T_EXPECT_EQ(out_buffer->entries, 2ULL, "should have 2 vm objects\n");
112 T_EXPECT_NE(out_buffer->data[0].object_id, 0ULL, "vm_object_id should not be 0\n");
113
114 addr = tmp_buf;
115 addr_size = tmp_size;
116 nestingDepth = UINT_MAX;
117 count = VM_REGION_SUBMAP_INFO_V2_COUNT_64;
118 kr = mach_vm_region_recurse(__self, &addr, &addr_size, &nestingDepth, (vm_region_info_t)&regionInfo, &count);
119 T_QUIET;
120 T_EXPECT_EQ(kr, KERN_SUCCESS, "mach_vm_region_recurse(%zu) error 0x%x (%s)\n",
121 tmp_size, kr, mach_error_string(kr));
122 T_EXPECT_EQ(regionInfo.object_id_full, out_buffer->data[0].object_id, "object_id_full does not match out_buffer->object[0]\n");
123
124 addr = tmp_buf2;
125 addr_size = tmp_size;
126 nestingDepth = UINT_MAX;
127 count = VM_REGION_SUBMAP_INFO_V2_COUNT_64;
128 kr = mach_vm_region_recurse(__self, &addr, &addr_size, &nestingDepth, (vm_region_info_t)&regionInfo, &count);
129 T_QUIET;
130 T_EXPECT_EQ(kr, KERN_SUCCESS, "mach_vm_region_recurse(%zu) error 0x%x (%s)\n",
131 tmp_size, kr, mach_error_string(kr));
132 T_EXPECT_EQ(regionInfo.object_id_full, out_buffer->data[1].object_id, "object_id_full does not match out_buffer->object[1]\n");
133
134 kr = vm_deallocate(__self, tmp_buf, tmp_size);
135 T_QUIET;
136 T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate(%zu) error 0x%x (%s)\n",
137 tmp_size, kr, mach_error_string(kr));
138
139 kr = vm_deallocate(__self, tmp_buf2, tmp_size);
140 T_QUIET;
141 T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate(%zu) error 0x%x (%s)\n",
142 tmp_size, kr, mach_error_string(kr));
143
144 free(out_buffer);
145 out_buffer = NULL;
146 }
147
148 T_DECL(test_get_vmobject_list, "Get owned vm_objects for process")
149 {
150 main_test();
151 }