diff options
author | David S. Miller <davem@davemloft.net> | 2015-12-15 18:24:22 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-12-15 18:24:22 (GMT) |
commit | 58ab367b85f45a9714af2f8bf122463285f80f5b (patch) | |
tree | 3780278c6946b64fdde2d1ec5a47b4251cca89a0 | |
parent | 389e4e04ad2d4887c7bdd7c01a93d3dfa5c14a06 (diff) | |
parent | 8aeb3c3d655e22d3aa5ba49f313157bd27354bb4 (diff) | |
download | linux-58ab367b85f45a9714af2f8bf122463285f80f5b.tar.xz |
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: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/isdn/gigaset/ser-gigaset.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 375be50..2a506fe 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -67,8 +67,7 @@ static int write_modem(struct cardstate *cs) struct sk_buff *skb = bcs->tx_skb; int sent = -EOPNOTSUPP; - if (!tty || !tty->driver || !skb) - return -EINVAL; + WARN_ON(!tty || !tty->ops || !skb); if (!skb->len) { dev_kfree_skb_any(skb); @@ -109,8 +108,7 @@ static int send_cb(struct cardstate *cs) unsigned long flags; int sent = 0; - if (!tty || !tty->driver) - return -EFAULT; + WARN_ON(!tty || !tty->ops); cb = cs->cmdbuf; if (!cb) @@ -370,19 +368,18 @@ static void gigaset_freecshw(struct cardstate *cs) tasklet_kill(&cs->write_tasklet); if (!cs->hw.ser) return; - dev_set_drvdata(&cs->hw.ser->dev.dev, NULL); platform_device_unregister(&cs->hw.ser->dev); - kfree(cs->hw.ser); - cs->hw.ser = NULL; } 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 */ - kfree(dev->platform_data); - kfree(pdev->resource); + if (!cs) + return; + 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, struct tty_struct *tty = cs->hw.ser->tty; 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; set = new_state & ~old_state; clear = old_state & ~new_state; |