Commit abf492e7 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

USB: kl5kusb105: fix DMA buffers on stack

Cc: Oliver Neukum <oliver@neukum.name>
Signed-off-by: default avatarJohan Hovold <jhovold@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent ca65d256
...@@ -212,10 +212,19 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, ...@@ -212,10 +212,19 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
unsigned long *line_state_p) unsigned long *line_state_p)
{ {
int rc; int rc;
__u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1}; u8 *status_buf;
__u16 status; __u16 status;
dev_info(&port->serial->dev->dev, "sending SIO Poll request\n"); 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, rc = usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0), usb_rcvctrlpipe(port->serial->dev, 0),
KL5KUSB105A_SIO_POLL, KL5KUSB105A_SIO_POLL,
...@@ -236,6 +245,8 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, ...@@ -236,6 +245,8 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
*line_state_p = klsi_105_status2linestate(status); *line_state_p = klsi_105_status2linestate(status);
} }
kfree(status_buf);
return rc; return rc;
} }
...@@ -364,7 +375,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) ...@@ -364,7 +375,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
int rc; int rc;
int i; int i;
unsigned long line_state; unsigned long line_state;
struct klsi_105_port_settings cfg; struct klsi_105_port_settings *cfg;
unsigned long flags; unsigned long flags;
dbg("%s port %d", __func__, port->number); 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) ...@@ -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 * Then read the modem line control and store values in
* priv->line_state. * priv->line_state.
*/ */
cfg.pktlen = 5; cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
cfg.baudrate = kl5kusb105a_sio_b9600; if (!cfg) {
cfg.databits = kl5kusb105a_dtb_8; dev_err(&port->dev, "%s - out of memory for config buffer.\n",
cfg.unknown1 = 0; __func__);
cfg.unknown2 = 1; return -ENOMEM;
klsi_105_chg_port_settings(port, &cfg); }
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 */ /* set up termios structure */
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
...@@ -391,11 +408,11 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) ...@@ -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; priv->termios.c_lflag = tty->termios->c_lflag;
for (i = 0; i < NCCS; i++) for (i = 0; i < NCCS; i++)
priv->termios.c_cc[i] = tty->termios->c_cc[i]; priv->termios.c_cc[i] = tty->termios->c_cc[i];
priv->cfg.pktlen = cfg.pktlen; priv->cfg.pktlen = cfg->pktlen;
priv->cfg.baudrate = cfg.baudrate; priv->cfg.baudrate = cfg->baudrate;
priv->cfg.databits = cfg.databits; priv->cfg.databits = cfg->databits;
priv->cfg.unknown1 = cfg.unknown1; priv->cfg.unknown1 = cfg->unknown1;
priv->cfg.unknown2 = cfg.unknown2; priv->cfg.unknown2 = cfg->unknown2;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
/* READ_ON and urb submission */ /* READ_ON and urb submission */
...@@ -441,6 +458,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) ...@@ -441,6 +458,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
retval = rc; retval = rc;
exit: exit:
kfree(cfg);
return retval; return retval;
} /* klsi_105_open */ } /* klsi_105_open */
...@@ -714,10 +732,17 @@ static void klsi_105_set_termios(struct tty_struct *tty, ...@@ -714,10 +732,17 @@ static void klsi_105_set_termios(struct tty_struct *tty,
unsigned int old_iflag = old_termios->c_iflag; unsigned int old_iflag = old_termios->c_iflag;
unsigned int cflag = tty->termios->c_cflag; unsigned int cflag = tty->termios->c_cflag;
unsigned int old_cflag = old_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; unsigned long flags;
speed_t baud; 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 */ /* lock while we are modifying the settings */
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
...@@ -793,11 +818,11 @@ static void klsi_105_set_termios(struct tty_struct *tty, ...@@ -793,11 +818,11 @@ static void klsi_105_set_termios(struct tty_struct *tty,
case CS5: case CS5:
dbg("%s - 5 bits/byte not supported", __func__); dbg("%s - 5 bits/byte not supported", __func__);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return ; goto err;
case CS6: case CS6:
dbg("%s - 6 bits/byte not supported", __func__); dbg("%s - 6 bits/byte not supported", __func__);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return ; goto err;
case CS7: case CS7:
priv->cfg.databits = kl5kusb105a_dtb_7; priv->cfg.databits = kl5kusb105a_dtb_7;
break; break;
...@@ -856,11 +881,13 @@ static void klsi_105_set_termios(struct tty_struct *tty, ...@@ -856,11 +881,13 @@ static void klsi_105_set_termios(struct tty_struct *tty,
#endif #endif
; ;
} }
memcpy(&cfg, &priv->cfg, sizeof(cfg)); memcpy(cfg, &priv->cfg, sizeof(*cfg));
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
/* now commit changes to device */ /* 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 */ } /* klsi_105_set_termios */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment