summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-12-01 17:43:43 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2018-01-05 11:54:35 -0500
commit05c1b29038acb05a52dc113ae2ab646f9a92bbfd (patch)
treee4fe8eca9a7858646bd79af655b8535f5b84361f /ipc
parentaf4a5372e4166e8f13cb5cd36d936a0f56bc8418 (diff)
mqueue: fold mq_attr_ok() into mqueue_get_inode()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/mqueue.c71
1 files changed, 21 insertions, 50 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index fee67559acbe..a2483524b633 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -270,13 +270,30 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
270 * that means the min(mq_maxmsg, max_priorities) * struct 270 * that means the min(mq_maxmsg, max_priorities) * struct
271 * posix_msg_tree_node. 271 * posix_msg_tree_node.
272 */ 272 */
273
274 ret = -EINVAL;
275 if (info->attr.mq_maxmsg <= 0 || info->attr.mq_msgsize <= 0)
276 goto out_inode;
277 if (capable(CAP_SYS_RESOURCE)) {
278 if (info->attr.mq_maxmsg > HARD_MSGMAX ||
279 info->attr.mq_msgsize > HARD_MSGSIZEMAX)
280 goto out_inode;
281 } else {
282 if (info->attr.mq_maxmsg > ipc_ns->mq_msg_max ||
283 info->attr.mq_msgsize > ipc_ns->mq_msgsize_max)
284 goto out_inode;
285 }
286 ret = -EOVERFLOW;
287 /* check for overflow */
288 if (info->attr.mq_msgsize > ULONG_MAX/info->attr.mq_maxmsg)
289 goto out_inode;
273 mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) + 290 mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
274 min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) * 291 min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
275 sizeof(struct posix_msg_tree_node); 292 sizeof(struct posix_msg_tree_node);
276 293 mq_bytes = info->attr.mq_maxmsg * info->attr.mq_msgsize;
277 mq_bytes = mq_treesize + (info->attr.mq_maxmsg * 294 if (mq_bytes + mq_treesize < mq_bytes)
278 info->attr.mq_msgsize); 295 goto out_inode;
279 296 mq_bytes += mq_treesize;
280 spin_lock(&mq_lock); 297 spin_lock(&mq_lock);
281 if (u->mq_bytes + mq_bytes < u->mq_bytes || 298 if (u->mq_bytes + mq_bytes < u->mq_bytes ||
282 u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) { 299 u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
@@ -696,34 +713,6 @@ static void remove_notification(struct mqueue_inode_info *info)
696 info->notify_user_ns = NULL; 713 info->notify_user_ns = NULL;
697} 714}
698 715
699static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
700{
701 int mq_treesize;
702 unsigned long total_size;
703
704 if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
705 return -EINVAL;
706 if (capable(CAP_SYS_RESOURCE)) {
707 if (attr->mq_maxmsg > HARD_MSGMAX ||
708 attr->mq_msgsize > HARD_MSGSIZEMAX)
709 return -EINVAL;
710 } else {
711 if (attr->mq_maxmsg > ipc_ns->mq_msg_max ||
712 attr->mq_msgsize > ipc_ns->mq_msgsize_max)
713 return -EINVAL;
714 }
715 /* check for overflow */
716 if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
717 return -EOVERFLOW;
718 mq_treesize = attr->mq_maxmsg * sizeof(struct msg_msg) +
719 min_t(unsigned int, attr->mq_maxmsg, MQ_PRIO_MAX) *
720 sizeof(struct posix_msg_tree_node);
721 total_size = attr->mq_maxmsg * attr->mq_msgsize;
722 if (total_size + mq_treesize < total_size)
723 return -EOVERFLOW;
724 return 0;
725}
726
727/* 716/*
728 * Invoked when creating a new queue via sys_mq_open 717 * Invoked when creating a new queue via sys_mq_open
729 */ 718 */
@@ -731,24 +720,6 @@ static int do_create(struct ipc_namespace *ipc_ns, struct inode *dir,
731 struct path *path, int oflag, umode_t mode, 720 struct path *path, int oflag, umode_t mode,
732 struct mq_attr *attr) 721 struct mq_attr *attr)
733{ 722{
734 int ret;
735
736 if (attr) {
737 ret = mq_attr_ok(ipc_ns, attr);
738 if (ret)
739 return ret;
740 } else {
741 struct mq_attr def_attr;
742
743 def_attr.mq_maxmsg = min(ipc_ns->mq_msg_max,
744 ipc_ns->mq_msg_default);
745 def_attr.mq_msgsize = min(ipc_ns->mq_msgsize_max,
746 ipc_ns->mq_msgsize_default);
747 ret = mq_attr_ok(ipc_ns, &def_attr);
748 if (ret)
749 return ret;
750 }
751
752 return vfs_mkobj(path->dentry, mode & ~current_umask(), 723 return vfs_mkobj(path->dentry, mode & ~current_umask(),
753 mqueue_create_attr, attr); 724 mqueue_create_attr, attr);
754} 725}