Blame SOURCES/CVE-2021-4083.patch

f8d36f
From 80c7e812dffa734599aadde93cb8e30b34f0983d Mon Sep 17 00:00:00 2001
f8d36f
From: Joe Lawrence <joe.lawrence@redhat.com>
f8d36f
Date: Mon, 21 Mar 2022 15:45:03 -0400
f8d36f
Subject: [KPATCH CVE-2021-4083] fget: kpatch fixes for CVE-2021-4083
f8d36f
f8d36f
Kernels:
f8d36f
3.10.0-1160.24.1.el7
f8d36f
3.10.0-1160.25.1.el7
f8d36f
3.10.0-1160.31.1.el7
f8d36f
3.10.0-1160.36.2.el7
f8d36f
3.10.0-1160.41.1.el7
f8d36f
3.10.0-1160.42.2.el7
f8d36f
3.10.0-1160.45.1.el7
f8d36f
3.10.0-1160.49.1.el7
f8d36f
3.10.0-1160.53.1.el7
f8d36f
3.10.0-1160.59.1.el7
f8d36f
f8d36f
Changes since last build:
f8d36f
arches: x86_64 ppc64le
f8d36f
file.o: changed function: SyS_dup
f8d36f
file.o: changed function: dup_fd
f8d36f
file.o: changed function: fget
f8d36f
file.o: changed function: fget_light
f8d36f
file.o: changed function: fget_raw
f8d36f
file.o: changed function: fget_raw_light
f8d36f
file.o: changed function: put_files_struct
f8d36f
file.o: new function: __fget
f8d36f
file.o: new function: __fget_light
f8d36f
---------------------------
f8d36f
f8d36f
Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-7/-/merge_requests/34
f8d36f
Approved-by: Yannick Cote (@ycote1)
f8d36f
Modifications:
f8d36f
- include/linux/rcupdate.h, kernel/rcupdate.c: leave exported
f8d36f
  rcu_my_thread_group_empty() intact
f8d36f
- fs/file.c: use fput() instead of fputs_many() since we skipped commit
f8d36f
  ("fs: add fget_many() and fput_many()")
