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

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

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
Loading
Loading
Loading
Loading
+11 −12
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	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,
	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;