From patchwork Mon Aug 17 15:12:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg KH X-Patchwork-Id: 266506 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86021C433E3 for ; Mon, 17 Aug 2020 15:27:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 57B6423372 for ; Mon, 17 Aug 2020 15:27:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1597678048; bh=WeFnEt1YJ74wkHQIzwIl0gpP6EkVjaWIE+vOpWbcNe8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=1PStijmmnFb/dA2i1LsjcnJhNHsU8NzSdwGpJfAQk7kK35Y/ui8E5qKNzHWCOZuc2 fqjOE3tEWo3eEIuBQH8sggnycd2GlrzdVMdM6lw7Jggs/Xy9DlP1m31n7a88E82M+x +s7Y/KqqqGWc1JvKD45OmEQVsk4thAzr06yXMglo= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729635AbgHQP11 (ORCPT ); Mon, 17 Aug 2020 11:27:27 -0400 Received: from mail.kernel.org ([198.145.29.99]:38968 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729496AbgHQP1Z (ORCPT ); Mon, 17 Aug 2020 11:27:25 -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 2CEB223B41; Mon, 17 Aug 2020 15:27:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1597678044; bh=WeFnEt1YJ74wkHQIzwIl0gpP6EkVjaWIE+vOpWbcNe8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BHrnB8y7BD8OKH1pQLTtCv1lk9DIkEejQQX7DLCl2fOnK59oC3/VmlxVzXsEpHjOC C5AbfrZztKcrYOR0bT76mMcBk83gvFtyARIG7LUwu/grwkyohV4yjgAPKSRidja09n 86tEduRvoeOwSx4rh+1yNasXbZbwd2F5Z4XbhYp4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, syzbot+4088ed905e4ae2b0e13b@syzkaller.appspotmail.com, Hillf Danton , Leon Romanovsky , Jason Gunthorpe , Sasha Levin Subject: [PATCH 5.8 200/464] RDMA/core: Fix bogus WARN_ON during ib_unregister_device_queued() Date: Mon, 17 Aug 2020 17:12:33 +0200 Message-Id: <20200817143843.402980804@linuxfoundation.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200817143833.737102804@linuxfoundation.org> References: <20200817143833.737102804@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Jason Gunthorpe [ Upstream commit 0cb42c0265837fafa2b4f302c8a7fed2631d7869 ] ib_unregister_device_queued() can only be used by drivers using the new dealloc_device callback flow, and it has a safety WARN_ON to ensure drivers are using it properly. However, if unregister and register are raced there is a special destruction path that maintains the uniform error handling semantic of 'caller does ib_dealloc_device() on failure'. This requires disabling the dealloc_device callback which triggers the WARN_ON. Instead of using NULL to disable the callback use a special function pointer so the WARN_ON does not trigger. Fixes: d0899892edd0 ("RDMA/device: Provide APIs from the core code to help unregistration") Link: https://lore.kernel.org/r/0-v1-a36d512e0a99+762-syz_dealloc_driver_jgg@nvidia.com Reported-by: syzbot+4088ed905e4ae2b0e13b@syzkaller.appspotmail.com Suggested-by: Hillf Danton Reviewed-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/infiniband/core/device.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 905a2beaf8850..eadba29432dd7 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -1339,6 +1339,10 @@ static int enable_device_and_get(struct ib_device *device) return ret; } +static void prevent_dealloc_device(struct ib_device *ib_dev) +{ +} + /** * ib_register_device - Register an IB device with IB core * @device: Device to register @@ -1409,11 +1413,11 @@ int ib_register_device(struct ib_device *device, const char *name) * possibility for a parallel unregistration along with this * error flow. Since we have a refcount here we know any * parallel flow is stopped in disable_device and will see the - * NULL pointers, causing the responsibility to + * special dealloc_driver pointer, causing the responsibility to * ib_dealloc_device() to revert back to this thread. */ dealloc_fn = device->ops.dealloc_driver; - device->ops.dealloc_driver = NULL; + device->ops.dealloc_driver = prevent_dealloc_device; ib_device_put(device); __ib_unregister_device(device); device->ops.dealloc_driver = dealloc_fn; @@ -1462,7 +1466,8 @@ static void __ib_unregister_device(struct ib_device *ib_dev) * Drivers using the new flow may not call ib_dealloc_device except * in error unwind prior to registration success. */ - if (ib_dev->ops.dealloc_driver) { + if (ib_dev->ops.dealloc_driver && + ib_dev->ops.dealloc_driver != prevent_dealloc_device) { WARN_ON(kref_read(&ib_dev->dev.kobj.kref) <= 1); ib_dealloc_device(ib_dev); }