mqueue: fold mq_attr_ok() into mqueue_get_inode()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2017-12-01 17:43:43 -05:00
parent af4a5372e4
commit 05c1b29038

View 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);
}