Hello, attached is a patch that fixes some critical and some less critical, but still harmful bugs in the input drivers. It's against 2.4.0-test11-pre6. Joysticks: drivers/joystick/adi.c: Fix X/Y axes on Logitech gamepads. drivers/joystick/ns558.c: Fix module impossible to load for ISA devices unless CONFIG_HOTPLUG - bug added in test11-pre6. [critical] Fix oops on unload if PCI gameports present. [critical] Fix oops on unload if PCI gameports not present, - bug added in test11-pre6. [critical] Fix memory leak on unload. [critical] drivers/char/joystick/sidewinder.c Fix missing button on MS FF Wheel. Input [USB+Joystick]: drivers/input/input.c: Fix a possible race at open - fix by Oliver Neukum. [critical] drivers/input/evdev.c: Fix possible overflows in connect and open. [critical] drivers/input/joydev.c: Fix possible overflows in connect and open. [critical] drivers/input/mousedev.c: Fix possible overflows in connect and open. [critical] Add missing randomness reporting. Please apply it. Thanks. -- Vojtech Pavlik SuSE Labs
diff -urN linux-2.4.0-test11-pre6/drivers/char/joystick/adi.c linux/drivers/char/joystick/adi.c --- linux-2.4.0-test11-pre6/drivers/char/joystick/adi.c Thu Jun 22 15:59:58 2000 +++ linux/drivers/char/joystick/adi.c Fri Nov 17 16:20:09 2000 @@ -418,7 +418,7 @@ adi->dev.private = port; adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - for (i = 0; i < adi->axes10 + adi->axes8 + adi->hats * 2; i++) + for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; +i++) set_bit(adi->abs[i], &adi->dev.absbit); for (i = 0; i < adi->buttons; i++) @@ -431,7 +431,7 @@ if (!adi->length) return; - for (i = 0; i < adi->axes10 + adi->axes8 + adi->hats * 2; i++) { + for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; +i++) { t = adi->abs[i]; x = adi->dev.abs[t]; diff -urN linux-2.4.0-test11-pre6/drivers/char/joystick/ns558.c linux/drivers/char/joystick/ns558.c --- linux-2.4.0-test11-pre6/drivers/char/joystick/ns558.c Fri Nov 17 16:13:41 2000 +++ linux/drivers/char/joystick/ns558.c Fri Nov 17 16:20:51 2000 @@ -58,6 +58,7 @@ }; static struct ns558 *ns558; +static int ns558_pci; /* * ns558_isa_probe() tries to find an isa gameport at the @@ -187,12 +188,10 @@ } memset(port, 0, sizeof(struct ns558)); - port->next = ns558; port->type = NS558_PCI; port->gameport.io = ioport; port->gameport.size = iolen; port->dev = pdev; - ns558 = port; pdev->driver_data = port; @@ -315,8 +314,7 @@ * it is the least-invasive probe. */ - i = pci_register_driver(&ns558_pci_driver); - if (i < 0) return i; + ns558_pci = !pci_module_init(&ns558_pci_driver); /* * Probe for ISA ports. @@ -337,12 +335,12 @@ } #endif - return 0; + return (ns558 || ns558_pci) ? 0 : -ENODEV; } void __exit ns558_exit(void) { - struct ns558 *port = ns558; + struct ns558 *next, *port = ns558; while (port) { gameport_unregister_port(&port->gameport); @@ -363,10 +361,13 @@ break; } - port = port->next; + next = port->next; + kfree(port); + port = next; } - pci_unregister_driver(&ns558_pci_driver); + if (ns558_pci) + pci_unregister_driver(&ns558_pci_driver); } module_init(ns558_init); diff -urN linux-2.4.0-test11-pre6/drivers/char/joystick/sidewinder.c linux/drivers/char/joystick/sidewinder.c --- linux-2.4.0-test11-pre6/drivers/char/joystick/sidewinder.c Mon Aug 14 22:55:01 2000 +++ linux/drivers/char/joystick/sidewinder.c Fri Nov 17 16:20:09 2000 @@ -102,7 +102,7 @@ { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT }, { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT }, { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }, - { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3 }}; + { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, +BTN_BASE4 }}; static struct { int x; diff -urN linux-2.4.0-test11-pre6/drivers/input/evdev.c linux/drivers/input/evdev.c --- linux-2.4.0-test11-pre6/drivers/input/evdev.c Fri Jul 28 03:36:54 2000 +++ linux/drivers/input/evdev.c Fri Nov 17 16:20:12 2000 @@ -123,7 +123,7 @@ struct evdev_list *list; int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE; - if (i > EVDEV_MINORS || !evdev_table[i]) + if (i >= EVDEV_MINORS || !evdev_table[i]) return -ENODEV; if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) @@ -288,7 +288,7 @@ int minor; for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); - if (evdev_table[minor]) { + if (minor == EVDEV_MINORS) { printk(KERN_ERR "evdev: no more free evdev devices\n"); return NULL; } diff -urN linux-2.4.0-test11-pre6/drivers/input/input.c linux/drivers/input/input.c --- linux-2.4.0-test11-pre6/drivers/input/input.c Wed Nov 15 11:03:35 2000 +++ linux/drivers/input/input.c Fri Nov 17 16:20:12 2000 @@ -29,6 +29,8 @@ */ #include <linux/init.h> +#include <linux/sched.h> +#include <linux/smp_lock.h> #include <linux/input.h> #include <linux/module.h> #include <linux/random.h> @@ -378,7 +380,11 @@ } old_fops = file->f_op; file->f_op = new_fops; + + lock_kernel(); err = new_fops->open(inode, file); + unlock_kernel(); + if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); diff -urN linux-2.4.0-test11-pre6/drivers/input/joydev.c linux/drivers/input/joydev.c --- linux-2.4.0-test11-pre6/drivers/input/joydev.c Tue Aug 22 18:06:31 2000 +++ linux/drivers/input/joydev.c Fri Nov 17 16:20:12 2000 @@ -193,7 +193,7 @@ struct joydev_list *list; int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE; - if (i > JOYDEV_MINORS || !joydev_table[i]) + if (i >= JOYDEV_MINORS || !joydev_table[i]) return -ENODEV; if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) @@ -395,7 +395,7 @@ || test_bit(BTN_1, dev->keybit)))) return NULL; for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); - if (joydev_table[minor]) { + if (minor == JOYDEV_MINORS) { printk(KERN_ERR "joydev: no more free joydev devices\n"); return NULL; } diff -urN linux-2.4.0-test11-pre6/drivers/input/mousedev.c linux/drivers/input/mousedev.c --- linux-2.4.0-test11-pre6/drivers/input/mousedev.c Tue Aug 22 18:06:31 2000 +++ linux/drivers/input/mousedev.c Fri Nov 17 16:20:12 2000 @@ -39,6 +39,7 @@ #include <linux/input.h> #include <linux/config.h> #include <linux/smp_lock.h> +#include <linux/random.h> #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X #define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 @@ -86,6 +87,8 @@ struct mousedev_list *list; int index, size; + add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value); + while (*mousedev) { list = (*mousedev)->list; while (list) { @@ -213,7 +216,7 @@ struct mousedev_list *list; int i = MINOR(inode->i_rdev) - MOUSEDEV_MINOR_BASE; - if (i > MOUSEDEV_MINORS || !mousedev_table[i]) + if (i >= MOUSEDEV_MINORS || !mousedev_table[i]) return -ENODEV; if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) @@ -407,7 +410,7 @@ return NULL; for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); - if (mousedev_table[minor]) { + if (minor == MOUSEDEV_MINORS) { printk(KERN_ERR "mousedev: no more free mousedev devices\n"); return NULL; }