OSDN Git Service

mqueue: fold mq_attr_ok() into mqueue_get_inode()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 1 Dec 2017 22:43:43 +0000 (17:43 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 5 Jan 2018 16:54:35 +0000 (11:54 -0500)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
ipc/mqueue.c

index fee6755..a248352 100644 (file)
@@ -270,13 +270,30 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
                 * that means the min(mq_maxmsg, max_priorities) * struct
                 * posix_msg_tree_node.
                 */
+
+               ret = -EINVAL;
+               if (info->attr.mq_maxmsg <= 0 || info->attr.mq_msgsize <= 0)
+                       goto out_inode;
+               if (capable(CAP_SYS_RESOURCE)) {
+                       if (info->attr.mq_maxmsg > HARD_MSGMAX ||
+                           info->attr.mq_msgsize > HARD_MSGSIZEMAX)
+                               goto out_inode;
+               } else {
+                       if (info->attr.mq_maxmsg > ipc_ns->mq_msg_max ||
+                                       info->attr.mq_msgsize > ipc_ns->mq_msgsize_max)
+                               goto out_inode;
+               }
+               ret = -EOVERFLOW;
+               /* check for overflow */
+               if (info->attr.mq_msgsize > ULONG_MAX/info->attr.mq_maxmsg)
+                       goto out_inode;
                mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
                        min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
                        sizeof(struct posix_msg_tree_node);
-
-               mq_bytes = mq_treesize + (info->attr.mq_maxmsg *
-                                         info->attr.mq_msgsize);
-
+               mq_bytes = info->attr.mq_maxmsg * info->attr.mq_msgsize;
+               if (mq_bytes + mq_treesize < mq_bytes)
+                       goto out_inode;
+               mq_bytes += mq_treesize;
                spin_lock(&mq_lock);
                if (u->mq_bytes + mq_bytes < u->mq_bytes ||
                    u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
@@ -696,34 +713,6 @@ static void remove_notification(struct mqueue_inode_info *info)
        info->notify_user_ns = NULL;
 }
 
-static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
-{
-       int mq_treesize;
-       unsigned long total_size;
-
-       if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
-               return -EINVAL;
-       if (capable(CAP_SYS_RESOURCE)) {
-               if (attr->mq_maxmsg > HARD_MSGMAX ||
-                   attr->mq_msgsize > HARD_MSGSIZEMAX)
-                       return -EINVAL;
-       } else {
-               if (attr->mq_maxmsg > ipc_ns->mq_msg_max ||
-                               attr->mq_msgsize > ipc_ns->mq_msgsize_max)
-                       return -EINVAL;
-       }
-       /* check for overflow */
-       if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
-               return -EOVERFLOW;
-       mq_treesize = attr->mq_maxmsg * sizeof(struct msg_msg) +
-               min_t(unsigned int, attr->mq_maxmsg, MQ_PRIO_MAX) *
-               sizeof(struct posix_msg_tree_node);
-       total_size = attr->mq_maxmsg * attr->mq_msgsize;
-       if (total_size + mq_treesize < total_size)
-               return -EOVERFLOW;
-       return 0;
-}
-
 /*
  * Invoked when creating a new queue via sys_mq_open
  */
@@ -731,24 +720,6 @@ static int do_create(struct ipc_namespace *ipc_ns, struct inode *dir,
                        struct path *path, int oflag, umode_t mode,
                        struct mq_attr *attr)
 {
-       int ret;
-
-       if (attr) {
-               ret = mq_attr_ok(ipc_ns, attr);
-               if (ret)
-                       return ret;
-       } else {
-               struct mq_attr def_attr;
-
-               def_attr.mq_maxmsg = min(ipc_ns->mq_msg_max,
-                                        ipc_ns->mq_msg_default);
-               def_attr.mq_msgsize = min(ipc_ns->mq_msgsize_max,
-                                         ipc_ns->mq_msgsize_default);
-               ret = mq_attr_ok(ipc_ns, &def_attr);
-               if (ret)
-                       return ret;
-       }
-
        return vfs_mkobj(path->dentry, mode & ~current_umask(),
                        mqueue_create_attr, attr);
 }