📄 loader.c
字号:
ENTER1("unloading driver: %s (%p)", driver->name, driver); TRACE1("freeing %d images", driver->num_pe_images); drv_obj = driver->drv_obj; for (i = 0; i < driver->num_pe_images; i++) if (driver->pe_images[i].image) { TRACE1("freeing image at %p", driver->pe_images[i].image); vfree(driver->pe_images[i].image); } TRACE1("freeing %d bin files", driver->num_bin_files); for (i = 0; i < driver->num_bin_files; i++) { TRACE1("freeing image at %p", driver->bin_files[i].data); if (driver->bin_files[i].data) vfree(driver->bin_files[i].data); } if (driver->bin_files) kfree(driver->bin_files); RtlFreeUnicodeString(&drv_obj->name); RemoveEntryList(&driver->list); nt_list_for_each_safe(cur, next, &driver->settings) { struct wrap_device_setting *setting; struct ndis_configuration_parameter *param; setting = container_of(cur, struct wrap_device_setting, list); TRACE2("%p", setting); param = setting->encoded; if (param) { TRACE2("%p", param); if (param->type == NdisParameterString) RtlFreeUnicodeString(¶m->data.string); ExFreePool(param); } kfree(setting); } /* this frees driver */ free_custom_extensions(drv_obj->drv_ext); kfree(drv_obj->drv_ext); TRACE1("drv_obj: %p", drv_obj); EXIT1(return);}/* call the entry point of the driver */static int start_wrap_driver(struct wrap_driver *driver){ int i; NTSTATUS ret, res; struct driver_object *drv_obj; typeof(driver->pe_images[0].entry) entry; ENTER1("%s", driver->name); drv_obj = driver->drv_obj; for (ret = res = 0, i = 0; i < driver->num_pe_images; i++) /* dlls are already started by loader */ if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) { entry = driver->pe_images[i].entry; drv_obj->start = driver->pe_images[i].entry; drv_obj->driver_size = driver->pe_images[i].size; TRACE1("entry: %p, %p, drv_obj: %p", entry, *entry, drv_obj); res = LIN2WIN2(entry, drv_obj, &drv_obj->name); ret |= res; TRACE1("entry returns %08X", res); break; } if (ret) { ERROR("driver initialization failed: %08X", ret); RtlFreeUnicodeString(&drv_obj->name); /* this frees ndis_driver */ free_custom_extensions(drv_obj->drv_ext); kfree(drv_obj->drv_ext); TRACE1("drv_obj: %p", drv_obj); ObDereferenceObject(drv_obj); EXIT1(return -EINVAL); } EXIT1(return 0);}/* * add driver to list of loaded driver but make sure this driver is * not loaded before. called with loader_mutex down */static int add_wrap_driver(struct wrap_driver *driver){ struct wrap_driver *tmp; ENTER1("name: %s", driver->name); nt_list_for_each_entry(tmp, &wrap_drivers, list) { if (stricmp(tmp->name, driver->name) == 0) { ERROR("cannot add duplicate driver"); EXIT1(return -EBUSY); } } InsertHeadList(&wrap_drivers, &driver->list); EXIT1(return 0);}/* load a driver from userspace and initialize it. called with * loader_mutex down */static int load_user_space_driver(struct load_driver *load_driver){ struct driver_object *drv_obj; struct ansi_string ansi_reg; struct wrap_driver *wrap_driver = NULL; ENTER1("%p", load_driver); drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL); if (!drv_obj) { ERROR("couldn't allocate memory"); EXIT1(return -ENOMEM); } TRACE1("drv_obj: %p", drv_obj); drv_obj->drv_ext = kmalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL); if (!drv_obj->drv_ext) { ERROR("couldn't allocate memory"); ObDereferenceObject(drv_obj); EXIT1(return -ENOMEM); } memset(drv_obj->drv_ext, 0, sizeof(*(drv_obj->drv_ext))); InitializeListHead(&drv_obj->drv_ext->custom_ext); if (IoAllocateDriverObjectExtension(drv_obj, (void *)WRAP_DRIVER_CLIENT_ID, sizeof(*wrap_driver), (void **)&wrap_driver) != STATUS_SUCCESS) EXIT1(return -ENOMEM); TRACE1("driver: %p", wrap_driver); memset(wrap_driver, 0, sizeof(*wrap_driver)); InitializeListHead(&wrap_driver->list); InitializeListHead(&wrap_driver->settings); InitializeListHead(&wrap_driver->wrap_devices); wrap_driver->drv_obj = drv_obj; RtlInitAnsiString(&ansi_reg, "/tmp"); if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) != STATUS_SUCCESS) { ERROR("couldn't initialize registry path"); free_custom_extensions(drv_obj->drv_ext); kfree(drv_obj->drv_ext); TRACE1("drv_obj: %p", drv_obj); ObDereferenceObject(drv_obj); EXIT1(return -EINVAL); } strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name)); wrap_driver->name[sizeof(wrap_driver->name)-1] = 0; if (load_sys_files(wrap_driver, load_driver) || load_bin_files_info(wrap_driver, load_driver) || load_settings(wrap_driver, load_driver) || start_wrap_driver(wrap_driver) || add_wrap_driver(wrap_driver)) { unload_wrap_driver(wrap_driver); EXIT1(return -EINVAL); } else { printk(KERN_INFO "%s: driver %s (%s) loaded\n", DRIVER_NAME, wrap_driver->name, wrap_driver->version);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) add_taint(TAINT_PROPRIETARY_MODULE); /* older kernels don't seem to have a way to set * tainted information */#endif EXIT1(return 0); }}/* register drivers for pci and usb */static void register_devices(void){ int res; memset(&wrap_pci_device, 0, sizeof(wrap_pci_device)); wrap_pci_device.vendor = PCI_ANY_ID; wrap_pci_device.device = PCI_ANY_ID; wrap_pci_device.subvendor = PCI_ANY_ID; wrap_pci_device.subdevice = PCI_ANY_ID; memset(&wrap_pci_driver, 0, sizeof(wrap_pci_driver)); wrap_pci_driver.name = DRIVER_NAME; wrap_pci_driver.id_table = &wrap_pci_device; wrap_pci_driver.probe = wrap_pnp_start_pci_device; wrap_pci_driver.remove = __devexit_p(wrap_pnp_remove_pci_device); wrap_pci_driver.suspend = wrap_pnp_suspend_pci_device; wrap_pci_driver.resume = wrap_pnp_resume_pci_device; res = pci_register_driver(&wrap_pci_driver); if (res < 0) { ERROR("couldn't register pci driver: %d", res); wrap_pci_driver.name = NULL; }#ifdef CONFIG_USB memset(&wrap_usb_device, 0, sizeof(wrap_usb_device)); wrap_usb_device.driver_info = 1; memset(&wrap_usb_driver, 0, sizeof(wrap_usb_driver)); wrap_usb_driver.name = DRIVER_NAME; wrap_usb_driver.id_table = &wrap_usb_device; wrap_usb_driver.probe = wrap_pnp_start_usb_device; wrap_usb_driver.disconnect = __devexit_p(wrap_pnp_remove_usb_device);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) wrap_usb_driver.suspend = wrap_pnp_suspend_usb_device; wrap_usb_driver.resume = wrap_pnp_resume_usb_device;#endif res = usb_register(&wrap_usb_driver); if (res < 0) { ERROR("couldn't register usb driver: %d", res); wrap_usb_driver.name = NULL; }#endif EXIT1(return);}static void unregister_devices(void){ struct nt_list *cur, *next; if (down_interruptible(&loader_mutex)) WARNING("couldn't obtain loader_mutex"); nt_list_for_each_safe(cur, next, &wrap_devices) { struct wrap_device *wd; wd = container_of(cur, struct wrap_device, list); set_bit(HW_PRESENT, &wd->hw_status); } up(&loader_mutex); if (wrap_pci_driver.name) pci_unregister_driver(&wrap_pci_driver);#ifdef CONFIG_USB if (wrap_usb_driver.name) usb_deregister(&wrap_usb_driver);#endif}struct wrap_device *load_wrap_device(struct load_device *load_device){ int ret; struct nt_list *cur; struct wrap_device *wd = NULL; char vendor[5], device[5], subvendor[5], subdevice[5], bus[5]; ENTER1("%04x, %04x, %04x, %04x", load_device->vendor, load_device->device, load_device->subvendor, load_device->subdevice); if (sprintf(vendor, "%04x", load_device->vendor) == 4 && sprintf(device, "%04x", load_device->device) == 4 && sprintf(subvendor, "%04x", load_device->subvendor) == 4 && sprintf(subdevice, "%04x", load_device->subdevice) == 4 && sprintf(bus, "%04x", load_device->bus) == 4) { char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE,#if defined(DEBUG) && DEBUG >= 1 "1",#else "0",#endif UTILS_VERSION, vendor, device, subvendor, subdevice, bus, NULL}; char *env[] = {NULL}; TRACE2("%s, %s, %s, %s, %s", vendor, device, subvendor, subdevice, bus); if (down_interruptible(&loader_mutex)) { WARNING("couldn't obtain loader_mutex"); EXIT1(return NULL); } INIT_COMPLETION(loader_complete); ret = call_usermodehelper("/sbin/loadndisdriver", argv, env#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) , 1#endif ); if (ret) { up(&loader_mutex); TRACE1("couldn't load device %04x:%04x; check system " "log for messages from 'loadndisdriver'", load_device->vendor, load_device->device); EXIT1(return NULL); } wait_for_completion(&loader_complete); wd = NULL; nt_list_for_each(cur, &wrap_devices) { wd = container_of(cur, struct wrap_device, list); TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor, wd->device, wd->subvendor, wd->subdevice); if (wd->vendor == load_device->vendor && wd->device == load_device->device) break; else wd = NULL; } up(&loader_mutex); } else wd = NULL; EXIT1(return wd);}struct wrap_device *get_wrap_device(void *dev, int bus){ struct nt_list *cur; struct wrap_device *wd; if (down_interruptible(&loader_mutex)) { WARNING("couldn't obtain loader_mutex"); return NULL; } wd = NULL; nt_list_for_each(cur, &wrap_devices) { wd = container_of(cur, struct wrap_device, list); if (bus == WRAP_PCI_BUS && wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev) break; else if (bus == WRAP_USB_BUS && wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev) break; else wd = NULL; } up(&loader_mutex); return wd;}/* called with loader_mutex is down */static int wrapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct load_driver *load_driver; struct load_device load_device; struct load_driver_file load_bin_file; int ret; ENTER1("cmd: %u", cmd); ret = 0; switch (cmd) { case WRAP_IOCTL_LOAD_DEVICE: if (copy_from_user(&load_device, (void *)arg, sizeof(load_device))) { ret = -EFAULT; break; } TRACE2("%04x, %04x, %04x, %04x", load_device.vendor, load_device.device, load_device.subvendor, load_device.subdevice); if (load_device.vendor) { struct wrap_device *wd; wd = kmalloc(sizeof(*wd), GFP_KERNEL); if (!wd) { ret = -ENOMEM; break; } memset(wd, 0, sizeof(*wd)); InitializeListHead(&wd->settings); wd->dev_bus = WRAP_BUS(load_device.bus); wd->vendor = load_device.vendor; wd->device = load_device.device; wd->subvendor = load_device.subvendor; wd->subdevice = load_device.subdevice; strncpy(wd->conf_file_name, load_device.conf_file_name, sizeof(wd->conf_file_name)); wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0; strncpy(wd->driver_name, load_device.driver_name, sizeof(wd->driver_name)); wd->driver_name[sizeof(wd->driver_name)-1] = 0; InsertHeadList(&wrap_devices, &wd->list); ret = 0; } else ret = -EINVAL; break; case WRAP_IOCTL_LOAD_DRIVER: TRACE1("loading driver at %p", (void *)arg); load_driver = vmalloc(sizeof(*load_driver)); if (!load_driver) { ret = -ENOMEM; break; } if (copy_from_user(load_driver, (void *)arg, sizeof(*load_driver))) ret = -EFAULT; else ret = load_user_space_driver(load_driver); vfree(load_driver); break; case WRAP_IOCTL_LOAD_BIN_FILE: if (copy_from_user(&load_bin_file, (void *)arg, sizeof(load_bin_file))) ret = -EFAULT; else ret = add_bin_file(&load_bin_file); break; default: ERROR("unknown ioctl %u", cmd); ret = -EINVAL; break; } complete(&loader_complete); EXIT1(return ret);}static int wrapper_ioctl_release(struct inode *inode, struct file *file){ ENTER1(""); return 0;}static struct file_operations wrapper_fops = { .owner = THIS_MODULE, .ioctl = wrapper_ioctl, .release = wrapper_ioctl_release,};static struct miscdevice wrapper_misc = { .name = DRIVER_NAME, .minor = MISC_DYNAMIC_MINOR, .fops = &wrapper_fops};int loader_init(void){ int err; InitializeListHead(&wrap_drivers); InitializeListHead(&wrap_devices); init_MUTEX(&loader_mutex); init_completion(&loader_complete); if ((err = misc_register(&wrapper_misc)) < 0 ) { ERROR("couldn't register module (%d)", err); unregister_devices(); EXIT1(return err); } register_devices(); EXIT1(return 0);}void loader_exit(void){ struct nt_list *cur, *next; ENTER1(""); misc_deregister(&wrapper_misc); unregister_devices(); if (down_interruptible(&loader_mutex)) WARNING("couldn't obtain loader_mutex"); nt_list_for_each_safe(cur, next, &wrap_drivers) { struct wrap_driver *driver; driver = container_of(cur, struct wrap_driver, list); unload_wrap_driver(driver); } up(&loader_mutex); EXIT1(return);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -