do_mq_open(): move all work prior to dentry_open() into a helper

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2017-12-01 17:51:39 -05:00
parent 05c1b29038
commit 066cc813e9
1 changed files with 31 additions and 46 deletions

View File

@ -713,34 +713,44 @@ static void remove_notification(struct mqueue_inode_info *info)
info->notify_user_ns = NULL; info->notify_user_ns = NULL;
} }
/* static int prepare_open(struct dentry *dentry, int oflag, int ro,
* Invoked when creating a new queue via sys_mq_open umode_t mode, struct filename *name,
*/
static int do_create(struct ipc_namespace *ipc_ns, struct inode *dir,
struct path *path, int oflag, umode_t mode,
struct mq_attr *attr) struct mq_attr *attr)
{
return vfs_mkobj(path->dentry, mode & ~current_umask(),
mqueue_create_attr, attr);
}
/* Opens existing queue */
static int do_open(struct path *path, int oflag)
{ {
static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
MAY_READ | MAY_WRITE }; MAY_READ | MAY_WRITE };
int acc; int acc;
if (oflag & O_CREAT) {
if (d_really_is_positive(dentry)) { /* entry already exists */
audit_inode(name, dentry, 0);
if (oflag & O_EXCL)
return -EEXIST;
} else {
if (ro)
return ro;
audit_inode_parent_hidden(name, dentry->d_parent);
return vfs_mkobj(dentry, mode & ~current_umask(),
mqueue_create_attr, attr);
}
} else {
if (d_really_is_negative(dentry)) {
return -ENOENT;
} else {
audit_inode(name, dentry, 0);
}
}
if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
return -EINVAL; return -EINVAL;
acc = oflag2acc[oflag & O_ACCMODE]; acc = oflag2acc[oflag & O_ACCMODE];
return inode_permission(d_inode(path->dentry), acc); return inode_permission(d_inode(dentry), acc);
} }
static int do_mq_open(const char __user *u_name, int oflag, umode_t mode, static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
struct mq_attr *attr) struct mq_attr *attr)
{ {
struct path path; struct path path;
struct file *filp;
struct filename *name; struct filename *name;
int fd, error; int fd, error;
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
@ -767,39 +777,14 @@ static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
} }
path.mnt = mntget(mnt); path.mnt = mntget(mnt);
if (oflag & O_CREAT) { error = prepare_open(path.dentry, oflag, ro, mode, name, attr);
if (d_really_is_positive(path.dentry)) { /* entry already exists */ if (!error) {
audit_inode(name, path.dentry, 0); struct file *file = dentry_open(&path, oflag, current_cred());
if (oflag & O_EXCL) if (!IS_ERR(file))
error = -EEXIST; fd_install(fd, file);
else else
error = do_open(&path, oflag); error = PTR_ERR(file);
} else {
if (ro) {
error = ro;
} else {
audit_inode_parent_hidden(name, root);
error = do_create(ipc_ns, d_inode(root), &path,
oflag, mode, attr);
} }
}
} else {
if (d_really_is_negative(path.dentry)) {
error = -ENOENT;
} else {
audit_inode(name, path.dentry, 0);
error = do_open(&path, oflag);
}
}
if (error)
goto out;
filp = dentry_open(&path, oflag, current_cred());
if (!IS_ERR(filp))
fd_install(fd, filp);
else
error = PTR_ERR(filp);
out:
path_put(&path); path_put(&path);
out_putfd: out_putfd:
if (error) { if (error) {