|
|
32bb78 |
From 909e24465c59ba4df4124d7caa0730f609c33369 Mon Sep 17 00:00:00 2001
|
|
|
32bb78 |
From: Joe Lawrence <joe.lawrence@redhat.com>
|
|
|
32bb78 |
Date: Tue, 26 Oct 2021 18:00:19 -0400
|
|
|
32bb78 |
Subject: [KPATCH CVE-2020-36385] RDMA/ucma: kpatch fixes for CVE-2020-36385
|
|
|
32bb78 |
|
|
|
32bb78 |
Changes since last build:
|
|
|
32bb78 |
arches: x86_64 ppc64le
|
|
|
32bb78 |
ucma.o: changed function: ucma_migrate_id
|
|
|
32bb78 |
---------------------------
|
|
|
32bb78 |
|
|
|
32bb78 |
Kernels:
|
|
|
32bb78 |
4.18.0-305.el8
|
|
|
32bb78 |
4.18.0-305.3.1.el8_4
|
|
|
32bb78 |
4.18.0-305.7.1.el8_4
|
|
|
32bb78 |
4.18.0-305.10.2.el8_4
|
|
|
32bb78 |
4.18.0-305.12.1.el8_4
|
|
|
32bb78 |
4.18.0-305.17.1.el8_4
|
|
|
32bb78 |
4.18.0-305.19.1.el8_4
|
|
|
32bb78 |
|
|
|
32bb78 |
Modifications:
|
|
|
32bb78 |
Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-8/-/merge_requests/1
|
|
|
32bb78 |
Approved-by: Artem Savkov (@artem.savkov)
|
|
|
32bb78 |
- Avoid the complications of reworking all the locks (and preceding
|
|
|
32bb78 |
commits) and apply a minimal patch to avoid the CVE condition.
|
|
|
32bb78 |
- Always inline ucma_unlock_files() to avoid new function on x64_64
|
|
|
32bb78 |
|
|
|
32bb78 |
Z-MR: https://gitlab.com/redhat/rhel/src/kernel/rhel-8/-/merge_requests/961
|
|
|
32bb78 |
|
|
|
32bb78 |
KT0 test PASS: https://beaker.engineering.redhat.com/jobs/5944203
|
|
|
32bb78 |
for kpatch-patch-4_18_0-305-1-6.el8 scratch build:
|
|
|
32bb78 |
https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=40633078
|
|
|
32bb78 |
|
|
|
32bb78 |
commit 15152e7e191054883e2859892e77b442c531d1e1
|
|
|
32bb78 |
Author: Kamal Heib <kheib@redhat.com>
|
|
|
32bb78 |
Date: Sun Mar 7 11:30:04 2021 +0200
|
|
|
32bb78 |
|
|
|
32bb78 |
RDMA/ucma: Rework ucma_migrate_id() to avoid races with destroy
|
|
|
32bb78 |
|
|
|
32bb78 |
Bugzilla: https://bugzilla.redhat.com/1982040
|
|
|
32bb78 |
CVE: CVE-2020-36385
|
|
|
32bb78 |
Y-Commit: 20c1e291ce96ca474f5e94272d2e6511c6a38d58
|
|
|
32bb78 |
|
|
|
32bb78 |
O-Bugzilla: http://bugzilla.redhat.com/1931846
|
|
|
32bb78 |
O-CVE: CVE-2020-36385
|
|
|
32bb78 |
|
|
|
32bb78 |
commit f5449e74802c1112dea984aec8af7a33c4516af1
|
|
|
32bb78 |
Author: Jason Gunthorpe <jgg@nvidia.com>
|
|
|
32bb78 |
Date: Mon Sep 14 08:59:56 2020 -0300
|
|
|
32bb78 |
|
|
|
32bb78 |
RDMA/ucma: Rework ucma_migrate_id() to avoid races with destroy
|
|
|
32bb78 |
|
|
|
32bb78 |
ucma_destroy_id() assumes that all things accessing the ctx will do so via
|
|
|
32bb78 |
the xarray. This assumption violated only in the case the FD is being
|
|
|
32bb78 |
closed, then the ctx is reached via the ctx_list. Normally this is OK
|
|
|
32bb78 |
since ucma_destroy_id() cannot run concurrenty with release(), however
|
|
|
32bb78 |
with ucma_migrate_id() is involved this can violated as the close of the
|
|
|
32bb78 |
2nd FD can run concurrently with destroy on the first:
|
|
|
32bb78 |
|
|
|
32bb78 |
CPU0 CPU1
|
|
|
32bb78 |
ucma_destroy_id(fda)
|
|
|
32bb78 |
ucma_migrate_id(fda -> fdb)
|
|
|
32bb78 |
ucma_get_ctx()
|
|
|
32bb78 |
xa_lock()
|
|
|
32bb78 |
_ucma_find_context()
|
|
|
32bb78 |
xa_erase()
|
|
|
32bb78 |
xa_unlock()
|
|
|
32bb78 |
xa_lock()
|
|
|
32bb78 |
ctx->file = new_file
|
|
|
32bb78 |
list_move()
|
|
|
32bb78 |
xa_unlock()
|
|
|
32bb78 |
ucma_put_ctx()
|
|
|
32bb78 |
|
|
|
32bb78 |
ucma_close(fdb)
|
|
|
32bb78 |
_destroy_id()
|
|
|
32bb78 |
kfree(ctx)
|
|
|
32bb78 |
|
|
|
32bb78 |
_destroy_id()
|
|
|
32bb78 |
wait_for_completion()
|
|
|
32bb78 |
// boom, ctx was freed
|
|
|
32bb78 |
|
|
|
32bb78 |
The ctx->file must be modified under the handler and xa_lock, and prior to
|
|
|
32bb78 |
modification the ID must be rechecked that it is still reachable from
|
|
|
32bb78 |
cur_file, ie there is no parallel destroy or migrate.
|
|
|
32bb78 |
|
|
|
32bb78 |
To make this work remove the double locking and streamline the control
|
|
|
32bb78 |
flow. The double locking was obsoleted by the handler lock now directly
|
|
|
32bb78 |
preventing new uevents from being created, and the ctx_list cannot be read
|
|
|
32bb78 |
while holding fgets on both files. Removing the double locking also
|
|
|
32bb78 |
removes the need to check for the same file.
|
|
|
32bb78 |
|
|
|
32bb78 |
Fixes: 88314e4dda1e ("RDMA/cma: add support for rdma_migrate_id()")
|
|
|
32bb78 |
Link: https://lore.kernel.org/r/0-v1-05c5a4090305+3a872-ucma_syz_migrate_jgg@nvidia.com
|
|
|
32bb78 |
Reported-and-tested-by: syzbot+cc6fc752b3819e082d0c@syzkaller.appspotmail.com
|
|
|
32bb78 |
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
|
|
|
32bb78 |
|
|
|
32bb78 |
Signed-off-by: Kamal Heib <kheib@redhat.com>
|
|
|
32bb78 |
|
|
|
32bb78 |
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
|
|
|
32bb78 |
---
|
|
|
32bb78 |
drivers/infiniband/core/ucma.c | 11 ++++++++++-
|
|
|
32bb78 |
1 file changed, 10 insertions(+), 1 deletion(-)
|
|
|
32bb78 |
|
|
|
32bb78 |
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
|
|
|
32bb78 |
index 138e0096ca8e..2cd4277bf4a8 100644
|
|
|
32bb78 |
--- a/drivers/infiniband/core/ucma.c
|
|
|
32bb78 |
+++ b/drivers/infiniband/core/ucma.c
|
|
|
32bb78 |
@@ -1626,7 +1626,7 @@ static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2)
|
|
|
32bb78 |
}
|
|
|
32bb78 |
}
|
|
|
32bb78 |
|
|
|
32bb78 |
-static void ucma_unlock_files(struct ucma_file *file1, struct ucma_file *file2)
|
|
|
32bb78 |
+static __always_inline void ucma_unlock_files(struct ucma_file *file1, struct ucma_file *file2)
|
|
|
32bb78 |
{
|
|
|
32bb78 |
if (file1 < file2) {
|
|
|
32bb78 |
mutex_unlock(&file2->mut);
|
|
|
32bb78 |
@@ -1689,6 +1689,14 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
|
|
|
32bb78 |
ucma_lock_files(cur_file, new_file);
|
|
|
32bb78 |
xa_lock(&ctx_table);
|
|
|
32bb78 |
|
|
|
32bb78 |
+ /* CVE-2020-36385 kpatch: double check the context one last time */
|
|
|
32bb78 |
+ if (_ucma_find_context(cmd.id, cur_file) != ctx) {
|
|
|
32bb78 |
+ xa_unlock(&ctx_table);
|
|
|
32bb78 |
+ ucma_unlock_files(cur_file, new_file);
|
|
|
32bb78 |
+ ret = -ENOENT;
|
|
|
32bb78 |
+ goto err_unlock;
|
|
|
32bb78 |
+ }
|
|
|
32bb78 |
+
|
|
|
32bb78 |
list_move_tail(&ctx->list, &new_file->ctx_list);
|
|
|
32bb78 |
ucma_move_events(ctx, new_file);
|
|
|
32bb78 |
ctx->file = new_file;
|
|
|
32bb78 |
@@ -1702,6 +1710,7 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
|
|
|
32bb78 |
&resp, sizeof(resp)))
|
|
|
32bb78 |
ret = -EFAULT;
|
|
|
32bb78 |
|
|
|
32bb78 |
+err_unlock:
|
|
|
32bb78 |
ucma_put_ctx(ctx);
|
|
|
32bb78 |
file_put:
|
|
|
32bb78 |
fdput(f);
|
|
|
32bb78 |
--
|
|
|
32bb78 |
2.31.1
|
|
|
32bb78 |
|
|
|
32bb78 |
|