[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220412062950.560954610@linuxfoundation.org>
Date: Tue, 12 Apr 2022 08:31:36 +0200
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org,
Douglas Miller <doug.miller@...nelisnetworks.com>,
Dennis Dalessandro <dennis.dalessandro@...nelisnetworks.com>,
Jason Gunthorpe <jgg@...dia.com>
Subject: [PATCH 5.16 239/285] RDMA/hfi1: Fix use-after-free bug for mm struct
From: Douglas Miller <doug.miller@...nelisnetworks.com>
commit 2bbac98d0930e8161b1957dc0ec99de39ade1b3c upstream.
Under certain conditions, such as MPI_Abort, the hfi1 cleanup code may
represent the last reference held on the task mm.
hfi1_mmu_rb_unregister() then drops the last reference and the mm is freed
before the final use in hfi1_release_user_pages(). A new task may
allocate the mm structure while it is still being used, resulting in
problems. One manifestation is corruption of the mmap_sem counter leading
to a hang in down_write(). Another is corruption of an mm struct that is
in use by another task.
Fixes: 3d2a9d642512 ("IB/hfi1: Ensure correct mm is used at all times")
Link: https://lore.kernel.org/r/20220408133523.122165.72975.stgit@awfm-01.cornelisnetworks.com
Cc: <stable@...r.kernel.org>
Signed-off-by: Douglas Miller <doug.miller@...nelisnetworks.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@...nelisnetworks.com>
Signed-off-by: Jason Gunthorpe <jgg@...dia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
drivers/infiniband/hw/hfi1/mmu_rb.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/infiniband/hw/hfi1/mmu_rb.c
+++ b/drivers/infiniband/hw/hfi1/mmu_rb.c
@@ -80,6 +80,9 @@ void hfi1_mmu_rb_unregister(struct mmu_r
unsigned long flags;
struct list_head del_list;
+ /* Prevent freeing of mm until we are completely finished. */
+ mmgrab(handler->mn.mm);
+
/* Unregister first so we don't get any more notifications. */
mmu_notifier_unregister(&handler->mn, handler->mn.mm);
@@ -102,6 +105,9 @@ void hfi1_mmu_rb_unregister(struct mmu_r
do_remove(handler, &del_list);
+ /* Now the mm may be freed. */
+ mmdrop(handler->mn.mm);
+
kfree(handler);
}
Powered by blists - more mailing lists