Blame SOURCES/CVE-2020-36385.patch

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