Blame SOURCES/CVE-2020-36385.patch

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