]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
file: Factor files_lookup_fd_locked out of fcheck_files
authorEric W. Biederman <ebiederm@xmission.com>
Fri, 20 Nov 2020 23:14:25 +0000 (17:14 -0600)
committerEric W. Biederman <ebiederm@xmission.com>
Thu, 10 Dec 2020 18:39:59 +0000 (12:39 -0600)
To make it easy to tell where files->file_lock protection is being
used when looking up a file create files_lookup_fd_locked.  Only allow
this function to be called with the file_lock held.

Update the callers of fcheck and fcheck_files that are called with the
files->file_lock held to call files_lookup_fd_locked instead.

Hopefully this makes it easier to quickly understand what is going on.

The need for better names became apparent in the last round of
discussion of this set of changes[1].

[1] https://lkml.kernel.org/r/CAHk-=wj8BQbgJFLa+J0e=iT-1qpmCRTbPAJ8gd6MJQ=kbRPqyQ@mail.gmail.com
Link: https://lkml.kernel.org/r/20201120231441.29911-8-ebiederm@xmission.com
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
fs/file.c
fs/locks.c
fs/proc/fd.c
include/linux/fdtable.h

index b5591efb87f56c5ef62ac70ca24fd5e638167a23..9d0e91168be185ecd2a05b3fcc581edd674e604f 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -1098,7 +1098,7 @@ static int ksys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
 
        spin_lock(&files->file_lock);
        err = expand_files(files, newfd);
-       file = fcheck(oldfd);
+       file = files_lookup_fd_locked(files, oldfd);
        if (unlikely(!file))
                goto Ebadf;
        if (unlikely(err < 0)) {
index 1f84a03601feca5ef577682572be81808b97e53f..148197c1b54773c10980a1e491ecf40a6d8b692a 100644 (file)
@@ -2539,14 +2539,15 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
         */
        if (!error && file_lock->fl_type != F_UNLCK &&
            !(file_lock->fl_flags & FL_OFDLCK)) {
+               struct files_struct *files = current->files;
                /*
                 * We need that spin_lock here - it prevents reordering between
                 * update of i_flctx->flc_posix and check for it done in
                 * close(). rcu_read_lock() wouldn't do.
                 */
-               spin_lock(&current->files->file_lock);
-               f = fcheck(fd);
-               spin_unlock(&current->files->file_lock);
+               spin_lock(&files->file_lock);
+               f = files_lookup_fd_locked(files, fd);
+               spin_unlock(&files->file_lock);
                if (f != filp) {
                        file_lock->fl_type = F_UNLCK;
                        error = do_lock_file_wait(filp, cmd, file_lock);
@@ -2670,14 +2671,15 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
         */
        if (!error && file_lock->fl_type != F_UNLCK &&
            !(file_lock->fl_flags & FL_OFDLCK)) {
+               struct files_struct *files = current->files;
                /*
                 * We need that spin_lock here - it prevents reordering between
                 * update of i_flctx->flc_posix and check for it done in
                 * close(). rcu_read_lock() wouldn't do.
                 */
-               spin_lock(&current->files->file_lock);
-               f = fcheck(fd);
-               spin_unlock(&current->files->file_lock);
+               spin_lock(&files->file_lock);
+               f = files_lookup_fd_locked(files, fd);
+               spin_unlock(&files->file_lock);
                if (f != filp) {
                        file_lock->fl_type = F_UNLCK;
                        error = do_lock_file_wait(filp, cmd, file_lock);
index d58960f6ee524db7fbc7642a2b1424b272359bd3..2cca9bca3b3a3ff110e856368bbaa764fc0b2587 100644 (file)
@@ -35,7 +35,7 @@ static int seq_show(struct seq_file *m, void *v)
                unsigned int fd = proc_fd(m->private);
 
                spin_lock(&files->file_lock);
-               file = fcheck_files(files, fd);
+               file = files_lookup_fd_locked(files, fd);
                if (file) {
                        struct fdtable *fdt = files_fdtable(files);
 
index 639933f37da9fbf4e3d0cd7b3ca1b052af8c5c52..fda4b81dd735ba8dbc6b97f6231d7af3047820ec 100644 (file)
@@ -91,6 +91,13 @@ static inline struct file *files_lookup_fd_raw(struct files_struct *files, unsig
        return NULL;
 }
 
+static inline struct file *files_lookup_fd_locked(struct files_struct *files, unsigned int fd)
+{
+       RCU_LOCKDEP_WARN(!lockdep_is_held(&files->file_lock),
+                          "suspicious rcu_dereference_check() usage");
+       return files_lookup_fd_raw(files, fd);
+}
+
 static inline struct file *fcheck_files(struct files_struct *files, unsigned int fd)
 {
        RCU_LOCKDEP_WARN(!rcu_read_lock_held() &&