xref: /xnu-11417.101.15/tests/iokit/io_catalog_send_data.m (revision e3723e1f17661b24996789d8afc084c0c3303b26)
1*e3723e1fSApple OSS Distributions// Copyright (c) 2019-2020 Apple Inc.
2*e3723e1fSApple OSS Distributions
3*e3723e1fSApple OSS Distributions#include <darwintest.h>
4*e3723e1fSApple OSS Distributions#include <sys/sysctl.h>
5*e3723e1fSApple OSS Distributions
6*e3723e1fSApple OSS Distributions#include <Foundation/Foundation.h>
7*e3723e1fSApple OSS Distributions#include <IOKit/IOCFSerialize.h>
8*e3723e1fSApple OSS Distributions#include <IOKit/IOKitLib.h>
9*e3723e1fSApple OSS Distributions
10*e3723e1fSApple OSS DistributionsT_GLOBAL_META(T_META_NAMESPACE("xnu.iokit"),
11*e3723e1fSApple OSS Distributions	T_META_RUN_CONCURRENTLY(true));
12*e3723e1fSApple OSS Distributions
13*e3723e1fSApple OSS Distributionsstatic kern_return_t
14*e3723e1fSApple OSS Distributionsbuild_ioregistry_by_catalog_send_data(const char *match_name,
15*e3723e1fSApple OSS Distributions    const char *userclient_name, const char *service_name)
16*e3723e1fSApple OSS Distributions{
17*e3723e1fSApple OSS Distributions	NSArray *rootCatalogueArray = @[@{
18*e3723e1fSApple OSS Distributions	    @kIOProviderClassKey: @kIOResourcesClass,
19*e3723e1fSApple OSS Distributions	    @kIOClassKey: (NSString * __nonnull)@(service_name),
20*e3723e1fSApple OSS Distributions	    @kIOUserClientClassKey: (NSString * __nonnull)@(userclient_name),
21*e3723e1fSApple OSS Distributions	    @kIOMatchCategoryKey: (NSString * __nonnull)@(match_name)
22*e3723e1fSApple OSS Distributions	}];
23*e3723e1fSApple OSS Distributions
24*e3723e1fSApple OSS Distributions	CFDataRef cfData = IOCFSerialize((__bridge CFTypeRef)rootCatalogueArray,
25*e3723e1fSApple OSS Distributions	    kIOCFSerializeToBinary);
26*e3723e1fSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(cfData, "IOCFSerialize root catalogue array");
27*e3723e1fSApple OSS Distributions	kern_return_t kret = IOCatalogueSendData(MACH_PORT_NULL, 1,
28*e3723e1fSApple OSS Distributions	    (const char *)CFDataGetBytePtr(cfData),
29*e3723e1fSApple OSS Distributions	    (uint32_t)CFDataGetLength(cfData));
30*e3723e1fSApple OSS Distributions	CFRelease(cfData);
31*e3723e1fSApple OSS Distributions	return kret;
32*e3723e1fSApple OSS Distributions}
33*e3723e1fSApple OSS Distributions
34*e3723e1fSApple OSS Distributionsstatic bool
35*e3723e1fSApple OSS Distributionstest_open_ioregistry(const char *match_name, const char *service_name,
36*e3723e1fSApple OSS Distributions    bool exploit)
37*e3723e1fSApple OSS Distributions{
38*e3723e1fSApple OSS Distributions	kern_return_t kret;
39*e3723e1fSApple OSS Distributions	bool ioreg_found = false;
40*e3723e1fSApple OSS Distributions	CFStringRef cfstrMatchName = NULL;
41*e3723e1fSApple OSS Distributions	io_connect_t conn = IO_OBJECT_NULL;
42*e3723e1fSApple OSS Distributions	io_iterator_t iter = IO_OBJECT_NULL, obj = IO_OBJECT_NULL;
43*e3723e1fSApple OSS Distributions	CFMutableDictionaryRef service_info = NULL, properties = NULL;
44*e3723e1fSApple OSS Distributions
45*e3723e1fSApple OSS Distributions	service_info = IOServiceMatching(service_name);
46*e3723e1fSApple OSS Distributions	kret = IOServiceGetMatchingServices(kIOMasterPortDefault, service_info, &iter);
47*e3723e1fSApple OSS Distributions	T_QUIET; T_ASSERT_MACH_SUCCESS(kret, "IOServiceGetMatchingServices");
48*e3723e1fSApple OSS Distributions	cfstrMatchName = CFStringCreateWithCString(kCFAllocatorDefault,
49*e3723e1fSApple OSS Distributions	    match_name, kCFStringEncodingUTF8);
50*e3723e1fSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(cfstrMatchName,
51*e3723e1fSApple OSS Distributions	    "created CFString from match name");
52*e3723e1fSApple OSS Distributions
53*e3723e1fSApple OSS Distributions	while ((obj = IOIteratorNext(iter)) != 0) {
54*e3723e1fSApple OSS Distributions		kret = IORegistryEntryCreateCFProperties(obj, &properties,
55*e3723e1fSApple OSS Distributions		    kCFAllocatorDefault, kNilOptions);
56*e3723e1fSApple OSS Distributions		if (kret != KERN_SUCCESS) {
57*e3723e1fSApple OSS Distributions			T_LOG("IORegistryEntryCreateCFProperties fails, 0x%08X",
58*e3723e1fSApple OSS Distributions			    (uint32_t)kret);
59*e3723e1fSApple OSS Distributions			IOObjectRelease(obj);
60*e3723e1fSApple OSS Distributions			continue;
61*e3723e1fSApple OSS Distributions		}
62*e3723e1fSApple OSS Distributions
63*e3723e1fSApple OSS Distributions		CFStringRef value = CFDictionaryGetValue(properties, CFSTR("IOMatchCategory"));
64*e3723e1fSApple OSS Distributions		if (value && CFGetTypeID(value) == CFStringGetTypeID() &&
65*e3723e1fSApple OSS Distributions		    CFEqual(value, cfstrMatchName)) {
66*e3723e1fSApple OSS Distributions			ioreg_found = true;
67*e3723e1fSApple OSS Distributions		} else {
68*e3723e1fSApple OSS Distributions			IOObjectRelease(obj);
69*e3723e1fSApple OSS Distributions			continue;
70*e3723e1fSApple OSS Distributions		}
71*e3723e1fSApple OSS Distributions
72*e3723e1fSApple OSS Distributions		if (!exploit) {
73*e3723e1fSApple OSS Distributions			IOObjectRelease(obj);
74*e3723e1fSApple OSS Distributions			break;
75*e3723e1fSApple OSS Distributions		}
76*e3723e1fSApple OSS Distributions
77*e3723e1fSApple OSS Distributions		T_LOG("try to exploit by opening service, possibly panic...");
78*e3723e1fSApple OSS Distributions		IOServiceOpen(obj, mach_task_self(), 0, &conn);
79*e3723e1fSApple OSS Distributions		IOObjectRelease(obj);
80*e3723e1fSApple OSS Distributions
81*e3723e1fSApple OSS Distributions		break;
82*e3723e1fSApple OSS Distributions	}
83*e3723e1fSApple OSS Distributions
84*e3723e1fSApple OSS Distributions	CFRelease(cfstrMatchName);
85*e3723e1fSApple OSS Distributions
86*e3723e1fSApple OSS Distributions	if (properties) {
87*e3723e1fSApple OSS Distributions		CFRelease(properties);
88*e3723e1fSApple OSS Distributions	}
89*e3723e1fSApple OSS Distributions
90*e3723e1fSApple OSS Distributions	if (iter != IO_OBJECT_NULL) {
91*e3723e1fSApple OSS Distributions		IOObjectRelease(iter);
92*e3723e1fSApple OSS Distributions	}
93*e3723e1fSApple OSS Distributions
94*e3723e1fSApple OSS Distributions	if (conn != IO_OBJECT_NULL) {
95*e3723e1fSApple OSS Distributions		IOServiceClose(conn);
96*e3723e1fSApple OSS Distributions	}
97*e3723e1fSApple OSS Distributions
98*e3723e1fSApple OSS Distributions	return ioreg_found;
99*e3723e1fSApple OSS Distributions}
100*e3723e1fSApple OSS Distributions
101*e3723e1fSApple OSS DistributionsT_DECL(io_catalog_send_data_test,
102*e3723e1fSApple OSS Distributions	"build an IORegistry entry with mismatching IOService and "
103*e3723e1fSApple OSS Distributions	"IOUserClientClass by IOCatalogueSendData to check for DoS in "
104*e3723e1fSApple OSS Distributions	"IOCatalogueSendData", T_META_TAG_VM_PREFERRED)
105*e3723e1fSApple OSS Distributions{
106*e3723e1fSApple OSS Distributions	kern_return_t kret = build_ioregistry_by_catalog_send_data("fooBar",
107*e3723e1fSApple OSS Distributions	    "IOSurfaceRootUserClient", "IOReportHub");
108*e3723e1fSApple OSS Distributions#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
109*e3723e1fSApple OSS Distributions	int development = 0;
110*e3723e1fSApple OSS Distributions	size_t development_size = sizeof(development);
111*e3723e1fSApple OSS Distributions
112*e3723e1fSApple OSS Distributions	T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &development,
113*e3723e1fSApple OSS Distributions	    &development_size, NULL, 0), "sysctl kern.development");
114*e3723e1fSApple OSS Distributions
115*e3723e1fSApple OSS Distributions	if (development) {
116*e3723e1fSApple OSS Distributions		T_EXPECT_MACH_SUCCESS(kret, "IOCatalogueSendData should "
117*e3723e1fSApple OSS Distributions		    "return success with development kernel");
118*e3723e1fSApple OSS Distributions	} else {
119*e3723e1fSApple OSS Distributions		/* this trick to build an entry by io_catalog_send_data should fail */
120*e3723e1fSApple OSS Distributions		T_EXPECT_EQ(kret, kIOReturnNotPrivileged, "build an entry with"
121*e3723e1fSApple OSS Distributions		    " mismatch IOService and IOUserClientClass by IOCatalogueSendData "
122*e3723e1fSApple OSS Distributions		    "should fail as kIOReturnNotPrivileged in none-dev kernel without kernelmanagerd");
123*e3723e1fSApple OSS Distributions	}
124*e3723e1fSApple OSS Distributions#else
125*e3723e1fSApple OSS Distributions	T_EXPECT_MACH_SUCCESS(kret,
126*e3723e1fSApple OSS Distributions	    "IOCatalogueSendData should return success with kernelmanagerd");
127*e3723e1fSApple OSS Distributions#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
128*e3723e1fSApple OSS Distributions	T_EXPECT_FALSE(test_open_ioregistry("fooBar", "IOReportHub", false),
129*e3723e1fSApple OSS Distributions	    "mismatched entry built by IOCatalogueSendData should not be opened");
130*e3723e1fSApple OSS Distributions}
131