| From 4e8f2535c8078c8c9d6538a645ae2206b3151850 Mon Sep 17 00:00:00 2001 |
| From: Julian Wiedmann <jwi@linux.ibm.com> |
| Date: Mon, 4 Feb 2019 17:40:08 +0100 |
| Subject: s390/qeth: cancel close_dev work before removing a card |
| |
| [ Upstream commit c2780c1a3fb724560b1d44f7976e0de17bf153c7 ] |
| |
| A card's close_dev work is scheduled on a driver-wide workqueue. If the |
| card is removed and freed while the work is still active, this causes a |
| use-after-free. |
| So make sure that the work is completed before freeing the card. |
| |
| Fixes: 0f54761d167f ("qeth: Support VEPA mode") |
| Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/s390/net/qeth_core.h | 1 + |
| drivers/s390/net/qeth_l2_main.c | 2 ++ |
| drivers/s390/net/qeth_l3_main.c | 1 + |
| 3 files changed, 4 insertions(+) |
| |
| diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h |
| index 970654fcc48d..2d1f6a583641 100644 |
| --- a/drivers/s390/net/qeth_core.h |
| +++ b/drivers/s390/net/qeth_core.h |
| @@ -22,6 +22,7 @@ |
| #include <linux/hashtable.h> |
| #include <linux/ip.h> |
| #include <linux/refcount.h> |
| +#include <linux/workqueue.h> |
| |
| #include <net/ipv6.h> |
| #include <net/if_inet6.h> |
| diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c |
| index 76b2fba5fba2..b7513c5848cf 100644 |
| --- a/drivers/s390/net/qeth_l2_main.c |
| +++ b/drivers/s390/net/qeth_l2_main.c |
| @@ -854,6 +854,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) |
| |
| if (cgdev->state == CCWGROUP_ONLINE) |
| qeth_l2_set_offline(cgdev); |
| + |
| + cancel_work_sync(&card->close_dev_work); |
| if (qeth_netdev_is_registered(card->dev)) |
| unregister_netdev(card->dev); |
| } |
| diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c |
| index b7f6a8384543..7f71ca0d08e7 100644 |
| --- a/drivers/s390/net/qeth_l3_main.c |
| +++ b/drivers/s390/net/qeth_l3_main.c |
| @@ -2611,6 +2611,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) |
| if (cgdev->state == CCWGROUP_ONLINE) |
| qeth_l3_set_offline(cgdev); |
| |
| + cancel_work_sync(&card->close_dev_work); |
| if (qeth_netdev_is_registered(card->dev)) |
| unregister_netdev(card->dev); |
| qeth_l3_clear_ip_htable(card, 0); |
| -- |
| 2.19.1 |
| |