Blame SOURCES/CVE-2020-36385.patch

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