Skip to content

Commit 99aea68

Browse files
ebiggersAl Viro
authored andcommitted
vfs: Don't let __fdget_pos() get FMODE_PATH files
Commit bd2a31d ("get rid of fget_light()") introduced the __fdget_pos() function, which returns the resulting file pointer and fdput flags combined in an 'unsigned long'. However, it also changed the behavior to return files with FMODE_PATH set, which shouldn't happen because read(), write(), lseek(), etc. aren't allowed on such files. This commit restores the old behavior. This regression actually had no effect on read() and write() since FMODE_READ and FMODE_WRITE are not set on file descriptors opened with O_PATH, but it did cause lseek() on a file descriptor opened with O_PATH to fail with ESPIPE rather than EBADF. Signed-off-by: Eric Biggers <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent d7a15f8 commit 99aea68

File tree

1 file changed

+4
-15
lines changed

1 file changed

+4
-15
lines changed

fs/file.c

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -713,27 +713,16 @@ unsigned long __fdget_raw(unsigned int fd)
713713

714714
unsigned long __fdget_pos(unsigned int fd)
715715
{
716-
struct files_struct *files = current->files;
717-
struct file *file;
718-
unsigned long v;
719-
720-
if (atomic_read(&files->count) == 1) {
721-
file = __fcheck_files(files, fd);
722-
v = 0;
723-
} else {
724-
file = __fget(fd, 0);
725-
v = FDPUT_FPUT;
726-
}
727-
if (!file)
728-
return 0;
716+
unsigned long v = __fdget(fd);
717+
struct file *file = (struct file *)(v & ~3);
729718

730-
if (file->f_mode & FMODE_ATOMIC_POS) {
719+
if (file && (file->f_mode & FMODE_ATOMIC_POS)) {
731720
if (file_count(file) > 1) {
732721
v |= FDPUT_POS_UNLOCK;
733722
mutex_lock(&file->f_pos_lock);
734723
}
735724
}
736-
return v | (unsigned long)file;
725+
return v;
737726
}
738727

739728
/*

0 commit comments

Comments
 (0)