|
@@ -599,15 +599,16 @@ static int mq_attr_ok(struct mq_attr *attr)
|
|
|
static struct file *do_create(struct dentry *dir, struct dentry *dentry,
|
|
|
int oflag, mode_t mode, struct mq_attr __user *u_attr)
|
|
|
{
|
|
|
- struct file *filp;
|
|
|
struct mq_attr attr;
|
|
|
int ret;
|
|
|
|
|
|
- if (u_attr != NULL) {
|
|
|
+ if (u_attr) {
|
|
|
+ ret = -EFAULT;
|
|
|
if (copy_from_user(&attr, u_attr, sizeof(attr)))
|
|
|
- return ERR_PTR(-EFAULT);
|
|
|
+ goto out;
|
|
|
+ ret = -EINVAL;
|
|
|
if (!mq_attr_ok(&attr))
|
|
|
- return ERR_PTR(-EINVAL);
|
|
|
+ goto out;
|
|
|
/* store for use during create */
|
|
|
dentry->d_fsdata = &attr;
|
|
|
}
|
|
@@ -616,13 +617,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
|
|
|
ret = vfs_create(dir->d_inode, dentry, mode, NULL);
|
|
|
dentry->d_fsdata = NULL;
|
|
|
if (ret)
|
|
|
- return ERR_PTR(ret);
|
|
|
+ goto out;
|
|
|
|
|
|
- filp = dentry_open(dentry, mqueue_mnt, oflag);
|
|
|
- if (!IS_ERR(filp))
|
|
|
- dget(dentry);
|
|
|
+ return dentry_open(dentry, mqueue_mnt, oflag);
|
|
|
|
|
|
- return filp;
|
|
|
+out:
|
|
|
+ dput(dentry);
|
|
|
+ mntput(mqueue_mnt);
|
|
|
+ return ERR_PTR(ret);
|
|
|
}
|
|
|
|
|
|
/* Opens existing queue */
|
|
@@ -630,20 +632,20 @@ static struct file *do_open(struct dentry *dentry, int oflag)
|
|
|
{
|
|
|
static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
|
|
|
MAY_READ | MAY_WRITE };
|
|
|
- struct file *filp;
|
|
|
|
|
|
- if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
|
|
|
+ if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
|
|
|
+ dput(dentry);
|
|
|
+ mntput(mqueue_mnt);
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
+ }
|
|
|
|
|
|
- if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL))
|
|
|
+ if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) {
|
|
|
+ dput(dentry);
|
|
|
+ mntput(mqueue_mnt);
|
|
|
return ERR_PTR(-EACCES);
|
|
|
+ }
|
|
|
|
|
|
- filp = dentry_open(dentry, mqueue_mnt, oflag);
|
|
|
-
|
|
|
- if (!IS_ERR(filp))
|
|
|
- dget(dentry);
|
|
|
-
|
|
|
- return filp;
|
|
|
+ return dentry_open(dentry, mqueue_mnt, oflag);
|
|
|
}
|
|
|
|
|
|
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
|
|
@@ -671,17 +673,20 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
|
|
|
|
|
|
if (oflag & O_CREAT) {
|
|
|
if (dentry->d_inode) { /* entry already exists */
|
|
|
- filp = (oflag & O_EXCL) ? ERR_PTR(-EEXIST) :
|
|
|
- do_open(dentry, oflag);
|
|
|
+ error = -EEXIST;
|
|
|
+ if (oflag & O_EXCL)
|
|
|
+ goto out;
|
|
|
+ filp = do_open(dentry, oflag);
|
|
|
} else {
|
|
|
filp = do_create(mqueue_mnt->mnt_root, dentry,
|
|
|
oflag, mode, u_attr);
|
|
|
}
|
|
|
- } else
|
|
|
- filp = (dentry->d_inode) ? do_open(dentry, oflag) :
|
|
|
- ERR_PTR(-ENOENT);
|
|
|
-
|
|
|
- dput(dentry);
|
|
|
+ } else {
|
|
|
+ error = -ENOENT;
|
|
|
+ if (!dentry->d_inode)
|
|
|
+ goto out;
|
|
|
+ filp = do_open(dentry, oflag);
|
|
|
+ }
|
|
|
|
|
|
if (IS_ERR(filp)) {
|
|
|
error = PTR_ERR(filp);
|
|
@@ -692,8 +697,10 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
|
|
|
fd_install(fd, filp);
|
|
|
goto out_upsem;
|
|
|
|
|
|
-out_putfd:
|
|
|
+out:
|
|
|
+ dput(dentry);
|
|
|
mntput(mqueue_mnt);
|
|
|
+out_putfd:
|
|
|
put_unused_fd(fd);
|
|
|
out_err:
|
|
|
fd = error;
|