f8d36f
- fs/file.c: use fcheck_files() instead of files_lookup_fd_raw() since
f8d36f
  we are skipping subsequent commit ("fget: clarify and improve
f8d36f
  __fget_files() implementation") that provides it.
f8d36f
- Set __attribute__((optimize("-fno-optimize-sibling-calls"))) for
f8d36f
  fget() and fget_raw() on ppc64le
f8d36f
f8d36f
commit c2207a235113315ad696b06eb96ccd36d1f5fdeb
f8d36f
Author: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
Date:   Fri Jan 21 10:22:29 2022 +0100
f8d36f
f8d36f
    introduce __fcheck_files() to fix rcu_dereference_check_fdtable(), kill rcu_my_thread_group_empty()
f8d36f
f8d36f
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2032478
f8d36f
    Upstream status: Linus
f8d36f
    Testing: xfstests
f8d36f
    CVE: CVE-2021-4083
f8d36f
    Conflicts:
f8d36f
            - context difference due to backport of later patch
f8d36f
            - target file difference due to missing backport of rcu source code
f8d36f
              move
f8d36f
f8d36f
    commit a8d4b8345e0ee48b732126d980efaf0dc373e2b0
f8d36f
    Author: Oleg Nesterov <oleg@redhat.com>
f8d36f
    Date:   Sat Jan 11 19:19:32 2014 +0100
f8d36f
f8d36f
        introduce __fcheck_files() to fix rcu_dereference_check_fdtable(), kill rcu_my_thread_group_empty()
f8d36f
f8d36f
        rcu_dereference_check_fdtable() looks very wrong,
f8d36f
f8d36f
        1. rcu_my_thread_group_empty() was added by 844b9a8707f1 "vfs: fix
f8d36f
           RCU-lockdep false positive due to /proc" but it doesn't really
f8d36f
           fix the problem. A CLONE_THREAD (without CLONE_FILES) task can
f8d36f
           hit the same race with get_files_struct().
f8d36f
f8d36f
           And otoh rcu_my_thread_group_empty() can suppress the correct
f8d36f
           warning if the caller is the CLONE_FILES (without CLONE_THREAD)
f8d36f
           task.
f8d36f
f8d36f
        2. files->count == 1 check is not really right too. Even if this
f8d36f
           files_struct is not shared it is not safe to access it lockless
f8d36f
           unless the caller is the owner.
f8d36f
f8d36f
           Otoh, this check is sub-optimal. files->count == 0 always means
f8d36f
           it is safe to use it lockless even if files != current->files,
f8d36f
           but put_files_struct() has to take rcu_read_lock(). See the next
f8d36f
           patch.
f8d36f
f8d36f
        This patch removes the buggy checks and turns fcheck_files() into
f8d36f
        __fcheck_files() which uses rcu_dereference_raw(), the "unshared"
f8d36f
        callers, fget_light() and fget_raw_light(), can use it to avoid
f8d36f
        the warning from RCU-lockdep.
f8d36f
f8d36f
        fcheck_files() is trivially reimplemented as rcu_lockdep_assert()
f8d36f
        plus __fcheck_files().
f8d36f
f8d36f
        Signed-off-by: Oleg Nesterov <oleg@redhat.com>
f8d36f
        Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
f8d36f
f8d36f
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
f8d36f
commit ec06bac02991edcfdeb148ab2fe7f3e2d7d3ceaa
f8d36f
Author: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
Date:   Fri Jan 21 10:22:30 2022 +0100
f8d36f
f8d36f
    fs: factor out common code in fget() and fget_raw()
f8d36f
f8d36f
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2032478
f8d36f
    Upstream status: Linus
f8d36f
    Testing: xfstests
f8d36f
    CVE: CVE-2021-4083
f8d36f
    Conflicts:
f8d36f
            - difference due to backport of later patch
f8d36f
f8d36f
    commit 1deb46e2562561255c34075825fd00f22a858bb3
f8d36f
    Author: Oleg Nesterov <oleg@redhat.com>
f8d36f
    Date:   Mon Jan 13 16:48:19 2014 +0100
f8d36f
f8d36f
        fs: factor out common code in fget() and fget_raw()
f8d36f
f8d36f
        Apart from FMODE_PATH check fget() and fget_raw() are identical,
f8d36f
        shift the code into the new simple helper, __fget(fd, mask). Saves
f8d36f
        160 bytes.
f8d36f
f8d36f
        Signed-off-by: Oleg Nesterov <oleg@redhat.com>
f8d36f
        Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
f8d36f
f8d36f
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
f8d36f
commit ac43fab520f6836e2a7d3d20dd64d6328233ccbe
f8d36f
Author: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
Date:   Fri Jan 21 10:22:30 2022 +0100
f8d36f
f8d36f
    fs: factor out common code in fget_light() and fget_raw_light()
f8d36f
f8d36f
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2032478
f8d36f
    Upstream status: Linus
f8d36f
    Testing: xfstests
f8d36f
    CVE: CVE-2021-4083
f8d36f
f8d36f
    commit ad46183445043b562856c60b74db664668fb364b
f8d36f
    Author: Oleg Nesterov <oleg@redhat.com>
f8d36f
    Date:   Mon Jan 13 16:48:40 2014 +0100
f8d36f
f8d36f
        fs: factor out common code in fget_light() and fget_raw_light()
f8d36f
f8d36f
        Apart from FMODE_PATH check fget_light() and fget_raw_light() are
f8d36f
        identical, shift the code into the new helper, __fget_light(fd, mask).
f8d36f
        Saves 208 bytes.
f8d36f
f8d36f
        Signed-off-by: Oleg Nesterov <oleg@redhat.com>
f8d36f
        Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
f8d36f
f8d36f
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
f8d36f
commit 9e24c8894f5df488a336f0c848f15a7d2f78d163
f8d36f
Author: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
Date:   Fri Jan 21 10:22:30 2022 +0100
f8d36f
f8d36f
    fs: __fget_light() can use __fget() in slow path
f8d36f
f8d36f
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2032478
f8d36f
    Upstream status: Linus
f8d36f
    Testing: xfstests
f8d36f
    CVE: CVE-2021-4083
f8d36f
f8d36f
    commit e6ff9a9fa4e05c1c03dec63cdc6a87d6dea02755
f8d36f
    Author: Oleg Nesterov <oleg@redhat.com>
f8d36f
    Date:   Mon Jan 13 16:49:06 2014 +0100
f8d36f
f8d36f
        fs: __fget_light() can use __fget() in slow path
f8d36f
f8d36f
        The slow path in __fget_light() can use __fget() to avoid the
f8d36f
        code duplication. Saves 232 bytes.
f8d36f
f8d36f
        Signed-off-by: Oleg Nesterov <oleg@redhat.com>
f8d36f
        Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
f8d36f
f8d36f
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
f8d36f
commit d63fb584ae2d7d9a1620e23e59072cb6929f3833
f8d36f
Author: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
Date:   Fri Jan 21 10:22:30 2022 +0100
f8d36f
f8d36f
    fs/file.c: __fget() and dup2() atomicity rules
f8d36f
f8d36f
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2032478
f8d36f
    Upstream status: Linus
f8d36f
    Testing: xfstests
f8d36f
    CVE: CVE-2021-4083
f8d36f
f8d36f
    commit 5ba97d2832f87943c43bb69cb1ef86dbc59df5bc
f8d36f
    Author: Eric Dumazet <edumazet@google.com>
f8d36f
    Date:   Mon Jun 29 17:10:30 2015 +0200
f8d36f
f8d36f
        fs/file.c: __fget() and dup2() atomicity rules
f8d36f
f8d36f
        __fget() does lockless fetch of pointer from the descriptor
f8d36f
        table, attempts to grab a reference and treats "it was already
f8d36f
        zero" as "it's already gone from the table, we just hadn't
f8d36f
        seen the store, let's fail".  Unfortunately, that breaks the
f8d36f
        atomicity of dup2() - __fget() might see the old pointer,
f8d36f
        notice that it's been already dropped and treat that as
f8d36f
        "it's closed".  What we should be getting is either the
f8d36f
        old file or new one, depending whether we come before or after
f8d36f
        dup2().
f8d36f
f8d36f
        Dmitry had following test failing sometimes :
f8d36f
f8d36f
        int fd;
f8d36f
        void *Thread(void *x) {
f8d36f
          char buf;
f8d36f
          int n = read(fd, &buf, 1);
f8d36f
          if (n != 1)
f8d36f
            exit(printf("read failed: n=%d errno=%d\n", n, errno));
f8d36f
          return 0;
f8d36f
        }
f8d36f
f8d36f
        int main()
f8d36f
        {
f8d36f
          fd = open("/dev/urandom", O_RDONLY);
f8d36f
          int fd2 = open("/dev/urandom", O_RDONLY);
f8d36f
          if (fd == -1 || fd2 == -1)
f8d36f
            exit(printf("open failed\n"));
f8d36f
          pthread_t th;
f8d36f
          pthread_create(&th, 0, Thread, 0);
f8d36f
          if (dup2(fd2, fd) == -1)
f8d36f
            exit(printf("dup2 failed\n"));
f8d36f
          pthread_join(th, 0);
f8d36f
          if (close(fd) == -1)
f8d36f
            exit(printf("close failed\n"));
f8d36f
          if (close(fd2) == -1)
f8d36f
            exit(printf("close failed\n"));
f8d36f
          printf("DONE\n");
f8d36f
          return 0;
f8d36f
        }
f8d36f
f8d36f
        Signed-off-by: Eric Dumazet <edumazet@google.com>
f8d36f
        Reported-by: Dmitry Vyukov <dvyukov@google.com>
f8d36f
        Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
f8d36f
f8d36f
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
f8d36f
commit bc04a10c9303dcd9a6305a0452361537257fa0c1
f8d36f
Author: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
Date:   Fri Jan 21 10:22:31 2022 +0100
f8d36f
f8d36f
    fget: check that the fd still exists after getting a ref to it
f8d36f
f8d36f
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2032478
f8d36f
    Upstream status: Linus
f8d36f
    Testing: xfstests
f8d36f
    CVE: CVE-2021-4083
f8d36f
f8d36f
    commit 054aa8d439b9185d4f5eb9a90282d1ce74772969
f8d36f
    Author: Linus Torvalds <torvalds@linux-foundation.org>
f8d36f
    Date:   Wed Dec 1 10:06:14 2021 -0800
f8d36f
f8d36f
        fget: check that the fd still exists after getting a ref to it
f8d36f
f8d36f
        Jann Horn points out that there is another possible race wrt Unix domain
f8d36f
        socket garbage collection, somewhat reminiscent of the one fixed in
f8d36f
        commit cbcf01128d0a ("af_unix: fix garbage collect vs MSG_PEEK").
f8d36f
f8d36f
        See the extended comment about the garbage collection requirements added
f8d36f
        to unix_peek_fds() by that commit for details.
f8d36f
f8d36f
        The race comes from how we can locklessly look up a file descriptor just
f8d36f
        as it is in the process of being closed, and with the right artificial
f8d36f
        timing (Jann added a few strategic 'mdelay(500)' calls to do that), the
f8d36f
        Unix domain socket garbage collector could see the reference count
f8d36f
        decrement of the close() happen before fget() took its reference to the
f8d36f
        file and the file was attached onto a new file descriptor.
f8d36f
f8d36f
        This is all (intentionally) correct on the 'struct file *' side, with
f8d36f
        RCU lookups and lockless reference counting very much part of the
f8d36f
        design.  Getting that reference count out of order isn't a problem per
f8d36f
        se.
f8d36f
f8d36f
        But the garbage collector can get confused by seeing this situation of
f8d36f
        having seen a file not having any remaining external references and then
f8d36f
        seeing it being attached to an fd.
f8d36f
f8d36f
        In commit cbcf01128d0a ("af_unix: fix garbage collect vs MSG_PEEK") the
f8d36f
        fix was to serialize the file descriptor install with the garbage
f8d36f
        collector by taking and releasing the unix_gc_lock.
f8d36f
f8d36f
        That's not really an option here, but since this all happens when we are
f8d36f
        in the process of looking up a file descriptor, we can instead simply
f8d36f
        just re-check that the file hasn't been closed in the meantime, and just
f8d36f
        re-do the lookup if we raced with a concurrent close() of the same file
f8d36f
        descriptor.
f8d36f
f8d36f
        Reported-and-tested-by: Jann Horn <jannh@google.com>
f8d36f
        Acked-by: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
        Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
f8d36f
f8d36f
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
f8d36f
f8d36f
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
f8d36f
---
f8d36f
 fs/file.c               | 86 +++++++++++++++--------------------------
f8d36f
 include/linux/fdtable.h | 35 ++++++++++-------
f8d36f
 2 files changed, 53 insertions(+), 68 deletions(-)
f8d36f
f8d36f
diff --git a/fs/file.c b/fs/file.c
f8d36f
index 44bd634b636a..564d60bf0fda 100644
f8d36f
--- a/fs/file.c
f8d36f
+++ b/fs/file.c
f8d36f
@@ -718,42 +718,43 @@ void do_close_on_exec(struct files_struct *files)
f8d36f
 	spin_unlock(&files->file_lock);
f8d36f
 }
