From patchwork Sat Sep 4 12:25:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Tao X-Patchwork-Id: 12475561 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=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,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 D9528C433FE for ; Sat, 4 Sep 2021 12:12:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AEE69610A1 for ; Sat, 4 Sep 2021 12:12:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236132AbhIDMNj (ORCPT ); Sat, 4 Sep 2021 08:13:39 -0400 Received: from szxga03-in.huawei.com ([45.249.212.189]:15289 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236368AbhIDMNi (ORCPT ); Sat, 4 Sep 2021 08:13:38 -0400 Received: from dggemv703-chm.china.huawei.com (unknown [172.30.72.54]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4H1tnj44jhz8spF; Sat, 4 Sep 2021 20:12:09 +0800 (CST) Received: from dggpeml500025.china.huawei.com (7.185.36.35) by dggemv703-chm.china.huawei.com (10.3.19.46) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Sat, 4 Sep 2021 20:12:35 +0800 Received: from huawei.com (10.175.124.27) by dggpeml500025.china.huawei.com (7.185.36.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Sat, 4 Sep 2021 20:12:34 +0800 From: Hou Tao To: Josef Bacik , Jens Axboe , CC: , , Subject: [PATCH v2 1/3] nbd: use pr_err to output error message Date: Sat, 4 Sep 2021 20:25:17 +0800 Message-ID: <20210904122519.1963983-2-houtao1@huawei.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210904122519.1963983-1-houtao1@huawei.com> References: <20210904122519.1963983-1-houtao1@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.124.27] X-ClientProxiedBy: dggems701-chm.china.huawei.com (10.3.19.178) To dggpeml500025.china.huawei.com (7.185.36.35) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Instead of using the long printk(KERN_ERR "nbd: ...") to output error message, defining pr_fmt and using the short pr_err("") to do that. The replacemen is done by using the following command: sed -i 's/printk(KERN_ERR "nbd: /pr_err("/g' \ drivers/block/nbd.c Signed-off-by: Hou Tao Reviewed-by: Christoph Hellwig --- drivers/block/nbd.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 5170a630778d..ef94f62895d6 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -44,6 +44,9 @@ #include #include +#undef pr_fmt +#define pr_fmt(fmt) "nbd: " fmt + #define CREATE_TRACE_POINTS #include @@ -1854,11 +1857,11 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NBD_ATTR_INDEX]) index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]); if (!info->attrs[NBD_ATTR_SOCKETS]) { - printk(KERN_ERR "nbd: must specify at least one socket\n"); + pr_err("must specify at least one socket\n"); return -EINVAL; } if (!info->attrs[NBD_ATTR_SIZE_BYTES]) { - printk(KERN_ERR "nbd: must specify a size in bytes for the device\n"); + pr_err("must specify a size in bytes for the device\n"); return -EINVAL; } again: @@ -1894,7 +1897,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) nbd_put(nbd); if (index == -1) goto again; - printk(KERN_ERR "nbd: nbd%d already in use\n", index); + pr_err("nbd%d already in use\n", index); return -EBUSY; } if (WARN_ON(nbd->config)) { @@ -1906,7 +1909,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) if (!nbd->config) { mutex_unlock(&nbd->config_lock); nbd_put(nbd); - printk(KERN_ERR "nbd: couldn't allocate config\n"); + pr_err("nbd: couldn't allocate config\n"); return -ENOMEM; } refcount_set(&nbd->config_refs, 1); @@ -1961,7 +1964,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) struct nlattr *socks[NBD_SOCK_MAX+1]; if (nla_type(attr) != NBD_SOCK_ITEM) { - printk(KERN_ERR "nbd: socks must be embedded in a SOCK_ITEM attr\n"); + pr_err("socks must be embedded in a SOCK_ITEM attr\n"); ret = -EINVAL; goto out; } @@ -1970,7 +1973,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) nbd_sock_policy, info->extack); if (ret != 0) { - printk(KERN_ERR "nbd: error processing sock list\n"); + pr_err("error processing sock list\n"); ret = -EINVAL; goto out; } @@ -2044,7 +2047,7 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info) return -EPERM; if (!info->attrs[NBD_ATTR_INDEX]) { - printk(KERN_ERR "nbd: must specify an index to disconnect\n"); + pr_err("must specify an index to disconnect\n"); return -EINVAL; } index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]); @@ -2052,13 +2055,13 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info) nbd = idr_find(&nbd_index_idr, index); if (!nbd) { mutex_unlock(&nbd_index_mutex); - printk(KERN_ERR "nbd: couldn't find device at index %d\n", + pr_err("couldn't find device at index %d\n", index); return -EINVAL; } if (!refcount_inc_not_zero(&nbd->refs)) { mutex_unlock(&nbd_index_mutex); - printk(KERN_ERR "nbd: device at index %d is going down\n", + pr_err("device at index %d is going down\n", index); return -EINVAL; } @@ -2084,7 +2087,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) return -EPERM; if (!info->attrs[NBD_ATTR_INDEX]) { - printk(KERN_ERR "nbd: must specify a device to reconfigure\n"); + pr_err("must specify a device to reconfigure\n"); return -EINVAL; } index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]); @@ -2092,7 +2095,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) nbd = idr_find(&nbd_index_idr, index); if (!nbd) { mutex_unlock(&nbd_index_mutex); - printk(KERN_ERR "nbd: couldn't find a device at index %d\n", + pr_err("couldn't find a device at index %d\n", index); return -EINVAL; } @@ -2114,7 +2117,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) } if (!refcount_inc_not_zero(&nbd->refs)) { mutex_unlock(&nbd_index_mutex); - printk(KERN_ERR "nbd: device at index %d is going down\n", + pr_err("device at index %d is going down\n", index); return -EINVAL; } @@ -2179,7 +2182,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) struct nlattr *socks[NBD_SOCK_MAX+1]; if (nla_type(attr) != NBD_SOCK_ITEM) { - printk(KERN_ERR "nbd: socks must be embedded in a SOCK_ITEM attr\n"); + pr_err("socks must be embedded in a SOCK_ITEM attr\n"); ret = -EINVAL; goto out; } @@ -2188,7 +2191,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) nbd_sock_policy, info->extack); if (ret != 0) { - printk(KERN_ERR "nbd: error processing sock list\n"); + pr_err("error processing sock list\n"); ret = -EINVAL; goto out; } @@ -2405,7 +2408,7 @@ static int __init nbd_init(void) BUILD_BUG_ON(sizeof(struct nbd_request) != 28); if (max_part < 0) { - printk(KERN_ERR "nbd: max_part must be >= 0\n"); + pr_err("max_part must be >= 0\n"); return -EINVAL; } @@ -2478,7 +2481,7 @@ static void __exit nbd_cleanup(void) nbd = list_first_entry(&del_list, struct nbd_device, list); list_del_init(&nbd->list); if (refcount_read(&nbd->refs) != 1) - printk(KERN_ERR "nbd: possibly leaking a device\n"); + pr_err("possibly leaking a device\n"); nbd_put(nbd); } From patchwork Sat Sep 4 12:25:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Tao X-Patchwork-Id: 12475565 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=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,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 EF45CC433EF for ; Sat, 4 Sep 2021 12:12:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B8C26610A2 for ; Sat, 4 Sep 2021 12:12:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234198AbhIDMNi (ORCPT ); Sat, 4 Sep 2021 08:13:38 -0400 Received: from szxga01-in.huawei.com ([45.249.212.187]:19006 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236132AbhIDMNi (ORCPT ); Sat, 4 Sep 2021 08:13:38 -0400 Received: from dggemv711-chm.china.huawei.com (unknown [172.30.72.57]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4H1tjd67z0zbkm5; Sat, 4 Sep 2021 20:08:37 +0800 (CST) Received: from dggpeml500025.china.huawei.com (7.185.36.35) by dggemv711-chm.china.huawei.com (10.1.198.66) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Sat, 4 Sep 2021 20:12:35 +0800 Received: from huawei.com (10.175.124.27) by dggpeml500025.china.huawei.com (7.185.36.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Sat, 4 Sep 2021 20:12:35 +0800 From: Hou Tao To: Josef Bacik , Jens Axboe , CC: , , Subject: [PATCH v2 2/3] nbd: call genl_unregister_family() first in nbd_cleanup() Date: Sat, 4 Sep 2021 20:25:18 +0800 Message-ID: <20210904122519.1963983-3-houtao1@huawei.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210904122519.1963983-1-houtao1@huawei.com> References: <20210904122519.1963983-1-houtao1@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.124.27] X-ClientProxiedBy: dggems701-chm.china.huawei.com (10.3.19.178) To dggpeml500025.china.huawei.com (7.185.36.35) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Otherwise there may be race between module removal and the handling of netlink command, which can lead to the oops as shown below: BUG: kernel NULL pointer dereference, address: 0000000000000098 Oops: 0002 [#1] SMP PTI CPU: 1 PID: 31299 Comm: nbd-client Tainted: G E 5.14.0-rc4 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) RIP: 0010:down_write+0x1a/0x50 Call Trace: start_creating+0x89/0x130 debugfs_create_dir+0x1b/0x130 nbd_start_device+0x13d/0x390 [nbd] nbd_genl_connect+0x42f/0x748 [nbd] genl_family_rcv_msg_doit.isra.0+0xec/0x150 genl_rcv_msg+0xe5/0x1e0 netlink_rcv_skb+0x55/0x100 genl_rcv+0x29/0x40 netlink_unicast+0x1a8/0x250 netlink_sendmsg+0x21b/0x430 ____sys_sendmsg+0x2a4/0x2d0 ___sys_sendmsg+0x81/0xc0 __sys_sendmsg+0x62/0xb0 __x64_sys_sendmsg+0x1f/0x30 do_syscall_64+0x3b/0xc0 entry_SYSCALL_64_after_hwframe+0x44/0xae Modules linked in: nbd(E-) Signed-off-by: Hou Tao Reviewed-by: Christoph Hellwig --- v2: * update comment and commit message (suggested by eblake@redhat.com) --- drivers/block/nbd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index ef94f62895d6..cedd3648e1a7 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -2471,6 +2471,12 @@ static void __exit nbd_cleanup(void) struct nbd_device *nbd; LIST_HEAD(del_list); + /* + * Unregister netlink interface prior to waiting + * for the completion of netlink commands. + */ + genl_unregister_family(&nbd_genl_family); + nbd_dbg_close(); mutex_lock(&nbd_index_mutex); @@ -2489,7 +2495,6 @@ static void __exit nbd_cleanup(void) destroy_workqueue(nbd_del_wq); idr_destroy(&nbd_index_idr); - genl_unregister_family(&nbd_genl_family); unregister_blkdev(NBD_MAJOR, "nbd"); } From patchwork Sat Sep 4 12:25:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Tao X-Patchwork-Id: 12475563 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=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,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 B4BF1C4332F for ; Sat, 4 Sep 2021 12:12:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9B084610A1 for ; Sat, 4 Sep 2021 12:12:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236368AbhIDMNj (ORCPT ); Sat, 4 Sep 2021 08:13:39 -0400 Received: from szxga08-in.huawei.com ([45.249.212.255]:15239 "EHLO szxga08-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236376AbhIDMNj (ORCPT ); Sat, 4 Sep 2021 08:13:39 -0400 Received: from dggemv704-chm.china.huawei.com (unknown [172.30.72.54]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4H1tnK4hCwz1DDrN; Sat, 4 Sep 2021 20:11:49 +0800 (CST) Received: from dggpeml500025.china.huawei.com (7.185.36.35) by dggemv704-chm.china.huawei.com (10.3.19.47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Sat, 4 Sep 2021 20:12:35 +0800 Received: from huawei.com (10.175.124.27) by dggpeml500025.china.huawei.com (7.185.36.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Sat, 4 Sep 2021 20:12:35 +0800 From: Hou Tao To: Josef Bacik , Jens Axboe , CC: , , Subject: [PATCH v2 3/3] nbd: fix race between nbd_alloc_config() and module removal Date: Sat, 4 Sep 2021 20:25:19 +0800 Message-ID: <20210904122519.1963983-4-houtao1@huawei.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210904122519.1963983-1-houtao1@huawei.com> References: <20210904122519.1963983-1-houtao1@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.124.27] X-ClientProxiedBy: dggems701-chm.china.huawei.com (10.3.19.178) To dggpeml500025.china.huawei.com (7.185.36.35) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org When nbd module is being removing, nbd_alloc_config() may be called concurrently by nbd_genl_connect(), although try_module_get() will return false, but nbd_alloc_config() doesn't handle it. The race may lead to the leak of nbd_config and its related resources (e.g, recv_workq) and oops in nbd_read_stat() due to the unload of nbd module as shown below: BUG: kernel NULL pointer dereference, address: 0000000000000040 Oops: 0000 [#1] SMP PTI CPU: 5 PID: 13840 Comm: kworker/u17:33 Not tainted 5.14.0+ #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) Workqueue: knbd16-recv recv_work [nbd] RIP: 0010:nbd_read_stat.cold+0x130/0x1a4 [nbd] Call Trace: recv_work+0x3b/0xb0 [nbd] process_one_work+0x1ed/0x390 worker_thread+0x4a/0x3d0 kthread+0x12a/0x150 ret_from_fork+0x22/0x30 Fixing it by checking the return value of try_module_get() in nbd_alloc_config(). As nbd_alloc_config() may return ERR_PTR(-ENODEV), assign nbd->config only when nbd_alloc_config() succeeds to ensure the value of nbd->config is binary (valid or NULL). Also adding a debug message to check the reference counter of nbd_config during module removal. Signed-off-by: Hou Tao --- drivers/block/nbd.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index cedd3648e1a7..fa6c069b79dc 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1473,15 +1473,20 @@ static struct nbd_config *nbd_alloc_config(void) { struct nbd_config *config; + if (!try_module_get(THIS_MODULE)) + return ERR_PTR(-ENODEV); + config = kzalloc(sizeof(struct nbd_config), GFP_NOFS); - if (!config) - return NULL; + if (!config) { + module_put(THIS_MODULE); + return ERR_PTR(-ENOMEM); + } + atomic_set(&config->recv_threads, 0); init_waitqueue_head(&config->recv_wq); init_waitqueue_head(&config->conn_wait); config->blksize = NBD_DEF_BLKSIZE; atomic_set(&config->live_connections, 0); - try_module_get(THIS_MODULE); return config; } @@ -1508,12 +1513,13 @@ static int nbd_open(struct block_device *bdev, fmode_t mode) mutex_unlock(&nbd->config_lock); goto out; } - config = nbd->config = nbd_alloc_config(); - if (!config) { - ret = -ENOMEM; + config = nbd_alloc_config(); + if (IS_ERR(config)) { + ret = PTR_ERR(config); mutex_unlock(&nbd->config_lock); goto out; } + nbd->config = config; refcount_set(&nbd->config_refs, 1); refcount_inc(&nbd->refs); mutex_unlock(&nbd->config_lock); @@ -1905,13 +1911,14 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) nbd_put(nbd); return -EINVAL; } - config = nbd->config = nbd_alloc_config(); - if (!nbd->config) { + config = nbd_alloc_config(); + if (IS_ERR(config)) { mutex_unlock(&nbd->config_lock); nbd_put(nbd); pr_err("nbd: couldn't allocate config\n"); - return -ENOMEM; + return PTR_ERR(config); } + nbd->config = config; refcount_set(&nbd->config_refs, 1); set_bit(NBD_RT_BOUND, &config->runtime_flags); @@ -2486,6 +2493,9 @@ static void __exit nbd_cleanup(void) while (!list_empty(&del_list)) { nbd = list_first_entry(&del_list, struct nbd_device, list); list_del_init(&nbd->list); + if (refcount_read(&nbd->config_refs)) + pr_err("possibly leaking nbd_config (ref %d)\n", + refcount_read(&nbd->config_refs)); if (refcount_read(&nbd->refs) != 1) pr_err("possibly leaking a device\n"); nbd_put(nbd);