diff options
Diffstat (limited to 'ipc/mqueue.c')
| -rw-r--r-- | ipc/mqueue.c | 49 |
1 files changed, 20 insertions, 29 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index d3a588d0dcf6..56e811f9e5fa 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -896,22 +896,23 @@ static struct file *mqueue_file_open(struct filename *name, struct vfsmount *mnt, int oflag, bool ro, umode_t mode, struct mq_attr *attr) { - struct path path __free(path_put) = {}; struct dentry *dentry; + struct file *file; int ret; - dentry = lookup_noperm(&QSTR(name->name), mnt->mnt_root); + dentry = start_creating_noperm(mnt->mnt_root, &QSTR(name->name)); if (IS_ERR(dentry)) return ERR_CAST(dentry); - path.dentry = dentry; - path.mnt = mntget(mnt); - - ret = prepare_open(path.dentry, oflag, ro, mode, name, attr); - if (ret) - return ERR_PTR(ret); + ret = prepare_open(dentry, oflag, ro, mode, name, attr); + file = ERR_PTR(ret); + if (!ret) { + const struct path path = { .mnt = mnt, .dentry = dentry }; + file = dentry_open(&path, oflag, current_cred()); + } - return dentry_open(&path, oflag, current_cred()); + end_creating(dentry); + return file; } static int do_mq_open(const char __user *u_name, int oflag, umode_t mode, @@ -919,9 +920,7 @@ static int do_mq_open(const char __user *u_name, int oflag, umode_t mode, { struct filename *name __free(putname) = NULL;; struct vfsmount *mnt = current->nsproxy->ipc_ns->mq_mnt; - struct dentry *root = mnt->mnt_root; - int fd; - int ro; + int fd, ro; audit_mq_open(oflag, mode, attr); @@ -930,9 +929,7 @@ static int do_mq_open(const char __user *u_name, int oflag, umode_t mode, return PTR_ERR(name); ro = mnt_want_write(mnt); /* we'll drop it in any case */ - inode_lock(d_inode(root)); fd = FD_ADD(O_CLOEXEC, mqueue_file_open(name, mnt, oflag, ro, mode, attr)); - inode_unlock(d_inode(root)); if (!ro) mnt_drop_write(mnt); return fd; @@ -953,7 +950,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) int err; struct filename *name; struct dentry *dentry; - struct inode *inode = NULL; + struct inode *inode; struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; struct vfsmount *mnt = ipc_ns->mq_mnt; @@ -965,26 +962,20 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) err = mnt_want_write(mnt); if (err) goto out_name; - inode_lock_nested(d_inode(mnt->mnt_root), I_MUTEX_PARENT); - dentry = lookup_noperm(&QSTR(name->name), mnt->mnt_root); + dentry = start_removing_noperm(mnt->mnt_root, &QSTR(name->name)); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); - goto out_unlock; + goto out_drop_write; } inode = d_inode(dentry); - if (!inode) { - err = -ENOENT; - } else { - ihold(inode); - err = vfs_unlink(&nop_mnt_idmap, d_inode(dentry->d_parent), - dentry, NULL); - } - dput(dentry); - -out_unlock: - inode_unlock(d_inode(mnt->mnt_root)); + ihold(inode); + err = vfs_unlink(&nop_mnt_idmap, d_inode(mnt->mnt_root), + dentry, NULL); + end_removing(dentry); iput(inode); + +out_drop_write: mnt_drop_write(mnt); out_name: putname(name); |