f8d36f
 
f8d36f
-struct file *fget(unsigned int fd)
f8d36f
+static struct file *__fget(unsigned int fd, fmode_t mask)
f8d36f
 {
f8d36f
-	struct file *file;
f8d36f
 	struct files_struct *files = current->files;
f8d36f
+	struct file *file;
f8d36f
 
f8d36f
 	rcu_read_lock();
f8d36f
+loop:
f8d36f
 	file = fcheck_files(files, fd);
f8d36f
 	if (file) {
f8d36f
-		/* File object ref couldn't be taken */
f8d36f
-		if (file->f_mode & FMODE_PATH || !get_file_rcu(file))
f8d36f
+		/* File object ref couldn't be taken.
f8d36f
+		 * dup2() atomicity guarantee is the reason
f8d36f
+		 * we loop to catch the new file (or NULL pointer)
f8d36f
+		 */
f8d36f
+		if (file->f_mode & mask)
f8d36f
 			file = NULL;
f8d36f
+		else if (!get_file_rcu(file))
f8d36f
+			goto loop;
f8d36f
+		else if (fcheck_files(files, fd) != file) {
f8d36f
+			fput(file);
f8d36f
+			goto loop;
f8d36f
+		}
f8d36f
 	}
f8d36f
 	rcu_read_unlock();
f8d36f
 
f8d36f
 	return file;
f8d36f
 }
