diff options
Diffstat (limited to 'fs/file.c')
-rw-r--r-- | fs/file.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/file.c b/fs/file.c index 3d2eb4c542a4..6c672ad329e9 100644 --- a/fs/file.c +++ b/fs/file.c @@ -664,11 +664,17 @@ static struct file *__fget(unsigned int fd, fmode_t mask) struct file *file; rcu_read_lock(); +loop: file = fcheck_files(files, fd); if (file) { - /* File object ref couldn't be taken */ - if ((file->f_mode & mask) || !get_file_rcu(file)) + /* File object ref couldn't be taken. + * dup2() atomicity guarantee is the reason + * we loop to catch the new file (or NULL pointer) + */ + if (file->f_mode & mask) file = NULL; + else if (!get_file_rcu(file)) + goto loop; } rcu_read_unlock(); |