diff options
| -rw-r--r-- | ipc/mqueue.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 076399ce363a..af1692556c52 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
| @@ -680,26 +680,26 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr) | |||
| 680 | unsigned long total_size; | 680 | unsigned long total_size; |
| 681 | 681 | ||
| 682 | if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0) | 682 | if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0) |
| 683 | return 0; | 683 | return -EINVAL; |
| 684 | if (capable(CAP_SYS_RESOURCE)) { | 684 | if (capable(CAP_SYS_RESOURCE)) { |
| 685 | if (attr->mq_maxmsg > HARD_MSGMAX || | 685 | if (attr->mq_maxmsg > HARD_MSGMAX || |
| 686 | attr->mq_msgsize > HARD_MSGSIZEMAX) | 686 | attr->mq_msgsize > HARD_MSGSIZEMAX) |
| 687 | return 0; | 687 | return -EINVAL; |
| 688 | } else { | 688 | } else { |
| 689 | if (attr->mq_maxmsg > ipc_ns->mq_msg_max || | 689 | if (attr->mq_maxmsg > ipc_ns->mq_msg_max || |
| 690 | attr->mq_msgsize > ipc_ns->mq_msgsize_max) | 690 | attr->mq_msgsize > ipc_ns->mq_msgsize_max) |
| 691 | return 0; | 691 | return -EINVAL; |
| 692 | } | 692 | } |
| 693 | /* check for overflow */ | 693 | /* check for overflow */ |
| 694 | if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg) | 694 | if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg) |
| 695 | return 0; | 695 | return -EOVERFLOW; |
| 696 | mq_treesize = attr->mq_maxmsg * sizeof(struct msg_msg) + | 696 | mq_treesize = attr->mq_maxmsg * sizeof(struct msg_msg) + |
| 697 | min_t(unsigned int, attr->mq_maxmsg, MQ_PRIO_MAX) * | 697 | min_t(unsigned int, attr->mq_maxmsg, MQ_PRIO_MAX) * |
| 698 | sizeof(struct posix_msg_tree_node); | 698 | sizeof(struct posix_msg_tree_node); |
| 699 | total_size = attr->mq_maxmsg * attr->mq_msgsize; | 699 | total_size = attr->mq_maxmsg * attr->mq_msgsize; |
| 700 | if (total_size + mq_treesize < total_size) | 700 | if (total_size + mq_treesize < total_size) |
| 701 | return 0; | 701 | return -EOVERFLOW; |
| 702 | return 1; | 702 | return 0; |
| 703 | } | 703 | } |
| 704 | 704 | ||
| 705 | /* | 705 | /* |
| @@ -714,12 +714,21 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, | |||
| 714 | int ret; | 714 | int ret; |
| 715 | 715 | ||
| 716 | if (attr) { | 716 | if (attr) { |
| 717 | if (!mq_attr_ok(ipc_ns, attr)) { | 717 | ret = mq_attr_ok(ipc_ns, attr); |
| 718 | ret = -EINVAL; | 718 | if (ret) |
| 719 | goto out; | 719 | goto out; |
| 720 | } | ||
| 721 | /* store for use during create */ | 720 | /* store for use during create */ |
| 722 | dentry->d_fsdata = attr; | 721 | dentry->d_fsdata = attr; |
| 722 | } else { | ||
| 723 | struct mq_attr def_attr; | ||
| 724 | |||
| 725 | def_attr.mq_maxmsg = min(ipc_ns->mq_msg_max, | ||
| 726 | ipc_ns->mq_msg_default); | ||
| 727 | def_attr.mq_msgsize = min(ipc_ns->mq_msgsize_max, | ||
| 728 | ipc_ns->mq_msgsize_default); | ||
| 729 | ret = mq_attr_ok(ipc_ns, &def_attr); | ||
| 730 | if (ret) | ||
| 731 | goto out; | ||
| 723 | } | 732 | } |
| 724 | 733 | ||
| 725 | mode &= ~current_umask(); | 734 | mode &= ~current_umask(); |
