Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 456c5be5 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

USB: ch341: fix port-data memory leak



Fix port-data memory leak by moving port data allocation to port_probe
and actually implementing deallocation.

Note that this driver has never even bothered to try to deallocate it's
port data...

Compile-only tested.

Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarJohan Hovold <jhovold@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c467206e
Loading
Loading
Loading
Loading
+16 −7
Original line number Original line Diff line number Diff line
@@ -242,13 +242,11 @@ out: kfree(buffer);
	return r;
	return r;
}
}


/* allocate private data */
static int ch341_port_probe(struct usb_serial_port *port)
static int ch341_attach(struct usb_serial *serial)
{
{
	struct ch341_private *priv;
	struct ch341_private *priv;
	int r;
	int r;


	/* private data */
	priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
	priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
	if (!priv)
	if (!priv)
		return -ENOMEM;
		return -ENOMEM;
@@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)
	priv->baud_rate = DEFAULT_BAUD_RATE;
	priv->baud_rate = DEFAULT_BAUD_RATE;
	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;


	r = ch341_configure(serial->dev, priv);
	r = ch341_configure(port->serial->dev, priv);
	if (r < 0)
	if (r < 0)
		goto error;
		goto error;


	usb_set_serial_port_data(serial->port[0], priv);
	usb_set_serial_port_data(port, priv);
	return 0;
	return 0;


error:	kfree(priv);
error:	kfree(priv);
	return r;
	return r;
}
}


static int ch341_port_remove(struct usb_serial_port *port)
{
	struct ch341_private *priv;

	priv = usb_get_serial_port_data(port);
	kfree(priv);

	return 0;
}

static int ch341_carrier_raised(struct usb_serial_port *port)
static int ch341_carrier_raised(struct usb_serial_port *port)
{
{
	struct ch341_private *priv = usb_get_serial_port_data(port);
	struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)
static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
{
{
	struct usb_serial *serial = port->serial;
	struct usb_serial *serial = port->serial;
	struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
	struct ch341_private *priv = usb_get_serial_port_data(port);
	int r;
	int r;


	priv->baud_rate = DEFAULT_BAUD_RATE;
	priv->baud_rate = DEFAULT_BAUD_RATE;
@@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {
	.tiocmget          = ch341_tiocmget,
	.tiocmget          = ch341_tiocmget,
	.tiocmset          = ch341_tiocmset,
	.tiocmset          = ch341_tiocmset,
	.read_int_callback = ch341_read_int_callback,
	.read_int_callback = ch341_read_int_callback,
	.attach            = ch341_attach,
	.port_probe        = ch341_port_probe,
	.port_remove       = ch341_port_remove,
	.reset_resume      = ch341_reset_resume,
	.reset_resume      = ch341_reset_resume,
};
};