diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-12-01 17:43:43 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-01-05 11:54:35 -0500 |
commit | 05c1b29038acb05a52dc113ae2ab646f9a92bbfd (patch) | |
tree | e4fe8eca9a7858646bd79af655b8535f5b84361f /ipc | |
parent | af4a5372e4166e8f13cb5cd36d936a0f56bc8418 (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.c | 71 |
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 | ||
699 | static 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 | } |