f8d36f
 
f8d36f
+__attribute__((optimize("-fno-optimize-sibling-calls"))) struct file *fget(unsigned int fd)
f8d36f
+{
f8d36f
+	return __fget(fd, FMODE_PATH);
f8d36f
+}
f8d36f
 EXPORT_SYMBOL(fget);
f8d36f
 
f8d36f
-struct file *fget_raw(unsigned int fd)
f8d36f
+__attribute__((optimize("-fno-optimize-sibling-calls"))) struct file *fget_raw(unsigned int fd)
f8d36f
 {
f8d36f
-	struct file *file;
f8d36f
-	struct files_struct *files = current->files;
f8d36f
-
f8d36f
-	rcu_read_lock();
f8d36f
-	file = fcheck_files(files, fd);
f8d36f
-	if (file) {
f8d36f
-		/* File object ref couldn't be taken */
f8d36f
-		if (!atomic_long_inc_not_zero(&file->f_count))
f8d36f
-			file = NULL;
f8d36f
-	}
f8d36f
-	rcu_read_unlock();
f8d36f
-
f8d36f
-	return file;
f8d36f
+	return __fget(fd, 0);
f8d36f
 }
f8d36f
-
f8d36f
 EXPORT_SYMBOL(fget_raw);
f8d36f
 
