summaryrefslogtreecommitdiff
path: root/fs/file.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-11-28 17:56:10 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-11-28 17:56:10 +0100
commit9d1566e1f36b5167731372d2dfea97dbb4c43edf (patch)
tree7eff84e5fd2c5758bb932d9e48ba1a5e43a80cad /fs/file.c
parent907140462eb511f3d98aa89c0665da1b618d3545 (diff)
parentb7b275e60bcd5f89771e865a8239325f86d9927d (diff)
Merge 6.1-rc7 into usb-next
We need the USB fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/file.c')
-rw-r--r--fs/file.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/file.c b/fs/file.c
index 5f9c802a5d8d3..c942c89ca4cda 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -1003,7 +1003,16 @@ static unsigned long __fget_light(unsigned int fd, fmode_t mask)
struct files_struct *files = current->files;
struct file *file;
- if (atomic_read(&files->count) == 1) {
+ /*
+ * If another thread is concurrently calling close_fd() followed
+ * by put_files_struct(), we must not observe the old table
+ * entry combined with the new refcount - otherwise we could
+ * return a file that is concurrently being freed.
+ *
+ * atomic_read_acquire() pairs with atomic_dec_and_test() in
+ * put_files_struct().
+ */
+ if (atomic_read_acquire(&files->count) == 1) {
file = files_lookup_fd_raw(files, fd);
if (!file || unlikely(file->f_mode & mask))
return 0;