USB: serial: io_edgeport: fix NULL-deref at open
[pandora-kernel.git] / drivers / usb / serial / io_edgeport.c
index 2ee8075..5a76b1c 100644 (file)
@@ -114,7 +114,6 @@ struct edgeport_port {
        wait_queue_head_t       wait_chase;             /* for handling sleeping while waiting for chase to finish */
        wait_queue_head_t       wait_open;              /* for handling sleeping while waiting for open to finish */
        wait_queue_head_t       wait_command;           /* for handling sleeping while waiting for command to finish */
-       wait_queue_head_t       delta_msr_wait;         /* for handling sleeping while waiting for msr change to happen */
 
        struct async_icount     icount;
        struct usb_serial_port  *port;                  /* loop back to the owner of this object */
@@ -885,7 +884,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
        /* initialize our wait queues */
        init_waitqueue_head(&edge_port->wait_open);
        init_waitqueue_head(&edge_port->wait_chase);
-       init_waitqueue_head(&edge_port->delta_msr_wait);
        init_waitqueue_head(&edge_port->wait_command);
 
        /* initialize our icount structure */
@@ -1703,13 +1701,17 @@ static int edge_ioctl(struct tty_struct *tty,
                dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
                cprev = edge_port->icount;
                while (1) {
-                       prepare_to_wait(&edge_port->delta_msr_wait,
+                       prepare_to_wait(&port->delta_msr_wait,
                                                &wait, TASK_INTERRUPTIBLE);
                        schedule();
-                       finish_wait(&edge_port->delta_msr_wait, &wait);
+                       finish_wait(&port->delta_msr_wait, &wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        cnow = edge_port->icount;
                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
                            cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -2090,7 +2092,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
                        icount->dcd++;
                if (newMsr & EDGEPORT_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&edge_port->delta_msr_wait);
+               wake_up_interruptible(&edge_port->port->delta_msr_wait);
        }
 
        /* Save the new modem status */
@@ -2934,6 +2936,11 @@ static int edge_startup(struct usb_serial *serial)
                                        EDGE_COMPATIBILITY_MASK1,
                                        EDGE_COMPATIBILITY_MASK2 };
 
+       if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
        dev = serial->dev;
 
        /* create our private serial structure */