f8d36f
 /*
f8d36f
@@ -772,56 +773,33 @@ EXPORT_SYMBOL(fget_raw);
f8d36f
  * The fput_needed flag returned by fget_light should be passed to the
f8d36f
  * corresponding fput_light.
f8d36f
  */
f8d36f
-struct file *fget_light(unsigned int fd, int *fput_needed)
f8d36f
+struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed)
f8d36f
 {
f8d36f
-	struct file *file;
f8d36f
 	struct files_struct *files = current->files;
f8d36f
+	struct file *file;
f8d36f
 
f8d36f
 	*fput_needed = 0;
f8d36f
 	if (atomic_read(&files->count) == 1) {
f8d36f
-		file = fcheck_files(files, fd);
f8d36f
-		if (file && (file->f_mode & FMODE_PATH))
f8d36f
+		file = __fcheck_files(files, fd);
f8d36f
+		if (file && (file->f_mode & mask))
f8d36f
 			file = NULL;
f8d36f
 	} else {
f8d36f
-		rcu_read_lock();
f8d36f
-		file = fcheck_files(files, fd);
f8d36f
-		if (file) {
f8d36f
-			if (!(file->f_mode & FMODE_PATH) &&
f8d36f
-			    atomic_long_inc_not_zero(&file->f_count))
f8d36f
-				*fput_needed = 1;
f8d36f
-			else
f8d36f
-				/* Didn't get the reference, someone's freed */
f8d36f
-				file = NULL;
f8d36f
-		}
f8d36f
-		rcu_read_unlock();
f8d36f
+		file = __fget(fd, mask);
f8d36f
+		if (file)
f8d36f
+			*fput_needed = 1;
f8d36f
 	}
f8d36f
 
f8d36f
 	return file;
f8d36f
 }
f8d36f
+struct file *fget_light(unsigned int fd, int *fput_needed)
f8d36f
+{
f8d36f
+	return __fget_light(fd, FMODE_PATH, fput_needed);
f8d36f
+}
f8d36f
 EXPORT_SYMBOL(fget_light);
f8d36f
 
f8d36f
 struct file *fget_raw_light(unsigned int fd, int *fput_needed)
