Commit 58ab367b authored by David S. Miller's avatar David S. Miller

Merge branch 'ser_gigaset-platform-device-dealloc'

Paul Bolle says:

====================
ser_gigaset: fix deallocation of platform device structure

Sascha Levin reported that the syzkaller fuzzer triggered a WARNING in
ser_gigaset (see https://lkml.kernel.org/g/56587467.8050102@oracle.com ). It
turned out that ser_gigaset has always deallocated its platform device
structure incorrectly. Tilman submitted the patch that fixes that (3/4) and a
related cleanup (4/4).

Tilman also submitted a minor cleanup of some NULL checks (1/4) that prompted
Alan to turn those checks into WARN_ONs (2/4). If no one hits these WARN_ONs in
the next couple of releases these WARN_ONs should be removed.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 389e4e04 8aeb3c3d
...@@ -67,8 +67,7 @@ static int write_modem(struct cardstate *cs) ...@@ -67,8 +67,7 @@ static int write_modem(struct cardstate *cs)
struct sk_buff *skb = bcs->tx_skb; struct sk_buff *skb = bcs->tx_skb;
int sent = -EOPNOTSUPP; int sent = -EOPNOTSUPP;
if (!tty || !tty->driver || !skb) WARN_ON(!tty || !tty->ops || !skb);
return -EINVAL;
if (!skb->len) { if (!skb->len) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -109,8 +108,7 @@ static int send_cb(struct cardstate *cs) ...@@ -109,8 +108,7 @@ static int send_cb(struct cardstate *cs)
unsigned long flags; unsigned long flags;
int sent = 0; int sent = 0;
if (!tty || !tty->driver) WARN_ON(!tty || !tty->ops);
return -EFAULT;
cb = cs->cmdbuf; cb = cs->cmdbuf;
if (!cb) if (!cb)
...@@ -370,19 +368,18 @@ static void gigaset_freecshw(struct cardstate *cs) ...@@ -370,19 +368,18 @@ static void gigaset_freecshw(struct cardstate *cs)
tasklet_kill(&cs->write_tasklet); tasklet_kill(&cs->write_tasklet);
if (!cs->hw.ser) if (!cs->hw.ser)
return; return;
dev_set_drvdata(&cs->hw.ser->dev.dev, NULL);
platform_device_unregister(&cs->hw.ser->dev); platform_device_unregister(&cs->hw.ser->dev);
kfree(cs->hw.ser);
cs->hw.ser = NULL;
} }
static void gigaset_device_release(struct device *dev) static void gigaset_device_release(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct cardstate *cs = dev_get_drvdata(dev);
/* adapted from platform_device_release() in drivers/base/platform.c */ if (!cs)
kfree(dev->platform_data); return;
kfree(pdev->resource); dev_set_drvdata(dev, NULL);
kfree(cs->hw.ser);
cs->hw.ser = NULL;
} }
/* /*
...@@ -432,7 +429,9 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, ...@@ -432,7 +429,9 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
struct tty_struct *tty = cs->hw.ser->tty; struct tty_struct *tty = cs->hw.ser->tty;
unsigned int set, clear; unsigned int set, clear;
if (!tty || !tty->driver || !tty->ops->tiocmset) WARN_ON(!tty || !tty->ops);
/* tiocmset is an optional tty driver method */
if (!tty->ops->tiocmset)
return -EINVAL; return -EINVAL;
set = new_state & ~old_state; set = new_state & ~old_state;
clear = old_state & ~new_state; clear = old_state & ~new_state;
......
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