Commit 9616ff43 authored by David S. Miller's avatar David S. Miller

sunsu: Fix use after free in su_remove().

Real serial port 'up' objects are statically allocated from an
array in the driver.  Keyboard and mouse ports, on the other
hand, are dynamically allocated.

Unfortunately, we free these dynamic 'up' objects before we unmap the
I/O registers.

Rearrange su_remove() so that this does not happen.

Noticed by Julia Lawall.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c1f6afc
...@@ -1500,20 +1500,25 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m ...@@ -1500,20 +1500,25 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
static int __devexit su_remove(struct of_device *op) static int __devexit su_remove(struct of_device *op)
{ {
struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
bool kbdms = false;
if (up->su_type == SU_PORT_MS || if (up->su_type == SU_PORT_MS ||
up->su_type == SU_PORT_KBD) { up->su_type == SU_PORT_KBD)
kbdms = true;
if (kbdms) {
#ifdef CONFIG_SERIO #ifdef CONFIG_SERIO
serio_unregister_port(&up->serio); serio_unregister_port(&up->serio);
#endif #endif
kfree(up); } else if (up->port.type != PORT_UNKNOWN)
} else if (up->port.type != PORT_UNKNOWN) {
uart_remove_one_port(&sunsu_reg, &up->port); uart_remove_one_port(&sunsu_reg, &up->port);
}
if (up->port.membase) if (up->port.membase)
of_iounmap(&op->resource[0], up->port.membase, up->reg_size); of_iounmap(&op->resource[0], up->port.membase, up->reg_size);
if (kbdms)
kfree(up);
dev_set_drvdata(&op->dev, NULL); dev_set_drvdata(&op->dev, NULL);
return 0; return 0;
......
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