f8d36f
 {
f8d36f
-	struct file *file;
f8d36f
-	struct files_struct *files = current->files;
f8d36f
-
f8d36f
-	*fput_needed = 0;
f8d36f
-	if (atomic_read(&files->count) == 1) {
f8d36f
-		file = fcheck_files(files, fd);
f8d36f
-	} else {
f8d36f
-		rcu_read_lock();
f8d36f
-		file = fcheck_files(files, fd);
f8d36f
-		if (file) {
f8d36f
-			if (atomic_long_inc_not_zero(&file->f_count))
f8d36f
-				*fput_needed = 1;
f8d36f
-			else
f8d36f
-				/* Didn't get the reference, someone's freed */
f8d36f
-				file = NULL;
f8d36f
-		}
f8d36f
-		rcu_read_unlock();
f8d36f
-	}
f8d36f
-
f8d36f
-	return file;
f8d36f
+	return __fget_light(fd, 0, fput_needed);
f8d36f
 }
f8d36f
 
f8d36f
 void set_close_on_exec(unsigned int fd, int flag)
f8d36f
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
f8d36f
index 88d74ca9418f..95bcca7c1a0f 100644
f8d36f
--- a/include/linux/fdtable.h
f8d36f
+++ b/include/linux/fdtable.h
f8d36f
@@ -70,29 +70,36 @@ struct files_struct {
f8d36f
 	RH_KABI_EXTEND(wait_queue_head_t resize_wait)
f8d36f
 };
f8d36f
 
f8d36f
-#define rcu_dereference_check_fdtable(files, fdtfd) \
f8d36f
-	(rcu_dereference_check((fdtfd), \
f8d36f
-			       lockdep_is_held(&(files)->file_lock) || \
f8d36f
-			       atomic_read(&(files)->count) == 1 || \
f8d36f
-			       rcu_my_thread_group_empty()))
f8d36f
-
f8d36f
-#define files_fdtable(files) \
f8d36f
-		(rcu_dereference_check_fdtable((files), (files)->fdt))
f8d36f
-
f8d36f
 struct file_operations;
f8d36f
 struct vfsmount;
f8d36f
 struct dentry;
f8d36f
 
f8d36f
-static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
f8d36f
+#define rcu_dereference_check_fdtable(files, fdtfd) \
f8d36f
+	rcu_dereference_check((fdtfd), lockdep_is_held(&(files)->file_lock))
f8d36f
+
f8d36f
+#define files_fdtable(files) \
f8d36f
+	rcu_dereference_check_fdtable((files), (files)->fdt)
f8d36f
+
f8d36f
+/*
f8d36f
+ * The caller must ensure that fd table isn't shared or hold rcu or file lock
f8d36f
+ */
f8d36f
+static inline struct file *__fcheck_files(struct files_struct *files, unsigned int fd)
f8d36f
 {
f8d36f
-	struct file * file = NULL;
f8d36f
-	struct fdtable *fdt = files_fdtable(files);
f8d36f
+	struct fdtable *fdt = rcu_dereference_raw(files->fdt);
f8d36f
 
f8d36f
 	if (fd < fdt->max_fds) {
f8d36f
 		fd = array_index_nospec(fd, fdt->max_fds);
f8d36f
-		file = rcu_dereference_check_fdtable(files, fdt->fd[fd]);
f8d36f
+		return rcu_dereference_raw(fdt->fd[fd]);
f8d36f
 	}
f8d36f
-	return file;
f8d36f
+	return NULL;
f8d36f
+}
f8d36f
+
f8d36f
+static inline struct file *fcheck_files(struct files_struct *files, unsigned int fd)
f8d36f
+{
f8d36f
+	rcu_lockdep_assert(rcu_read_lock_held() ||
f8d36f
+			   lockdep_is_held(&files->file_lock),
f8d36f
+			   "suspicious rcu_dereference_check() usage");
f8d36f
+	return __fcheck_files(files, fd);
f8d36f
 }
f8d36f
 
f8d36f
 /*
f8d36f
-- 
f8d36f
2.26.3
f8d36f
f8d36f