Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964820AbbLOB3z (ORCPT ); Mon, 14 Dec 2015 20:29:55 -0500 Received: from p3plsmtps2ded04.prod.phx3.secureserver.net ([208.109.80.198]:35150 "EHLO p3plsmtps2ded04.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932859AbbLOB20 (ORCPT ); Mon, 14 Dec 2015 20:28:26 -0500 x-originating-ip: 72.167.245.219 From: "K. Y. Srinivasan" To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com, vkuznets@redhat.com, jasowang@redhat.com Cc: "K. Y. Srinivasan" Subject: [PATCH 4/9] Drivers: hv: utils: fix crash when device is removed from host side Date: Mon, 14 Dec 2015 19:01:56 -0800 Message-Id: <1450148521-28447-4-git-send-email-kys@microsoft.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1450148521-28447-1-git-send-email-kys@microsoft.com> References: <1450148455-28399-1-git-send-email-kys@microsoft.com> <1450148521-28447-1-git-send-email-kys@microsoft.com> X-CMAE-Envelope: MS4wfNZyUouou8GX8q+0w2xRIoo2AFqsoc3Wjhz7MeSchJR+ImpIxDZs1SJ3eBs9yDJTYx6UwzSLnASO22GIBo1kWhshNAwwb/QgP8VhPR4a/MFkT71Y21W3 VOO2Mgcmb6Z5rw4V6KwPtUSWRxy6/ZPcucVU1cGm+Y++W8pv39FM/MMks9l0g1P9jybPBtCxwanVdnX1/7dUXvUXm176acYchNoUfb2iLzpFJnD4Mfc/FuXs 3zkHO+2wMqe0iNpa2aX3qjO6TtkcjfrmbcQSi8x4lMG1c6OpuhWJbaKWTsxSS99HOdJVbkZb2zQPVTxWwSD4vH2p9xyanzb/GxgWZRx1F9cNQ1yUjnufiIC1 fbDd1ZjaTgFN3qEf/HTaSye0jRIZm80LRQZfB/PFsePW42w3Tfy4EMcf6HFoCN8SoBdUwQjl Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3345 Lines: 106 From: Vitaly Kuznetsov The crash is observed when a service is being disabled host side while userspace daemon is connected to the device: [ 90.244859] general protection fault: 0000 [#1] SMP ... [ 90.800082] Call Trace: [ 90.800082] [] __fput+0xc8/0x1f0 [ 90.800082] [] ____fput+0xe/0x10 ... [ 90.800082] [] do_signal+0x28/0x580 [ 90.800082] [] ? finish_task_switch+0xa6/0x180 [ 90.800082] [] ? __schedule+0x28f/0x870 [ 90.800082] [] ? hvt_op_read+0x12a/0x140 [hv_utils] ... The problem is that hvutil_transport_destroy() which does misc_deregister() freeing the appropriate device is reachable by two paths: module unload and from util_remove(). While module unload path is protected by .owner in struct file_operations util_remove() path is not. Freeing the device while someone holds an open fd for it is a show stopper. In general, it is not possible to revoke an fd from all users so the only way to solve the issue is to defer freeing the hvutil_transport structure. Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan --- drivers/hv/hv_utils_transport.c | 26 +++++++++++++++++++++++--- 1 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c index 31c2f86..ee20b50 100644 --- a/drivers/hv/hv_utils_transport.c +++ b/drivers/hv/hv_utils_transport.c @@ -155,13 +155,22 @@ static int hvt_op_open(struct inode *inode, struct file *file) return ret; } +static void hvt_transport_free(struct hvutil_transport *hvt) +{ + misc_deregister(&hvt->mdev); + kfree(hvt->outmsg); + kfree(hvt); +} + static int hvt_op_release(struct inode *inode, struct file *file) { struct hvutil_transport *hvt; + int mode_old; hvt = container_of(file->f_op, struct hvutil_transport, fops); mutex_lock(&hvt->lock); + mode_old = hvt->mode; if (hvt->mode != HVUTIL_TRANSPORT_DESTROY) hvt->mode = HVUTIL_TRANSPORT_INIT; /* @@ -171,6 +180,9 @@ static int hvt_op_release(struct inode *inode, struct file *file) hvt_reset(hvt); mutex_unlock(&hvt->lock); + if (mode_old == HVUTIL_TRANSPORT_DESTROY) + hvt_transport_free(hvt); + return 0; } @@ -304,17 +316,25 @@ err_free_hvt: void hvutil_transport_destroy(struct hvutil_transport *hvt) { + int mode_old; + mutex_lock(&hvt->lock); + mode_old = hvt->mode; hvt->mode = HVUTIL_TRANSPORT_DESTROY; wake_up_interruptible(&hvt->outmsg_q); mutex_unlock(&hvt->lock); + /* + * In case we were in 'chardev' mode we still have an open fd so we + * have to defer freeing the device. Netlink interface can be freed + * now. + */ spin_lock(&hvt_list_lock); list_del(&hvt->list); spin_unlock(&hvt_list_lock); if (hvt->cn_id.idx > 0 && hvt->cn_id.val > 0) cn_del_callback(&hvt->cn_id); - misc_deregister(&hvt->mdev); - kfree(hvt->outmsg); - kfree(hvt); + + if (mode_old != HVUTIL_TRANSPORT_CHARDEV) + hvt_transport_free(hvt); } -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/