Skip to content

Commit 7ee47dc

Browse files
thejhAl Viro
authored andcommitted
fs: use acquire ordering in __fget_light()
We must prevent the CPU from reordering the files->count read with the FD table access like this, on architectures where read-read reordering is possible: files_lookup_fd_raw() close_fd() put_files_struct() atomic_read(&files->count) I would like to mark this for stable, but the stable rules explicitly say "no theoretical races", and given that the FD table pointer and files->count are explicitly stored in the same cacheline, this sort of reordering seems quite unlikely in practice... Signed-off-by: Jann Horn <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 9abf231 commit 7ee47dc

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

fs/file.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,16 @@ static unsigned long __fget_light(unsigned int fd, fmode_t mask)
10031003
struct files_struct *files = current->files;
10041004
struct file *file;
10051005

1006-
if (atomic_read(&files->count) == 1) {
1006+
/*
1007+
* If another thread is concurrently calling close_fd() followed
1008+
* by put_files_struct(), we must not observe the old table
1009+
* entry combined with the new refcount - otherwise we could
1010+
* return a file that is concurrently being freed.
1011+
*
1012+
* atomic_read_acquire() pairs with atomic_dec_and_test() in
1013+
* put_files_struct().
1014+
*/
1015+
if (atomic_read_acquire(&files->count) == 1) {
10071016
file = files_lookup_fd_raw(files, fd);
10081017
if (!file || unlikely(file->f_mode & mask))
10091018
return 0;

0 commit comments

Comments
 (0)