Merge branch 'vfs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs

Pull vfs fixes from Miklos Szeredi.

This mainly fixes some confusion about whether the open 'mode' variable
passed around should contain the full file type (S_IFREG etc)
information or just the permission mode.  In particular, the lack of
proper file type information had confused fuse.

* 'vfs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
  vfs: fix propagation of atomic_open create error on negative dentry
  fuse: check create mode in atomic open
  vfs: pass right create mode to may_o_create()
  vfs: atomic_open(): fix create mode usage
  vfs: canonicalize create mode in build_open_flags()
This commit is contained in:
Linus Torvalds 2012-08-18 10:02:17 -07:00
commit 20fb1936de
3 changed files with 13 additions and 5 deletions

View file

@ -383,6 +383,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
struct fuse_entry_out outentry;
struct fuse_file *ff;
/* Userspace expects S_IFREG in create mode */
BUG_ON((mode & S_IFMT) != S_IFREG);
forget = fuse_alloc_forget();
err = -ENOMEM;
if (!forget)

View file

@ -2414,7 +2414,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
goto out;
}
mode = op->mode & S_IALLUGO;
mode = op->mode;
if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
mode &= ~current_umask();
@ -2452,7 +2452,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
}
if (open_flag & O_CREAT) {
error = may_o_create(&nd->path, dentry, op->mode);
error = may_o_create(&nd->path, dentry, mode);
if (error) {
create_error = error;
if (open_flag & O_EXCL)
@ -2489,6 +2489,10 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
dput(dentry);
dentry = file->f_path.dentry;
}
if (create_error && dentry->d_inode == NULL) {
error = create_error;
goto out;
}
goto looked_up;
}

View file

@ -852,9 +852,10 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
int lookup_flags = 0;
int acc_mode;
if (!(flags & O_CREAT))
mode = 0;
op->mode = mode;
if (flags & O_CREAT)
op->mode = (mode & S_IALLUGO) | S_IFREG;
else
op->mode = 0;
/* Must never be set by userspace */
flags &= ~FMODE_NONOTIFY;