void kmsg_load_kext(kmsg_load_kext_msg_t* msg) { /* * mach_msg_header_t head; * void* buffer; * unsigned int buffer_len; */ Boolean ret; size_t size; void* buf; const struct nlist* nl; size = msg->buffer_len; buf = ke_alloc(size); if (copy_from_user(buf, msg->buffer, size)) { printk(KERN_WARNING "kmsg_load_kext: goof \n"); return; } KXFile file; kld_file_map(buf, size, &file); nl = kld_find_symbol_by_name(&file, "_CoolStuff"); if (nl == NULL) { printk(KERN_WARNING "kmsg_load_kext: symbol not found \n"); return; } uintptr_t val = nl->n_value; uint16_t* whatever = (uint16_t*)((val + file.fSegmentOffset + (uintptr_t)file.fMachO) | 1); ray = (void*)whatever; printk(KERN_WARNING "func {abs=%p, rel=%p, sect=%p} \n", (void*)ray, (void*)nl->n_value, (void*)file.fSegmentOffset); printk(KERN_WARNING "instruct: %p \n", (void*)*(whatever)); printk(KERN_WARNING "call {%d} \n", ray()); }
/********************************************************************* * This function reads the startup extensions dictionary to get the * address and length of the executable data for the requested kmod. *********************************************************************/ static int map_and_patch(const char * kmod_name) { char *address; // Does the kld system already know about this kmod? address = (char *) kld_file_getaddr(kmod_name, NULL); if (address) return 1; // None of these needs to be released. OSDictionary * extensionsDict; OSDictionary * kmodDict; OSData * compressedCode = 0; // Driver Code may need to be released OSData * driverCode; /* Get the requested kmod's info dictionary from the global * startup extensions dictionary. */ extensionsDict = getStartupExtensions(); if (!extensionsDict) { IOLog("map_and_patch(): No extensions dictionary.\n"); LOG_DELAY(); return 0; } kmodDict = OSDynamicCast(OSDictionary, extensionsDict->getObject(kmod_name)); if (!kmodDict) { IOLog("map_and_patch(): " "Extension \"%s\" cannot be found.\n", kmod_name); LOG_DELAY(); return 0; } Boolean ret = false; driverCode = OSDynamicCast(OSData, kmodDict->getObject("code")); if (driverCode) { ret = kld_file_map(kmod_name, (unsigned char *) driverCode->getBytesNoCopy(), (size_t) driverCode->getLength(), /* isKmem */ false); } else { // May be an compressed extension // If we have a compressed segment the uncompressModule // will return a new OSData object that points to the kmem_alloced // memory. Note we don't take a reference to driverCode so later // when we release it we will actually free this driver. Ownership // of the kmem has been handed of to kld_file. compressedCode = OSDynamicCast(OSData, kmodDict->getObject("compressedCode")); if (!compressedCode) { IOLog("map_and_patch(): " "Extension \"%s\" has no \"code\" property.\n", kmod_name); LOG_DELAY(); return 0; } if (!uncompressModule(compressedCode, &driverCode)) { IOLog("map_and_patch(): " "Extension \"%s\" Couldn't uncompress code.\n", kmod_name); LOG_DELAY(); return 0; } unsigned char *driver = (unsigned char *) driverCode->getBytesNoCopy(); size_t driverSize = driverCode->getLength(); ret = kld_file_map(kmod_name, driver, driverSize, /* isKmem */ true); driverCode->release(); if (!ret) kmem_free(kernel_map, (vm_address_t) driver, driverSize); } if (!ret) { IOLog("map_and_patch(): " "Extension \"%s\" Didn't successfully load.\n", kmod_name); LOG_DELAY(); return 0; } ret = TRUE; if (!kld_file_patch_OSObjects(kmod_name)) { IOLog("map_and_patch(): " "Extension \"%s\" Error binding OSObjects.\n", kmod_name); LOG_DELAY(); // RY: Instead of returning here, set the return value. // We still need to call kld_file_prepare_for_link because // we might have patched files outside of the driver. Don't // worry, it will know to ignore the damaged file ret = FALSE; } // Now repair any damage that the kld patcher may have done to the image kld_file_prepare_for_link(); return ret; }