1 /*
2 * Copyright (c) 1998-2021 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 *
30 */
31
32 #define TEST_HEADERS 0
33
34 #if TEST_HEADERS
35
36 #include <libkern/OSByteOrder.h>
37 #include <libkern/c++/OSArray.h>
38 #include <libkern/c++/OSAllocation.h>
39 #include <libkern/c++/OSBoolean.h>
40 #include <libkern/c++/OSBoundedArray.h>
41 #include <libkern/c++/OSBoundedArrayRef.h>
42 #include <libkern/c++/OSBoundedPtr.h>
43 #include <libkern/c++/OSCollection.h>
44 #include <libkern/c++/OSCollectionIterator.h>
45 #include <libkern/c++/OSContainers.h>
46 #include <libkern/c++/OSCPPDebug.h>
47 #include <libkern/c++/OSData.h>
48 #include <libkern/c++/OSDictionary.h>
49 #include <libkern/c++/OSEndianTypes.h>
50 #include <libkern/c++/OSIterator.h>
51 #include <libkern/c++/OSKext.h>
52 #include <libkern/c++/OSLib.h>
53 #include <libkern/c++/OSMetaClass.h>
54 #include <libkern/c++/OSNumber.h>
55 #include <libkern/c++/OSObject.h>
56 #include <libkern/c++/OSOrderedSet.h>
57 #include <libkern/c++/OSSerialize.h>
58 #include <libkern/c++/OSSet.h>
59 #include <libkern/c++/OSSharedPtr.h>
60 #include <libkern/c++/OSString.h>
61 #include <libkern/c++/OSSymbol.h>
62 #include <libkern/c++/OSUnserialize.h>
63 #include <libkern/crypto/aes.h>
64 #include <libkern/crypto/aesxts.h>
65 #include <libkern/crypto/crypto_internal.h>
66 #include <libkern/crypto/des.h>
67 #include <libkern/crypto/md5.h>
68 #include <libkern/crypto/register_crypto.h>
69 #include <libkern/crypto/sha1.h>
70 #include <libkern/crypto/sha2.h>
71 #include <libkern/kernel_mach_header.h>
72 #include <libkern/kext_request_keys.h>
73 #include <libkern/kxld.h>
74 #include <libkern/kxld_types.h>
75 #include <libkern/locks.h>
76 #include <libkern/mkext.h>
77 #include <libkern/OSAtomic.h>
78 #include <libkern/OSBase.h>
79 #include <libkern/OSDebug.h>
80 #include <libkern/OSKextLib.h>
81 #include <libkern/OSKextLibPrivate.h>
82 #include <libkern/OSReturn.h>
83 #include <libkern/OSSerializeBinary.h>
84 #include <libkern/OSTypes.h>
85 #include <libkern/prelink.h>
86 #include <libkern/stack_protector.h>
87 #include <libkern/sysctl.h>
88 #include <libkern/tree.h>
89 #include <libkern/zconf.h>
90 #include <libkern/zlib.h>
91
92 #include <IOKit/AppleKeyStoreInterface.h>
93 #include <IOKit/assert.h>
94 #include <IOKit/IOBSD.h>
95 #include <IOKit/IOBufferMemoryDescriptor.h>
96 #include <IOKit/IOCatalogue.h>
97 #include <IOKit/IOCommand.h>
98 #include <IOKit/IOCommandGate.h>
99 #include <IOKit/IOCommandPool.h>
100 #include <IOKit/IOCommandQueue.h>
101 #include <IOKit/IOConditionLock.h>
102 #include <IOKit/IOCPU.h>
103 //#include <IOKit/IODataQueue.h>
104 #include <IOKit/IODataQueueShared.h>
105 #include <IOKit/IODeviceMemory.h>
106 #include <IOKit/IODeviceTreeSupport.h>
107 #include <IOKit/IODMACommand.h>
108 #include <IOKit/IODMAController.h>
109 #include <IOKit/IODMAEventSource.h>
110 #include <IOKit/IOEventSource.h>
111 #include <IOKit/IOFilterInterruptEventSource.h>
112 #include <IOKit/IOHibernatePrivate.h>
113 #include <IOKit/IOInterleavedMemoryDescriptor.h>
114 #include <IOKit/IOInterruptAccounting.h>
115 #include <IOKit/IOInterruptAccountingPrivate.h>
116 #include <IOKit/IOInterruptController.h>
117 #include <IOKit/IOInterruptEventSource.h>
118 #include <IOKit/IOInterrupts.h>
119 #include <IOKit/IOKernelReporters.h>
120 #include <IOKit/IOKernelReportStructs.h>
121 #include <IOKit/IOKitDebug.h>
122 #include <IOKit/IOKitDiagnosticsUserClient.h>
123 #include <IOKit/IOKitKeys.h>
124 #include <IOKit/IOKitKeysPrivate.h>
125 #include <IOKit/IOKitServer.h>
126 #include <IOKit/IOLib.h>
127 #include <IOKit/IOLocks.h>
128 #include <IOKit/IOLocksPrivate.h>
129 #include <IOKit/IOMapper.h>
130 #include <IOKit/IOMemoryCursor.h>
131 #include <IOKit/IOMemoryDescriptor.h>
132 #include <IOKit/IOMessage.h>
133 #include <IOKit/IOMultiMemoryDescriptor.h>
134 #include <IOKit/IONotifier.h>
135 #include <IOKit/IONVRAM.h>
136 #include <IOKit/IOPlatformExpert.h>
137 #include <IOKit/IOPolledInterface.h>
138 #include <IOKit/IORangeAllocator.h>
139 #include <IOKit/IORegistryEntry.h>
140 #include <IOKit/IOReportMacros.h>
141 #include <IOKit/IOReportTypes.h>
142 #include <IOKit/IOReturn.h>
143 #include <IOKit/IOService.h>
144 #include <IOKit/IOServicePM.h>
145 #include <IOKit/IOSharedDataQueue.h>
146 #include <IOKit/IOSharedLock.h>
147 #include <IOKit/IOStatistics.h>
148 #include <IOKit/IOStatisticsPrivate.h>
149 #include <IOKit/IOSubMemoryDescriptor.h>
150 #include <IOKit/IOSyncer.h>
151 #include <IOKit/IOTimerEventSource.h>
152 #include <IOKit/IOTimeStamp.h>
153 #include <IOKit/IOTypes.h>
154 #include <IOKit/IOUserClient.h>
155 #include <IOKit/IOWorkLoop.h>
156 #include <IOKit/nvram/IONVRAMController.h>
157 #include <IOKit/OSMessageNotification.h>
158 #include <IOKit/platform/AppleMacIO.h>
159 #include <IOKit/platform/AppleMacIODevice.h>
160 #include <IOKit/platform/AppleNMI.h>
161 #include <IOKit/platform/ApplePlatformExpert.h>
162 #include <IOKit/power/IOPwrController.h>
163 #include <IOKit/pwr_mgt/IOPM.h>
164 #include <IOKit/pwr_mgt/IOPMinformee.h>
165 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
166 #include <IOKit/pwr_mgt/IOPMLibDefs.h>
167 #include <IOKit/pwr_mgt/IOPMlog.h>
168 #include <IOKit/pwr_mgt/IOPMPowerSource.h>
169 #include <IOKit/pwr_mgt/IOPMPowerSourceList.h>
170 #include <IOKit/pwr_mgt/IOPMpowerState.h>
171 #include <IOKit/pwr_mgt/IOPMPrivate.h>
172 #include <IOKit/pwr_mgt/IOPowerConnection.h>
173 #include <IOKit/pwr_mgt/RootDomain.h>
174 #include <IOKit/rtc/IORTCController.h>
175 #include <IOKit/system.h>
176 #include <IOKit/system_management/IOWatchDogTimer.h>
177
178 #endif /* TEST_HEADERS */
179
180 #include <sys/sysctl.h>
181 #include <libkern/c++/OSData.h>
182 #include <IOKit/IOService.h>
183 #include <IOKit/IOUserClient.h>
184 #include "Tests.h"
185
186
187 #if DEVELOPMENT || DEBUG
188
189 #include <IOKit/IOWorkLoop.h>
190 #include <IOKit/IOTimerEventSource.h>
191 #include <IOKit/IOInterruptEventSource.h>
192 #include <IOKit/IOCommandGate.h>
193 #include <IOKit/IOPlatformExpert.h>
194 #include <IOKit/IOSharedDataQueue.h>
195 #include <IOKit/IODataQueueShared.h>
196 #include <IOKit/IOServiceStateNotificationEventSource.h>
197 #include <IOKit/IOKitKeysPrivate.h>
198 #include <IOKit/IOKitServer.h>
199 #include <IOKit/IOBSD.h>
200 #include <kern/ipc_kobject.h>
201 #include <libkern/Block.h>
202 #include <libkern/Block_private.h>
203 #include <libkern/c++/OSAllocation.h>
204 #include <libkern/c++/OSBoundedArray.h>
205 #include <libkern/c++/OSBoundedArrayRef.h>
206 #include <libkern/c++/OSBoundedPtr.h>
207 #include <libkern/c++/OSSharedPtr.h>
208 #include <os/cpp_util.h>
209
210 static uint64_t gIOWorkLoopTestDeadline;
211
212 static void
TESAction(OSObject * owner,IOTimerEventSource * tes)213 TESAction(OSObject * owner, IOTimerEventSource * tes)
214 {
215 if (mach_absolute_time() < gIOWorkLoopTestDeadline) {
216 tes->setTimeout(1, kMicrosecondScale);
217 }
218 }
219
220 static int
IOWorkLoopTest(int newValue)221 IOWorkLoopTest(int newValue)
222 {
223 IOReturn err;
224 uint32_t idx;
225 IOWorkLoop * wl;
226 IOTimerEventSource * tes;
227 IOInterruptEventSource * ies;
228
229 wl = IOWorkLoop::workLoop();
230 assert(wl);
231 tes = IOTimerEventSource::timerEventSource(kIOTimerEventSourceOptionsPriorityWorkLoop, wl, &TESAction);
232 assert(tes);
233 err = wl->addEventSource(tes);
234 assert(kIOReturnSuccess == err);
235 clock_interval_to_deadline(100, kMillisecondScale, &gIOWorkLoopTestDeadline);
236 for (idx = 0; mach_absolute_time() < gIOWorkLoopTestDeadline; idx++) {
237 tes->setTimeout(idx & 1023, kNanosecondScale);
238 }
239 tes->cancelTimeout();
240 wl->removeEventSource(tes);
241 tes->release();
242
243 int value = 3;
244
245 tes = IOTimerEventSource::timerEventSource(kIOTimerEventSourceOptionsDefault, wl, ^(IOTimerEventSource * tes){
246 kprintf("wl %p, value %d\n", wl, value);
247 });
248 err = wl->addEventSource(tes);
249 assert(kIOReturnSuccess == err);
250
251 value = 2;
252 tes->setTimeout(1, kNanosecondScale);
253 IOSleep(1);
254 wl->removeEventSource(tes);
255 tes->release();
256
257 ies = IOInterruptEventSource::interruptEventSource(wl, NULL, 0, ^void (IOInterruptEventSource *sender, int count){
258 kprintf("ies block %p, %d\n", sender, count);
259 });
260
261 assert(ies);
262 kprintf("ies %p\n", ies);
263 err = wl->addEventSource(ies);
264 assert(kIOReturnSuccess == err);
265 ies->interruptOccurred(NULL, NULL, 0);
266 IOSleep(1);
267 ies->interruptOccurred(NULL, NULL, 0);
268 IOSleep(1);
269 wl->removeEventSource(ies);
270 ies->release();
271
272 wl->release();
273
274 return 0;
275 }
276
277 static int
OSCollectionTest(int newValue)278 OSCollectionTest(int newValue)
279 {
280 OSArray * array = OSArray::withCapacity(8);
281 array->setObject(kOSBooleanTrue);
282 array->setObject(kOSBooleanFalse);
283 array->setObject(kOSBooleanFalse);
284 array->setObject(kOSBooleanTrue);
285 array->setObject(kOSBooleanFalse);
286 array->setObject(kOSBooleanTrue);
287
288 __block unsigned int index;
289 index = 0;
290 array->iterateObjects(^bool (OSObject * obj) {
291 kprintf("%d:%d ", index, (obj == kOSBooleanTrue) ? 1 : (obj == kOSBooleanFalse) ? 0 : 2);
292 index++;
293 return false;
294 });
295 kprintf("\n");
296 array->release();
297
298 OSDictionary * dict = IOService::resourceMatching("hello");
299 assert(dict);
300 index = 0;
301 dict->iterateObjects(^bool (const OSSymbol * sym, OSObject * obj) {
302 OSString * str = OSDynamicCast(OSString, obj);
303 assert(str);
304 kprintf("%d:%s=%s\n", index, sym->getCStringNoCopy(), str->getCStringNoCopy());
305 index++;
306 return false;
307 });
308 dict->release();
309
310 OSSerializer * serializer = OSSerializer::withBlock(^bool (OSSerialize * s){
311 return gIOBSDUnitKey->serialize(s);
312 });
313 assert(serializer);
314 IOService::getPlatform()->setProperty("OSSerializer_withBlock", serializer);
315 serializer->release();
316
317 OSString * ab = OSString::withCString("abcdef", 2);
318 assert(strcmp(ab->getCStringNoCopy(), "ab") == 0);
319 OSString * defgh = OSString::withCString("defgh", 10);
320 assert(strcmp(defgh->getCStringNoCopy(), "defgh") == 0);
321 OSString * zyxwvut = OSString::withCString("zyxwvut", 7);
322 assert(strcmp(zyxwvut->getCStringNoCopy(), "zyxwvut") == 0);
323 OSSafeReleaseNULL(ab);
324 OSSafeReleaseNULL(defgh);
325 OSSafeReleaseNULL(zyxwvut);
326
327 return 0;
328 }
329
330 static int
OSAllocationTests(int)331 OSAllocationTests(int)
332 {
333 OSAllocation<int> ints(100, OSAllocateMemory);
334 assert(ints);
335
336 {
337 int counter = 0;
338 for (int& i : ints) {
339 i = counter++;
340 }
341 }
342
343 {
344 int counter = 0;
345 for (int& i : ints) {
346 assert(i == counter);
347 ++counter;
348 }
349 }
350
351 OSAllocation<int> arrayZero(100, OSAllocateMemoryZero);
352 assert(arrayZero);
353 for (const auto& i : arrayZero) {
354 assert(i == 0);
355 }
356
357 // Make sure we can have two-level OSAllocations
358 {
359 OSAllocation<OSAllocation<int> > testArray(10, OSAllocateMemory);
360 for (int i = 0; i < 10; i++) {
361 testArray[i] = OSAllocation<int>(10, OSAllocateMemory);
362 for (int j = 0; j < 10; ++j) {
363 testArray[i][j] = i + j;
364 }
365 }
366
367 for (int i = 0; i < 10; i++) {
368 for (int j = 0; j < 10; ++j) {
369 assert(testArray[i][j] == i + j);
370 }
371 }
372 }
373
374 return 0;
375 }
376
377 static int
OSDataAllocationTests(int)378 OSDataAllocationTests(int)
379 {
380 OSDataAllocation<int> ints(100, OSAllocateMemory);
381 assert(ints);
382
383 {
384 int counter = 0;
385 for (int& i : ints) {
386 i = counter++;
387 }
388 }
389
390 {
391 int counter = 0;
392 for (const int& i : ints) {
393 assert(i == counter);
394 ++counter;
395 }
396 }
397
398 OSDataAllocation<int> arrayZero(100, OSAllocateMemoryZero);
399 assert(arrayZero);
400 for (const auto& i : arrayZero) {
401 assert(i == 0);
402 }
403
404 return 0;
405 }
406
407 static int
OSBoundedArrayTests(int)408 OSBoundedArrayTests(int)
409 {
410 OSBoundedArray<int, 5> ints = {0, 1, 2, 3, 4};
411 assert(ints.size() == 5);
412
413 {
414 int counter = 0;
415 for (int& i : ints) {
416 i = counter++;
417 }
418 }
419
420 {
421 int counter = 0;
422 for (int& i : ints) {
423 assert(i == counter);
424 ++counter;
425 }
426 }
427
428 return 0;
429 }
430
431 static int
OSBoundedArrayRefTests(int)432 OSBoundedArrayRefTests(int)
433 {
434 OSBoundedArray<int, 5> storage = {0, 1, 2, 3, 4};
435 OSBoundedArrayRef<int> ints(storage);
436 assert(ints);
437
438 {
439 int counter = 0;
440 for (int& i : ints) {
441 i = counter++;
442 }
443 }
444
445 {
446 int counter = 0;
447 for (int& i : ints) {
448 assert(i == counter);
449 ++counter;
450 }
451 }
452
453 return 0;
454 }
455
456 class OSArraySubclass : public OSArray {
457 OSDeclareDefaultStructors(OSArraySubclass);
458 public:
459 static OSArraySubclass * withCapacity(unsigned int inCapacity);
460 virtual unsigned int iteratorSize() const APPLE_KEXT_OVERRIDE;
461 };
462
463 OSDefineMetaClassAndStructors(OSArraySubclass, OSArray);
464
465 OSArraySubclass *
withCapacity(unsigned int inCapacity)466 OSArraySubclass::withCapacity(unsigned int inCapacity)
467 {
468 OSArraySubclass * me = OSTypeAlloc(OSArraySubclass);
469
470 if (me && !me->initWithCapacity(inCapacity)) {
471 return nullptr;
472 }
473
474 return me;
475 }
476
477 unsigned int
iteratorSize() const478 OSArraySubclass::iteratorSize() const
479 {
480 unsigned int result = 64;
481 // Has to be larger than the OSArray iterator size to prevent out-of-bounds writes
482 assert(result >= OSArray::iteratorSize());
483 return result;
484 }
485
486 class OSCISubclass : public OSCollectionIterator {
487 OSDeclareDefaultStructors(OSCISubclass);
488 public:
489 static OSCISubclass * withCollection(const OSCollection * inColl);
490 };
491
492 OSDefineMetaClassAndStructors(OSCISubclass, OSCollectionIterator);
493
494 OSCISubclass *
withCollection(const OSCollection * inColl)495 OSCISubclass::withCollection(const OSCollection * inColl)
496 {
497 OSCISubclass * me = OSTypeAlloc(OSCISubclass);
498
499 if (me && !me->initWithCollection(inColl)) {
500 return nullptr;
501 }
502
503 return me;
504 }
505
506 static int
OSCollectionIteratorTests(int)507 OSCollectionIteratorTests(int)
508 {
509 OSArray * array = OSArray::withCapacity(0);
510 OSString * firstObj = OSString::withCString("test object");
511 OSString * secondObj = OSString::withCString("test object 2");
512 OSObject * current = NULL;
513 OSCollectionIterator * osci = NULL;
514 OSCISubclass * osciSubclass = NULL;
515 size_t index = 0;
516 array->setObject(firstObj);
517 array->setObject(secondObj);
518
519 // Test iteration over a normal OSArray
520 osci = OSCollectionIterator::withCollection(array);
521 assert(osci != NULL);
522
523 index = 0;
524 while ((current = osci->getNextObject()) != NULL) {
525 if (index == 0) {
526 assert(current == firstObj);
527 } else if (index == 1) {
528 assert(current == secondObj);
529 } else {
530 panic("index out of range");
531 }
532 index++;
533 }
534
535 OSSafeReleaseNULL(osci);
536
537 // Test iteration with a OSCollectionIterator subclass over a normal OSArray
538 osciSubclass = OSCISubclass::withCollection(array);
539 assert(osciSubclass != NULL);
540
541 index = 0;
542 while ((current = osciSubclass->getNextObject()) != NULL) {
543 if (index == 0) {
544 assert(current == firstObj);
545 } else if (index == 1) {
546 assert(current == secondObj);
547 } else {
548 panic("index out of range");
549 }
550 index++;
551 }
552
553 OSSafeReleaseNULL(osciSubclass);
554
555 OSSafeReleaseNULL(array);
556
557 // Create the OSArray subclass
558 OSArraySubclass * arraySubclass = OSArraySubclass::withCapacity(0);
559 arraySubclass->setObject(firstObj);
560 arraySubclass->setObject(secondObj);
561 // Test iteration over a subclassed OSArray, with a large iterator size
562 osci = OSCollectionIterator::withCollection(arraySubclass);
563 assert(osci != NULL);
564
565 index = 0;
566 while ((current = osci->getNextObject()) != NULL) {
567 if (index == 0) {
568 assert(current == firstObj);
569 } else if (index == 1) {
570 assert(current == secondObj);
571 } else {
572 panic("index out of range");
573 }
574 index++;
575 }
576
577 OSSafeReleaseNULL(osci);
578
579 // Test iteration with a OSCollectionIterator subclass over a subclassed OSArray,
580 // with a large iterator size.
581 osciSubclass = OSCISubclass::withCollection(arraySubclass);
582 assert(osciSubclass != NULL);
583
584 index = 0;
585 while ((current = osciSubclass->getNextObject()) != NULL) {
586 if (index == 0) {
587 assert(current == firstObj);
588 } else if (index == 1) {
589 assert(current == secondObj);
590 } else {
591 panic("index out of range");
592 }
593 index++;
594 }
595
596 OSSafeReleaseNULL(osciSubclass);
597
598 OSSafeReleaseNULL(arraySubclass);
599 OSSafeReleaseNULL(firstObj);
600 OSSafeReleaseNULL(secondObj);
601
602 return 0;
603 }
604
605 static int
OSBoundedPtrTests(int)606 OSBoundedPtrTests(int)
607 {
608 int array[5] = {55, 66, 77, 88, 99};
609 OSBoundedPtr<int> begin(&array[0], &array[0], &array[5]);
610 OSBoundedPtr<int> end(&array[5], &array[0], &array[5]);
611
612 {
613 int counter = 0;
614 for (OSBoundedPtr<int> b = begin; b != end; ++b) {
615 *b = counter++;
616 }
617 }
618
619 {
620 int counter = 0;
621 for (OSBoundedPtr<int> b = begin; b != end; ++b) {
622 assert(*b == counter);
623 ++counter;
624 }
625 }
626
627 return 0;
628 }
629
630 static int
IOSharedDataQueue_44636964(__unused int newValue)631 IOSharedDataQueue_44636964(__unused int newValue)
632 {
633 IOSharedDataQueue* sd = IOSharedDataQueue::withCapacity(DATA_QUEUE_ENTRY_HEADER_SIZE + sizeof(UInt64));
634 UInt64 data = 0x11223344aa55aa55;
635 UInt32 data2 = 0x44332211;
636 UInt32 size = sizeof(UInt32);
637 /* enqueue moves tail to end */
638 sd->enqueue(&data, sizeof(UInt64));
639 /* dequeue moves head to end */
640 sd->dequeue(&data, &size);
641 /* Tail wraps around, head is still at end */
642 sd->enqueue(&data2, sizeof(UInt32));
643 /* something in the queue so peek() should return non-null */
644 assert(sd->peek() != NULL);
645 sd->release();
646 return KERN_SUCCESS;
647 }
648
649 #if 0
650 #include <IOKit/IOUserClient.h>
651 class TestUserClient : public IOUserClient
652 {
653 OSDeclareDefaultStructors(TestUserClient);
654 virtual void stop( IOService *provider) APPLE_KEXT_OVERRIDE;
655 virtual bool finalize(IOOptionBits options) APPLE_KEXT_OVERRIDE;
656 virtual IOReturn externalMethod( uint32_t selector,
657 IOExternalMethodArguments * arguments,
658 IOExternalMethodDispatch * dispatch,
659 OSObject * target,
660 void * reference ) APPLE_KEXT_OVERRIDE;
661 };
662
663 void
664 TestUserClient::stop( IOService *provider)
665 {
666 kprintf("TestUserClient::stop\n");
667 }
668 bool
669 TestUserClient::finalize(IOOptionBits options)
670 {
671 kprintf("TestUserClient::finalize\n");
672 return true;
673 }
674 IOReturn
675 TestUserClient::externalMethod( uint32_t selector,
676 IOExternalMethodArguments * arguments,
677 IOExternalMethodDispatch * dispatch,
678 OSObject * target,
679 void * reference )
680 {
681 getProvider()->terminate();
682 IOSleep(500);
683 return 0;
684 }
685 OSDefineMetaClassAndStructors(TestUserClient, IOUserClient);
686 #endif
687
688 static int
IOServiceTest(int newValue)689 IOServiceTest(int newValue)
690 {
691 OSDictionary * matching;
692 IONotifier * note;
693 __block IOService * found;
694
695 #if 0
696 found = new IOService;
697 found->init();
698 found->setName("IOTestUserClientProvider");
699 found->attach(IOService::getPlatform());
700 found->setProperty("IOUserClientClass", "TestUserClient");
701 found->registerService();
702 #endif
703
704 matching = IOService::serviceMatching("IOPlatformExpert");
705 assert(matching);
706 found = nullptr;
707 note = IOService::addMatchingNotification(gIOMatchedNotification, matching, 0,
708 ^bool (IOService * newService, IONotifier * notifier) {
709 kprintf("found %s, %d\n", newService->getName(), newService->getRetainCount());
710 found = newService;
711 found->retain();
712 return true;
713 }
714 );
715 assert(note);
716 assert(found);
717 matching->release();
718 note->remove();
719
720 note = found->registerInterest(gIOBusyInterest,
721 ^IOReturn (uint32_t messageType, IOService * provider,
722 void * messageArgument, size_t argSize) {
723 kprintf("%p messageType 0x%08x %p\n", provider, messageType, messageArgument);
724 return kIOReturnSuccess;
725 });
726 assert(note);
727 IOSleep(1 * 1000);
728 note->remove();
729 found->release();
730
731 return 0;
732 }
733
734 static void
OSStaticPtrCastTests()735 OSStaticPtrCastTests()
736 {
737 // const& overload
738 {
739 OSSharedPtr<OSDictionary> const dict = OSMakeShared<OSDictionary>();
740 OSSharedPtr<OSCollection> collection = OSStaticPtrCast<OSCollection>(dict);
741 assert(collection == dict);
742 }
743 {
744 OSSharedPtr<OSDictionary> const dict = nullptr;
745 OSSharedPtr<OSCollection> collection = OSStaticPtrCast<OSCollection>(dict);
746 assert(collection == nullptr);
747 }
748 // && overload
749 {
750 OSSharedPtr<OSDictionary> dict = OSMakeShared<OSDictionary>();
751 OSDictionary* oldDict = dict.get();
752 OSSharedPtr<OSCollection> collection = OSStaticPtrCast<OSCollection>(os::move(dict));
753 assert(collection.get() == oldDict);
754 assert(dict == nullptr);
755 }
756 {
757 OSSharedPtr<OSDictionary> dict = nullptr;
758 OSSharedPtr<OSCollection> collection = OSStaticPtrCast<OSCollection>(os::move(dict));
759 assert(collection == nullptr);
760 assert(dict == nullptr);
761 }
762 }
763
764 static void
OSConstPtrCastTests()765 OSConstPtrCastTests()
766 {
767 // const& overload
768 {
769 OSSharedPtr<OSDictionary const> const dict = OSMakeShared<OSDictionary>();
770 OSSharedPtr<OSDictionary> dict2 = OSConstPtrCast<OSDictionary>(dict);
771 assert(dict2 == dict);
772 }
773 {
774 OSSharedPtr<OSDictionary const> const dict = OSMakeShared<OSDictionary>();
775 OSSharedPtr<OSDictionary const> dict2 = OSConstPtrCast<OSDictionary const>(dict);
776 assert(dict2 == dict);
777 }
778 {
779 OSSharedPtr<OSDictionary const> const dict = nullptr;
780 OSSharedPtr<OSDictionary> dict2 = OSConstPtrCast<OSDictionary>(dict);
781 assert(dict2 == nullptr);
782 }
783 {
784 OSSharedPtr<OSDictionary const> const dict = nullptr;
785 OSSharedPtr<OSDictionary const> dict2 = OSConstPtrCast<OSDictionary const>(dict);
786 assert(dict2 == nullptr);
787 }
788
789 // && overload
790 {
791 OSSharedPtr<OSDictionary const> dict = OSMakeShared<OSDictionary>();
792 OSDictionary const* oldDict = dict.get();
793 OSSharedPtr<OSDictionary> dict2 = OSConstPtrCast<OSDictionary>(os::move(dict));
794 assert(dict == nullptr);
795 assert(dict2 == oldDict);
796 }
797 {
798 OSSharedPtr<OSDictionary const> dict = nullptr;
799 OSSharedPtr<OSDictionary> dict2 = OSConstPtrCast<OSDictionary>(os::move(dict));
800 assert(dict == nullptr);
801 assert(dict2 == nullptr);
802 }
803 }
804
805 static void
OSDynamicPtrCastTests()806 OSDynamicPtrCastTests()
807 {
808 OSSharedPtr<OSDictionary> const dict = OSMakeShared<OSDictionary>();
809 {
810 OSSharedPtr<OSCollection> collection = OSDynamicPtrCast<OSCollection>(dict);
811 assert(collection != nullptr);
812 }
813 {
814 OSSharedPtr<OSArray> array = OSDynamicPtrCast<OSArray>(dict);
815 assert(array == nullptr);
816 assert(dict != nullptr);
817 }
818 {
819 OSTaggedSharedPtr<OSCollection, OSCollection> taggedDict(dict.get(), OSRetain);
820 OSTaggedSharedPtr<OSCollection, OSCollection> collection = OSDynamicPtrCast<OSCollection>(taggedDict);
821 assert(collection != nullptr);
822 }
823 {
824 OSTaggedSharedPtr<OSCollection, OSCollection> taggedDict(dict.get(), OSRetain);
825 OSTaggedSharedPtr<OSArray, OSCollection> array = OSDynamicPtrCast<OSArray>(taggedDict);
826 assert(array == nullptr);
827 assert(dict != nullptr);
828 }
829 {
830 OSSharedPtr<OSCollection> collection = OSDynamicPtrCast<OSCollection>(dict);
831 assert(collection.get() == OSDynamicCast(OSDictionary, dict.get()));
832 OSSharedPtr<OSDictionary> newDict = OSDynamicPtrCast<OSDictionary>(os::move(collection));
833 assert(collection == nullptr);
834 assert(newDict != nullptr);
835 assert(newDict.get() == dict.get());
836 }
837 }
838
839
840 class IOTestUserNotification : public IOUserNotification
841 {
842 OSDeclareDefaultStructors(IOTestUserNotification);
843 };
844
845 OSDefineMetaClassAndStructors(IOTestUserNotification, IOUserNotification)
846
847 struct IOUserNotificationTestThreadArgs {
848 IOTestUserNotification * userNotify;
849 IOLock * lock;
850 size_t * completed;
851 size_t iterations;
852 };
853
854 static bool
IOUserNotificationMatchingHandler(void * target __unused,void * ref __unused,IOService * newService __unused,IONotifier * notifier __unused)855 IOUserNotificationMatchingHandler( void * target __unused,
856 void * ref __unused, IOService * newService __unused, IONotifier * notifier __unused )
857 {
858 return true;
859 }
860
861 static void
IOUserNotificationTestThread(void * arg,wait_result_t result __unused)862 IOUserNotificationTestThread(void * arg, wait_result_t result __unused)
863 {
864 IOUserNotificationTestThreadArgs * threadArgs = (IOUserNotificationTestThreadArgs *)arg;
865
866 OSDictionary * dict = OSDictionary::withCapacity(0);
867 OSString * rootPath = OSString::withCStringNoCopy(":/");
868 dict->setObject(gIOPathMatchKey, rootPath);
869
870 for (size_t i = 0; i < threadArgs->iterations; i++) {
871 if (i % 2 == 0) {
872 IONotifier * notify = IOService::addMatchingNotification( gIOWillTerminateNotification, dict,
873 &IOUserNotificationMatchingHandler, NULL );
874 threadArgs->userNotify->setNotification(notify);
875 } else {
876 threadArgs->userNotify->setNotification(NULL);
877 }
878 }
879
880 threadArgs->userNotify->setNotification(NULL);
881 OSSafeReleaseNULL(rootPath);
882 OSSafeReleaseNULL(dict);
883
884 IOLockLock(threadArgs->lock);
885 *threadArgs->completed = *threadArgs->completed + 1;
886 IOLockWakeup(threadArgs->lock, (event_t)threadArgs->completed, true);
887 IOLockUnlock(threadArgs->lock);
888 }
889
890 static int
IOUserNotificationTests(__unused int newValue)891 IOUserNotificationTests(__unused int newValue)
892 {
893 constexpr size_t numThreads = 10;
894 constexpr size_t numIterations = 500000;
895 IOTestUserNotification * userNotify = OSTypeAlloc(IOTestUserNotification);
896 IOLock * lock = IOLockAlloc();
897 size_t threadsCompleted;
898 size_t i = 0;
899 thread_t threads[numThreads];
900 kern_return_t kr;
901 bool result;
902
903 struct IOUserNotificationTestThreadArgs threadArgs = {
904 .userNotify = userNotify,
905 .lock = lock,
906 .completed = &threadsCompleted,
907 .iterations = numIterations,
908 };
909
910 result = userNotify->init();
911 assert(result);
912
913 for (i = 0; i < numThreads; i++) {
914 kr = kernel_thread_start(&IOUserNotificationTestThread, (void *)&threadArgs, &threads[i]);
915 assert(kr == KERN_SUCCESS);
916 }
917
918 IOLockLock(lock);
919 while (threadsCompleted < numThreads) {
920 IOLockSleep(lock, &threadsCompleted, THREAD_UNINT);
921 IOLog("%s: Threads completed: %zu/%zu\n", __func__, threadsCompleted, numThreads);
922 }
923 IOLockUnlock(lock);
924
925 for (i = 0; i < numThreads; i++) {
926 thread_deallocate(threads[i]);
927 }
928
929 userNotify->setNotification(NULL);
930
931 OSSafeReleaseNULL(userNotify);
932 IOLockFree(lock);
933
934 return KERN_SUCCESS;
935 }
936
937 static void
IOServiceMatchingSharedPtrTests()938 IOServiceMatchingSharedPtrTests()
939 {
940 const OSSymbol * name = OSSymbol::withCString("name");
941 const OSSymbol * value = OSSymbol::withCString("value");
942
943 {
944 OSSharedPtr<OSDictionary> table;
945 OSSharedPtr<OSDictionary> result = IOService::serviceMatching("name", table);
946 assert(result);
947 assert(result->getRetainCount() == 1);
948
949 table = result;
950 assert(table->getRetainCount() == 2);
951 OSSharedPtr<OSDictionary> result2 = IOService::serviceMatching("name", table);
952 assert(result2);
953 assert(result2 == table);
954 assert(result2->getRetainCount() == 3);
955 }
956
957 {
958 OSSharedPtr<OSDictionary> table;
959 OSSharedPtr<OSDictionary> result = IOService::serviceMatching(name, table);
960 assert(result);
961 assert(result->getRetainCount() == 1);
962
963 table = result;
964 assert(table->getRetainCount() == 2);
965 OSSharedPtr<OSDictionary> result2 = IOService::serviceMatching(name, table);
966 assert(result2);
967 assert(result2 == table);
968 assert(result2->getRetainCount() == 3);
969 }
970
971 {
972 OSSharedPtr<OSDictionary> table;
973 OSSharedPtr<OSDictionary> result = IOService::nameMatching("name", table);
974 assert(result);
975 assert(result->getRetainCount() == 1);
976
977 table = result;
978 assert(table->getRetainCount() == 2);
979 OSSharedPtr<OSDictionary> result2 = IOService::nameMatching("name", table);
980 assert(result2);
981 assert(result2 == table);
982 assert(result2->getRetainCount() == 3);
983 }
984
985 {
986 OSSharedPtr<OSDictionary> table;
987 OSSharedPtr<OSDictionary> result = IOService::nameMatching(name, table);
988 assert(result);
989 assert(result->getRetainCount() == 1);
990
991 table = result;
992 assert(table->getRetainCount() == 2);
993 OSSharedPtr<OSDictionary> result2 = IOService::nameMatching(name, table);
994 assert(result2);
995 assert(result2 == table);
996 assert(result2->getRetainCount() == 3);
997 }
998
999 {
1000 OSSharedPtr<OSDictionary> table;
1001 OSSharedPtr<OSDictionary> result = IOService::resourceMatching("name", table);
1002 assert(result);
1003 assert(result->getRetainCount() == 1);
1004
1005 table = result;
1006 assert(table->getRetainCount() == 2);
1007 OSSharedPtr<OSDictionary> result2 = IOService::resourceMatching("name", table);
1008 assert(result2);
1009 assert(result2 == table);
1010 assert(result2->getRetainCount() == 3);
1011 }
1012
1013 {
1014 OSSharedPtr<OSDictionary> table;
1015 OSSharedPtr<OSDictionary> result = IOService::resourceMatching(name, table);
1016 assert(result);
1017 assert(result->getRetainCount() == 1);
1018
1019 table = result;
1020 assert(table->getRetainCount() == 2);
1021 OSSharedPtr<OSDictionary> result2 = IOService::resourceMatching(name, table);
1022 assert(result2);
1023 assert(result2 == table);
1024 assert(result2->getRetainCount() == 3);
1025 }
1026
1027 {
1028 OSSharedPtr<OSDictionary> table;
1029 OSSharedPtr<OSDictionary> result = IOService::propertyMatching(name, value, table);
1030 assert(result);
1031 assert(result->getRetainCount() == 1);
1032
1033 table = result;
1034 assert(table->getRetainCount() == 2);
1035 OSSharedPtr<OSDictionary> result2 = IOService::propertyMatching(name, value, table);
1036 assert(result2);
1037 assert(result2 == table);
1038 assert(result2->getRetainCount() == 3);
1039 }
1040
1041 {
1042 OSSharedPtr<OSDictionary> table;
1043 OSSharedPtr<OSDictionary> result = IOService::registryEntryIDMatching(12, table);
1044 assert(result);
1045 assert(result->getRetainCount() == 1);
1046
1047 table = result;
1048 assert(table->getRetainCount() == 2);
1049 OSSharedPtr<OSDictionary> result2 = IOService::registryEntryIDMatching(12, table);
1050 assert(result2);
1051 assert(result2 == table);
1052 assert(result2->getRetainCount() == 3);
1053 }
1054 OSSafeReleaseNULL(name);
1055 OSSafeReleaseNULL(value);
1056 }
1057
1058 static int
OSSharedPtrTests(int)1059 OSSharedPtrTests(int)
1060 {
1061 OSDynamicPtrCastTests();
1062 OSConstPtrCastTests();
1063 OSStaticPtrCastTests();
1064 IOServiceMatchingSharedPtrTests();
1065 return 0;
1066 }
1067
1068 static int
IOServiceStateNotificationTests(int)1069 IOServiceStateNotificationTests(int)
1070 {
1071 IOService * service = IOService::getSystemStateNotificationService();
1072 OSString * str = OSString::withCString(kIOSystemStateClamshellKey);
1073 kern_return_t kr = service->StateNotificationItemCreate(str, NULL);
1074 assert(kIOReturnSuccess == kr);
1075
1076 void (^sendClam)(OSBoolean * state) = ^void (OSBoolean * state) {
1077 OSDictionary * value;
1078 kern_return_t kr;
1079
1080 value = OSDictionary::withCapacity(4);
1081 value->setObject("value", state);
1082 kr = IOService::getSystemStateNotificationService()->StateNotificationItemSet(str, value);
1083 assert(kIOReturnSuccess == kr);
1084 value->release();
1085 };
1086 sendClam(kOSBooleanTrue);
1087 IOSleep(100);
1088 sendClam(kOSBooleanFalse);
1089 str->release();
1090
1091 str = OSString::withCString("test");
1092 OSArray * array = OSArray::withCapacity(4);
1093 array->setObject(str);
1094 IOStateNotificationListenerRef listenerRef;
1095 kr = service->stateNotificationListenerAdd(array, &listenerRef, ^kern_return_t () {
1096 IOLog("test handler\n");
1097 kern_return_t kr;
1098 OSDictionary * dict;
1099 kr = service->StateNotificationItemCopy(str, &dict);
1100 if (kIOReturnSuccess == kr) {
1101 OSSerialize * s = OSSerialize::withCapacity(4096);
1102 dict->serialize(s);
1103 IOLog("test handler %s\n", s->text());
1104 s->release();
1105 }
1106 return kIOReturnSuccess;
1107 });
1108 assert(kIOReturnSuccess == kr);
1109
1110 IOEventSource * es =
1111 IOServiceStateNotificationEventSource::serviceStateNotificationEventSource(
1112 service, array,
1113 ^void () {
1114 IOLog("test es handler\n");
1115 kern_return_t kr;
1116 OSDictionary * dict;
1117 kr = service->StateNotificationItemCopy(str, &dict);
1118 if (kIOReturnSuccess == kr) {
1119 OSSerialize * s = OSSerialize::withCapacity(4096);
1120 dict->serialize(s);
1121 IOLog("test es handler %s\n", s->text());
1122 s->release();
1123 }
1124 });
1125 assert(es != nullptr);
1126 IOService::getPlatform()->getWorkLoop()->addEventSource(es);
1127 es->enable();
1128 IOSleep(30 * 1000);
1129 IOService::getPlatform()->getWorkLoop()->removeEventSource(es);
1130 es->release();
1131
1132 return kIOReturnSuccess;
1133 }
1134
1135
1136 #endif /* DEVELOPMENT || DEBUG */
1137
1138 #ifndef __clang_analyzer__
1139 // All the scary things that this function is doing, such as the intentional
1140 // overrelease of an OSData, are hidden from the static analyzer.
1141 static int
sysctl_iokittest(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1142 sysctl_iokittest(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1143 {
1144 int error;
1145 int newValue, changed;
1146
1147 error = sysctl_io_number(req, 0, sizeof(int), &newValue, &changed);
1148 if (error) {
1149 return error;
1150 }
1151
1152 #if DEVELOPMENT || DEBUG
1153 if (changed && (66 == newValue)) {
1154 IOReturn ret;
1155 IOWorkLoop * wl = IOWorkLoop::workLoop();
1156 IOCommandGate * cg = IOCommandGate::commandGate(wl);
1157 ret = wl->addEventSource(cg);
1158
1159 struct x {
1160 uint64_t h;
1161 uint64_t l;
1162 };
1163 struct x y;
1164
1165 y.h = 0x1111111122222222;
1166 y.l = 0x3333333344444444;
1167
1168 kprintf("ret1 %d\n", ret);
1169 ret = cg->runActionBlock(^(){
1170 printf("hello %d 0x%qx\n", wl->inGate(), y.h);
1171 return 99;
1172 });
1173 kprintf("ret %d\n", ret);
1174 }
1175
1176 if (changed && (999 == newValue)) {
1177 OSData * data = OSData::withCapacity(16);
1178 data->release();
1179 data->release();
1180 }
1181
1182 if (changed && (newValue >= 6666) && (newValue <= 6669)) {
1183 OSIterator * iter;
1184 IOService * service;
1185
1186 service = NULL;
1187 iter = IOService::getMatchingServices(IOService::nameMatching("XHC1"));
1188 if (iter && (service = (IOService *) iter->getNextObject())) {
1189 if (newValue == 6666) {
1190 IOLog("terminating 0x%qx\n", service->getRegistryEntryID());
1191 service->terminate();
1192 } else if (newValue == 6667) {
1193 IOLog("register 0x%qx\n", service->getRegistryEntryID());
1194 service->registerService();
1195 }
1196 }
1197 OSSafeReleaseNULL(iter);
1198 if (service) {
1199 return 0;
1200 }
1201 }
1202
1203
1204 if (changed && (555 == newValue)) {
1205 IOServiceStateNotificationTests(newValue);
1206 }
1207
1208 if (changed && newValue) {
1209 error = IOWorkLoopTest(newValue);
1210 assert(KERN_SUCCESS == error);
1211 error = IOServiceTest(newValue);
1212 assert(KERN_SUCCESS == error);
1213 error = OSCollectionTest(newValue);
1214 assert(KERN_SUCCESS == error);
1215 error = OSCollectionIteratorTests(newValue);
1216 assert(KERN_SUCCESS == error);
1217 error = OSAllocationTests(newValue);
1218 assert(KERN_SUCCESS == error);
1219 error = OSDataAllocationTests(newValue);
1220 assert(KERN_SUCCESS == error);
1221 error = OSBoundedArrayTests(newValue);
1222 assert(KERN_SUCCESS == error);
1223 error = OSBoundedArrayRefTests(newValue);
1224 assert(KERN_SUCCESS == error);
1225 error = OSBoundedPtrTests(newValue);
1226 assert(KERN_SUCCESS == error);
1227 error = IOMemoryDescriptorTest(newValue);
1228 assert(KERN_SUCCESS == error);
1229 error = OSSharedPtrTests(newValue);
1230 assert(KERN_SUCCESS == error);
1231 error = IOSharedDataQueue_44636964(newValue);
1232 assert(KERN_SUCCESS == error);
1233 error = IOUserNotificationTests(newValue);
1234 assert(KERN_SUCCESS == error);
1235 }
1236 #endif /* DEVELOPMENT || DEBUG */
1237
1238 return error;
1239 }
1240
1241 SYSCTL_PROC(_kern, OID_AUTO, iokittest,
1242 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1243 NULL, 0, sysctl_iokittest, "I", "");
1244 #endif // __clang_analyzer__
1245
1246 #if DEVELOPMENT || DEBUG
1247
1248 /*
1249 * A simple wrapper around an IOService. This terminates the IOService in free().
1250 */
1251 class TestIOServiceHandle : public OSObject
1252 {
1253 OSDeclareDefaultStructors(TestIOServiceHandle);
1254 public:
1255 static TestIOServiceHandle * withService(IOService * service);
1256
1257 private:
1258 bool initWithService(IOService * service);
1259 virtual void free() APPLE_KEXT_OVERRIDE;
1260
1261 IOService * fService;
1262 };
1263
1264 OSDefineMetaClassAndStructors(TestIOServiceHandle, OSObject);
1265
1266 TestIOServiceHandle *
withService(IOService * service)1267 TestIOServiceHandle::withService(IOService * service)
1268 {
1269 TestIOServiceHandle * handle = new TestIOServiceHandle;
1270 if (handle && !handle->initWithService(service)) {
1271 return NULL;
1272 }
1273 return handle;
1274 }
1275
1276 bool
initWithService(IOService * service)1277 TestIOServiceHandle::initWithService(IOService * service)
1278 {
1279 fService = service;
1280 fService->retain();
1281 return true;
1282 }
1283
1284 void
free()1285 TestIOServiceHandle::free()
1286 {
1287 if (fService) {
1288 fService->terminate();
1289 OSSafeReleaseNULL(fService);
1290 }
1291 }
1292
1293 /*
1294 * Set up test IOServices. See the available services in xnu/iokit/Tests/TestServices.
1295 *
1296 * xnu darwintests use this sysctl to make these test services available. A send right is pushed
1297 * to the task that called the sysctl, which when deallocated removes the service. This ensures
1298 * that the registry isn't polluted by misbehaving tests.
1299 *
1300 * Since this sysctl allows callers to instantiate arbitrary classes based on their class name,
1301 * this can be a security concern. Tests that call this sysctl need the
1302 * kIOServiceTestServiceManagementEntitlementKey entitlement.
1303 */
1304 static int
sysctl_iokit_test_service_setup(struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1305 sysctl_iokit_test_service_setup(struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1306 {
1307 char classname[128] = {0};
1308 IOService * service; // must not release
1309 OSObject * obj = NULL; // must release
1310 IOService * provider = NULL; // must not release
1311 TestIOServiceHandle * handle = NULL; // must release
1312 mach_port_name_t name __unused;
1313 int error;
1314
1315 if (!IOTaskHasEntitlement(current_task(), kIOServiceTestServiceManagementEntitlementKey)) {
1316 error = EPERM;
1317 goto finish;
1318 }
1319
1320 error = sysctl_handle_string(oidp, classname, sizeof(classname), req);
1321 if (error != 0) {
1322 goto finish;
1323 }
1324
1325 /*
1326 * All test services currently attach to IOResources.
1327 */
1328 provider = IOService::getResourceService();
1329 if (!provider) {
1330 IOLog("Failed to find IOResources\n");
1331 error = ENOENT;
1332 goto finish;
1333 }
1334
1335 obj = OSMetaClass::allocClassWithName(classname);
1336 if (!obj) {
1337 IOLog("Failed to alloc class %s\n", classname);
1338 error = ENOENT;
1339 goto finish;
1340 }
1341
1342 service = OSDynamicCast(IOService, obj);
1343
1344 if (!service) {
1345 IOLog("Instance of class %s is not an IOService\n", classname);
1346 error = EINVAL;
1347 goto finish;
1348 }
1349
1350 if (!service->init()) {
1351 IOLog("Failed to initialize %s\n", classname);
1352 error = EINVAL;
1353 goto finish;
1354 }
1355
1356 if (!service->attach(provider)) {
1357 IOLog("Failed to attach %s\n", classname);
1358 error = EINVAL;
1359 goto finish;
1360 }
1361
1362 if (!service->start(provider)) {
1363 IOLog("Failed to start %s\n", classname);
1364 error = EINVAL;
1365 goto finish;
1366 }
1367
1368 handle = TestIOServiceHandle::withService(service);
1369 if (!handle) {
1370 IOLog("Failed to create service handle\n");
1371 error = ENOMEM;
1372 goto finish;
1373 }
1374 name = iokit_make_send_right(current_task(), handle, IKOT_IOKIT_OBJECT);
1375
1376 error = 0;
1377
1378 finish:
1379
1380 OSSafeReleaseNULL(obj);
1381 OSSafeReleaseNULL(handle);
1382 return error;
1383 }
1384
1385
1386 SYSCTL_PROC(_kern, OID_AUTO, iokit_test_service_setup,
1387 CTLTYPE_STRING | CTLFLAG_WR | CTLFLAG_KERN | CTLFLAG_LOCKED,
1388 NULL, 0, sysctl_iokit_test_service_setup, "-", "");
1389
1390 #endif /* DEVELOPMENT || DEBUG */
1391
1392
1393 static __unused void
CastCompileTest(OSObject * obj)1394 CastCompileTest(OSObject *obj)
1395 {
1396 OSDynamicCast(IOService, obj)->terminate();
1397 OSRequiredCast(IOService, obj)->terminate();
1398 }
1399