USB: kl5kusb105: fix DMA buffers on stack
authorJohan Hovold <jhovold@gmail.com>
Mon, 28 Dec 2009 22:01:52 +0000 (23:01 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 2 Mar 2010 22:53:55 +0000 (14:53 -0800)
Cc: Oliver Neukum <oliver@neukum.name>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/kl5kusb105.c

index 3a7873806f465aaf02a41213df7c2d41e5f866f1..731964b5ded6c92488627e71b67fcb52cde8bad8 100644 (file)
@@ -212,10 +212,19 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
                                   unsigned long *line_state_p)
 {
        int rc;
-       __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1};
+       u8 *status_buf;
        __u16 status;
 
        dev_info(&port->serial->dev->dev, "sending SIO Poll request\n");
+
+       status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL);
+       if (!status_buf) {
+               dev_err(&port->dev, "%s - out of memory for status buffer.\n",
+                               __func__);
+               return -ENOMEM;
+       }
+       status_buf[0] = 0xff;
+       status_buf[1] = 0xff;
        rc = usb_control_msg(port->serial->dev,
                             usb_rcvctrlpipe(port->serial->dev, 0),
                             KL5KUSB105A_SIO_POLL,
@@ -236,6 +245,8 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
 
                *line_state_p = klsi_105_status2linestate(status);
        }
+
+       kfree(status_buf);
        return rc;
 }
 
@@ -364,7 +375,7 @@ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
        int rc;
        int i;
        unsigned long line_state;
-       struct klsi_105_port_settings cfg;
+       struct klsi_105_port_settings *cfg;
        unsigned long flags;
 
        dbg("%s port %d", __func__, port->number);
@@ -376,12 +387,18 @@ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
         * Then read the modem line control and store values in
         * priv->line_state.
         */
-       cfg.pktlen   = 5;
-       cfg.baudrate = kl5kusb105a_sio_b9600;
-       cfg.databits = kl5kusb105a_dtb_8;
-       cfg.unknown1 = 0;
-       cfg.unknown2 = 1;
-       klsi_105_chg_port_settings(port, &cfg);
+       cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
+       if (!cfg) {
+               dev_err(&port->dev, "%s - out of memory for config buffer.\n",
+                               __func__);
+               return -ENOMEM;
+       }
+       cfg->pktlen   = 5;
+       cfg->baudrate = kl5kusb105a_sio_b9600;
+       cfg->databits = kl5kusb105a_dtb_8;
+       cfg->unknown1 = 0;
+       cfg->unknown2 = 1;
+       klsi_105_chg_port_settings(port, cfg);
 
        /* set up termios structure */
        spin_lock_irqsave(&priv->lock, flags);
@@ -391,11 +408,11 @@ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
        priv->termios.c_lflag = tty->termios->c_lflag;
        for (i = 0; i < NCCS; i++)
                priv->termios.c_cc[i] = tty->termios->c_cc[i];
-       priv->cfg.pktlen   = cfg.pktlen;
-       priv->cfg.baudrate = cfg.baudrate;
-       priv->cfg.databits = cfg.databits;
-       priv->cfg.unknown1 = cfg.unknown1;
-       priv->cfg.unknown2 = cfg.unknown2;
+       priv->cfg.pktlen   = cfg->pktlen;
+       priv->cfg.baudrate = cfg->baudrate;
+       priv->cfg.databits = cfg->databits;
+       priv->cfg.unknown1 = cfg->unknown1;
+       priv->cfg.unknown2 = cfg->unknown2;
        spin_unlock_irqrestore(&priv->lock, flags);
 
        /* READ_ON and urb submission */
@@ -441,6 +458,7 @@ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
                retval = rc;
 
 exit:
+       kfree(cfg);
        return retval;
 } /* klsi_105_open */
 
@@ -714,10 +732,17 @@ static void klsi_105_set_termios(struct tty_struct *tty,
        unsigned int old_iflag = old_termios->c_iflag;
        unsigned int cflag = tty->termios->c_cflag;
        unsigned int old_cflag = old_termios->c_cflag;
-       struct klsi_105_port_settings cfg;
+       struct klsi_105_port_settings *cfg;
        unsigned long flags;
        speed_t baud;
 
+       cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
+       if (!cfg) {
+               dev_err(&port->dev, "%s - out of memory for config buffer.\n",
+                               __func__);
+               return;
+       }
+
        /* lock while we are modifying the settings */
        spin_lock_irqsave(&priv->lock, flags);
 
@@ -793,11 +818,11 @@ static void klsi_105_set_termios(struct tty_struct *tty,
                case CS5:
                        dbg("%s - 5 bits/byte not supported", __func__);
                        spin_unlock_irqrestore(&priv->lock, flags);
-                       return ;
+                       goto err;
                case CS6:
                        dbg("%s - 6 bits/byte not supported", __func__);
                        spin_unlock_irqrestore(&priv->lock, flags);
-                       return ;
+                       goto err;
                case CS7:
                        priv->cfg.databits = kl5kusb105a_dtb_7;
                        break;
@@ -856,11 +881,13 @@ static void klsi_105_set_termios(struct tty_struct *tty,
 #endif
                ;
        }
-       memcpy(&cfg, &priv->cfg, sizeof(cfg));
+       memcpy(cfg, &priv->cfg, sizeof(*cfg));
        spin_unlock_irqrestore(&priv->lock, flags);
 
        /* now commit changes to device */
-       klsi_105_chg_port_settings(port, &cfg);
+       klsi_105_chg_port_settings(port, cfg);
+err:
+       kfree(cfg);
 } /* klsi_105_set_termios */