Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp1139211pxa; Thu, 20 Aug 2020 03:43:13 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyGGun02ymahu+eoCTXHgwOVHyPVnHFDCjOKJzRuwyWKWSeTzcAc8+njBXvKXbr7jquc2tu X-Received: by 2002:a17:906:7e05:: with SMTP id e5mr2728395ejr.252.1597920192906; Thu, 20 Aug 2020 03:43:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1597920192; cv=none; d=google.com; s=arc-20160816; b=luSmOcOp8ve1jLsBhrKybGTlAC7dl0MQlgMKfkLeL7+tkj84Y8z7KZJAeW5fDxct1U WBcMzungMZA+Nno7m82JGV4mu3jhD22P8qkE1HvUP8Bofgl9Ac6TjgPf3DiKa4+6komI XJyGpiNne4gE9M+5Vt6cU8RIdtAWQHmqxn74wHUi0oIc/5vmzVU61jdA5E/6vumj9eCQ MdKTKwhFZ9CixR7YsD0Dyp7HuSgF/ra29DN6OpCNbYV8a1S9SpDrV1wXw6hUrwMF+BzW aRUbZVHx4JdPNsfLrRgumEWpb0buQtiXbLFKc1gMgjOUiD0VxrzrpyElO3v5Wp7+CKkk PlMg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=L6IXOjzMvjSRZH89HQtLcqmWcj04mz1koUu9+6faAfA=; b=xB3f5N33PGp2Gd08phAk/457zh6MrCz+VCuIAWli+k1UMvFta1Hh2eXbypYWzE4E22 cgeFj7yIYsM6oZLfOKJBd9C0iutZLvTTp7jdIea8FbEe5cQfjnhVHCHY4Zu94jUYnmJI 89JkNFzRIyjxRn/lbUiLv7eZkl/aFSUPkfIfGXJ1niYhjwlR/fYuGHp1y33phDvQhyfl /NmroCrqppz4+uN+J15AqWAqgCha3bZJIsSv2QXXOOHSAAMN9c3XJnKlKSPUjBD2aD63 25LoweWmZapnpWH+5hf7GB/+bgVf6APs63faC9mL1wjKUtw4M25TG1/s1PZYhV66wh68 S35Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=HM0k7QQu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id 91si1423475edy.18.2020.08.20.03.42.49; Thu, 20 Aug 2020 03:43:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=HM0k7QQu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730170AbgHTKjw (ORCPT + 99 others); Thu, 20 Aug 2020 06:39:52 -0400 Received: from mail.kernel.org ([198.145.29.99]:39644 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729721AbgHTKR4 (ORCPT ); Thu, 20 Aug 2020 06:17:56 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B62642067C; Thu, 20 Aug 2020 10:17:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1597918675; bh=FssRAtjvO9q3R2ql3sbZw5EJB0pb70GEDIhbn2tG0Gc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HM0k7QQubnvPSpgtU18u961Y1LaDEYpEHD32vrjwPVYswaGggRjzooQP5AP2EFbla Uk3TRMfhzdVLKyUoUNsFPGoftsU7JqA/rPx4/rWMkhVrrR7YInUhdRqT8gEPpuh3Kv WxkPjuVV4VMVAvRwf6OgASZKtWf9XtDxmVK2nAgA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Andrea Righi , "David S. Miller" , Sasha Levin Subject: [PATCH 4.4 025/149] xen-netfront: fix potential deadlock in xennet_remove() Date: Thu, 20 Aug 2020 11:21:42 +0200 Message-Id: <20200820092126.939313881@linuxfoundation.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200820092125.688850368@linuxfoundation.org> References: <20200820092125.688850368@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andrea Righi [ Upstream commit c2c633106453611be07821f53dff9e93a9d1c3f0 ] There's a potential race in xennet_remove(); this is what the driver is doing upon unregistering a network device: 1. state = read bus state 2. if state is not "Closed": 3. request to set state to "Closing" 4. wait for state to be set to "Closing" 5. request to set state to "Closed" 6. wait for state to be set to "Closed" If the state changes to "Closed" immediately after step 1 we are stuck forever in step 4, because the state will never go back from "Closed" to "Closing". Make sure to check also for state == "Closed" in step 4 to prevent the deadlock. Also add a 5 sec timeout any time we wait for the bus state to change, to avoid getting stuck forever in wait_event(). Signed-off-by: Andrea Righi Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/xen-netfront.c | 64 +++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 22 deletions(-) --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -62,6 +62,8 @@ module_param_named(max_queues, xennet_ma MODULE_PARM_DESC(max_queues, "Maximum number of queues per virtual interface"); +#define XENNET_TIMEOUT (5 * HZ) + static const struct ethtool_ops xennet_ethtool_ops; struct netfront_cb { @@ -1349,12 +1351,15 @@ static struct net_device *xennet_create_ netif_carrier_off(netdev); - xenbus_switch_state(dev, XenbusStateInitialising); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) != - XenbusStateClosed && - xenbus_read_driver_state(dev->otherend) != - XenbusStateUnknown); + do { + xenbus_switch_state(dev, XenbusStateInitialising); + err = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) != + XenbusStateClosed && + xenbus_read_driver_state(dev->otherend) != + XenbusStateUnknown, XENNET_TIMEOUT); + } while (!err); + return netdev; exit: @@ -2166,28 +2171,43 @@ static const struct attribute_group xenn }; #endif /* CONFIG_SYSFS */ -static int xennet_remove(struct xenbus_device *dev) +static void xennet_bus_close(struct xenbus_device *dev) { - struct netfront_info *info = dev_get_drvdata(&dev->dev); - - dev_dbg(&dev->dev, "%s\n", dev->nodename); + int ret; - if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) { + if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed) + return; + do { xenbus_switch_state(dev, XenbusStateClosing); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) == - XenbusStateClosing || - xenbus_read_driver_state(dev->otherend) == - XenbusStateUnknown); + ret = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosing || + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosed || + xenbus_read_driver_state(dev->otherend) == + XenbusStateUnknown, + XENNET_TIMEOUT); + } while (!ret); + if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed) + return; + + do { xenbus_switch_state(dev, XenbusStateClosed); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) == - XenbusStateClosed || - xenbus_read_driver_state(dev->otherend) == - XenbusStateUnknown); - } + ret = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosed || + xenbus_read_driver_state(dev->otherend) == + XenbusStateUnknown, + XENNET_TIMEOUT); + } while (!ret); +} + +static int xennet_remove(struct xenbus_device *dev) +{ + struct netfront_info *info = dev_get_drvdata(&dev->dev); + xennet_bus_close(dev); xennet_disconnect_backend(info); if (info->netdev->reg_state == NETREG_REGISTERED)