Skip to content

Commit

Permalink
don't bother with {get,put}_write_access() on non-regular files
Browse files Browse the repository at this point in the history
it's pointless and actually leads to wrong behaviour in at least one
moderately convoluted case (pipe(), close one end, try to get to
another via /proc/*/fd and run into ETXTBUSY).

Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Apr 2, 2014
1 parent 44ba840 commit dd20908
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 21 deletions.
4 changes: 2 additions & 2 deletions fs/file_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,10 @@ static void drop_file_write_access(struct file *file)
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;

put_write_access(inode);

if (special_file(inode->i_mode))
return;

put_write_access(inode);
if (file_check_writeable(file) != 0)
return;
__mnt_drop_write(mnt);
Expand Down
26 changes: 7 additions & 19 deletions fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,23 +641,12 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
static inline int __get_file_write_access(struct inode *inode,
struct vfsmount *mnt)
{
int error;
error = get_write_access(inode);
int error = get_write_access(inode);
if (error)
return error;
/*
* Do not take mount writer counts on
* special files since no writes to
* the mount itself will occur.
*/
if (!special_file(inode->i_mode)) {
/*
* Balanced in __fput()
*/
error = __mnt_want_write(mnt);
if (error)
put_write_access(inode);
}
error = __mnt_want_write(mnt);
if (error)
put_write_access(inode);
return error;
}

Expand Down Expand Up @@ -690,12 +679,11 @@ static int do_dentry_open(struct file *f,

path_get(&f->f_path);
inode = f->f_inode = f->f_path.dentry->d_inode;
if (f->f_mode & FMODE_WRITE) {
if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
error = __get_file_write_access(inode, f->f_path.mnt);
if (error)
goto cleanup_file;
if (!special_file(inode->i_mode))
file_take_write(f);
file_take_write(f);
}

f->f_mapping = inode->i_mapping;
Expand Down Expand Up @@ -742,14 +730,14 @@ static int do_dentry_open(struct file *f,
cleanup_all:
fops_put(f->f_op);
if (f->f_mode & FMODE_WRITE) {
put_write_access(inode);
if (!special_file(inode->i_mode)) {
/*
* We don't consider this a real
* mnt_want/drop_write() pair
* because it all happenend right
* here, so just reset the state.
*/
put_write_access(inode);
file_reset_write(f);
__mnt_drop_write(f->f_path.mnt);
}
Expand Down

0 comments on commit dd20908

Please sign in to comment.