]> git.saurik.com Git - apple/xnu.git/blob - tests/iokit/io_catalog_send_data.m
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tests / iokit / io_catalog_send_data.m
1 /*
2 * io_catalog_send_data.m
3 *
4 * A regression test to build an IORegistry entry with mismatching
5 * IOService and IOUserClientClass via IOCatalogueSendData, to verify
6 * if exploit risk still exists in IOCatalogueSendData.
7 *
8 */
9 #include <darwintest.h>
10
11 #include <Foundation/Foundation.h>
12 #include <IOKit/IOCFSerialize.h>
13 #include <IOKit/IOKitLib.h>
14
15 #define kIOClassKey @"IOClass"
16 #define kIOProviderClassKey @"IOProviderClass"
17 #define kIOMatchCategoryKey @"IOMatchCategory"
18 #define kIOUserClientClassKey @"IOUserClientClass"
19 #define vIOProviderClassValue @"IOResources"
20
21 T_GLOBAL_META(T_META_NAMESPACE("xnu.iokit"),
22 T_META_RUN_CONCURRENTLY(true));
23
24 kern_return_t
25 build_ioregistry_by_catalog_send_data(const char *match_name,
26 const char *userclient_name, const char *service_name)
27 {
28 kern_return_t kret;
29
30 NSArray *rootCatalogueArray = @[@{
31 kIOProviderClassKey: vIOProviderClassValue,
32 kIOClassKey: @(service_name),
33 kIOUserClientClassKey: @(userclient_name),
34 kIOMatchCategoryKey: @(match_name)
35 }];
36
37 CFDataRef cfData = IOCFSerialize((__bridge CFTypeRef)rootCatalogueArray,
38 kIOCFSerializeToBinary);
39
40 kret = IOCatalogueSendData(MACH_PORT_NULL, 1, CFDataGetBytePtr(cfData),
41 CFDataGetLength(cfData));
42
43 if (cfData) {
44 CFRelease(cfData);
45 }
46
47 return kret;
48 }
49
50 bool
51 test_open_ioregistry(const char *match_name, const char *service_name,
52 bool exploit)
53 {
54 kern_return_t kret;
55 bool ioreg_found = false;
56 CFStringRef cfstrMatchName = NULL;
57 io_connect_t conn = IO_OBJECT_NULL;
58 io_iterator_t iter = IO_OBJECT_NULL, obj = IO_OBJECT_NULL;
59 CFMutableDictionaryRef service_info = NULL, properties = NULL;
60
61 service_info = IOServiceMatching(service_name);
62 kret = IOServiceGetMatchingServices(kIOMasterPortDefault, service_info, &iter);
63 T_QUIET; T_ASSERT_MACH_SUCCESS(kret, "IOServiceGetMatchingServices");
64 cfstrMatchName = CFStringCreateWithCString(kCFAllocatorDefault,
65 match_name, kCFStringEncodingUTF8);
66
67 while (obj = IOIteratorNext(iter)) {
68 kret = IORegistryEntryCreateCFProperties(obj, &properties,
69 kCFAllocatorDefault, kNilOptions);
70 if (kret != KERN_SUCCESS) {
71 T_LOG("IORegistryEntryCreateCFProperties fails, 0x%08X",
72 (uint32_t)kret);
73 IOObjectRelease(obj);
74 continue;
75 }
76
77 CFStringRef value = CFDictionaryGetValue(properties, CFSTR("IOMatchCategory"));
78 if (value && CFGetTypeID(value) == CFStringGetTypeID() &&
79 CFEqual(value, cfstrMatchName)) {
80 ioreg_found = true;
81 } else {
82 IOObjectRelease(obj);
83 continue;
84 }
85
86 if (!exploit) {
87 goto bail;
88 }
89
90 T_LOG("try to exploit by opening io service, possibly panic?");
91 IOServiceOpen(obj, mach_task_self(), 0, &conn);
92 IOObjectRelease(obj);
93
94 break;
95 }
96
97 bail:
98 if (cfstrMatchName) {
99 CFRelease(cfstrMatchName);
100 }
101
102 if (properties) {
103 CFRelease(properties);
104 }
105
106 if (iter != IO_OBJECT_NULL) {
107 IOObjectRelease(iter);
108 }
109
110 if (conn != IO_OBJECT_NULL) {
111 IOServiceClose(conn);
112 }
113
114 return ioreg_found;
115 }
116
117 T_DECL(io_catalog_send_data_test, "regression test to build an IORegistry entry"
118 " with mismatching IOService and IOUserClientClass by IOCatalogueSendData, "
119 "to verify if exploit risk still exists in IOCatalogueSendData for "
120 "potential DoS - <rdar://problem/31558871>")
121 {
122 kern_return_t kret;
123
124 kret = build_ioregistry_by_catalog_send_data("fooBar",
125 "IOSurfaceRootUserClient", "IOReportHub");
126 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
127 /* this trick to build an entry by io_catalog_send_data should fail */
128 T_EXPECT_EQ(kret, kIOReturnNotPrivileged, "build an entry with"
129 " mismatch IOService and IOUserClientClass by IOCatalogueSendData "
130 "should fail as kIOReturnNotPrivileged");
131 #else
132 T_EXPECT_EQ(kret, KERN_SUCCESS, "IOCatalogueSendData should return success with kextd");
133 #endif
134 T_EXPECT_FALSE(test_open_ioregistry("fooBar", "IOReportHub", false),
135 "Mismatched entry built by IOCatalogueSendData should not be opened");
136 }