This is xnu-11215.1.10. See this file in:
#include <darwintest.h>
#include <mach/mach.h>
#include <mach/message.h>
#include <stdlib.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
T_GLOBAL_META(
T_META_NAMESPACE("xnu.iokit"),
T_META_RUN_CONCURRENTLY(true),
T_META_ASROOT(true),
T_META_RADAR_COMPONENT_NAME("xnu"),
T_META_RADAR_COMPONENT_VERSION("IOKit"),
T_META_OWNER("souvik_b"));
struct notification_create_thread_args {
size_t iterations;
};
static void *
notification_create_thread(void * data)
{
struct notification_create_thread_args * args = (struct notification_create_thread_args *)data;
for (size_t x = 0; x < args->iterations; x++) {
IONotificationPortRef notifyPort = IONotificationPortCreate(kIOMainPortDefault);
io_iterator_t notification;
IOServiceAddMatchingNotification(notifyPort, kIOTerminatedNotification, IOServiceMatching("IOResources"), NULL, NULL, ¬ification);
usleep(5000);
IOObjectRelease(notification);
IONotificationPortDestroy(notifyPort);
}
return NULL;
}
struct iokit_port_object_description_thread_args {
size_t iterations;
};
static void *
iokit_port_object_description_thread(void * data)
{
struct iokit_port_object_description_thread_args * args = (struct iokit_port_object_description_thread_args *)data;
for (size_t x = 0; x < args->iterations; x++) {
mach_port_name_array_t portNameArray;
mach_msg_type_number_t portNameCount;
mach_port_type_array_t portTypeArray;
mach_msg_type_number_t portTypeCount;
unsigned int kotype = 0;
mach_vm_address_t kaddr;
kobject_description_t desc;
desc[0] = '\0';
T_QUIET; T_ASSERT_MACH_SUCCESS(mach_port_names(mach_task_self(), &portNameArray, &portNameCount, &portTypeArray, &portTypeCount), "mach_port_names");
for (size_t i = 0; i < portNameCount; i++) {
mach_port_name_t port = portNameArray[i];
/* the return value doesn't matter */
(void)mach_port_kobject_description(mach_task_self(), port, &kotype, &kaddr, desc);
}
T_QUIET; T_ASSERT_MACH_SUCCESS(vm_deallocate(mach_task_self(), (vm_address_t) portNameArray, portNameCount * sizeof(*portNameArray)), "vm_deallocate port name array");
T_QUIET; T_ASSERT_MACH_SUCCESS(vm_deallocate(mach_task_self(), (vm_address_t) portTypeArray, portTypeCount * sizeof(*portTypeArray)), "vm_deallocate port type array");
}
return NULL;
}
T_DECL(port_object_description_race, "Test iokit_port_object_description() race condition", T_META_TAG_VM_PREFERRED)
{
pthread_t notification_create_pth;
pthread_t iokit_port_object_description_pth;
struct notification_create_thread_args notification_create_args;
struct iokit_port_object_description_thread_args iokit_port_object_description_args;
notification_create_args.iterations = 2000;
iokit_port_object_description_args.iterations = 2000;
// start racing threads
T_ASSERT_POSIX_ZERO(pthread_create(¬ification_create_pth, NULL, notification_create_thread, ¬ification_create_args), "create notification thread");
T_ASSERT_POSIX_ZERO(pthread_create(&iokit_port_object_description_pth, NULL, iokit_port_object_description_thread, &iokit_port_object_description_args), "create port description thread");
// wait for threads to finish
T_ASSERT_POSIX_ZERO(pthread_join(notification_create_pth, NULL), "join notificiation thread");
T_ASSERT_POSIX_ZERO(pthread_join(iokit_port_object_description_pth, NULL), "join port description thread");
}