Skip to content

Commit

Permalink
vfs: Don't let __fdget_pos() get FMODE_PATH files
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
ebiggers authored and Al Viro committed Mar 23, 2014
1 parent d7a15f8 commit 99aea68
Showing 1 changed file with 4 additions and 15 deletions.
19 changes: 4 additions & 15 deletions fs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,27 +713,16 @@ unsigned long __fdget_raw(unsigned int fd)

unsigned long __fdget_pos(unsigned int fd)
{
struct files_struct *files = current->files;
struct file *file;
unsigned long v;

if (atomic_read(&files->count) == 1) {
file = __fcheck_files(files, fd);
v = 0;
} else {
file = __fget(fd, 0);
v = FDPUT_FPUT;
}
if (!file)
return 0;
unsigned long v = __fdget(fd);
struct file *file = (struct file *)(v & ~3);

if (file->f_mode & FMODE_ATOMIC_POS) {
if (file && (file->f_mode & FMODE_ATOMIC_POS)) {
if (file_count(file) > 1) {
v |= FDPUT_POS_UNLOCK;
mutex_lock(&file->f_pos_lock);
}
}
return v | (unsigned long)file;
return v;
}

/*
Expand Down

0 comments on commit 99aea68

Please sign in to comment.