Commit 113289cc086f80f28acd06f160a7c6423cdd4191

Authored by Doug Ledford
Committed by Linus Torvalds
1 parent 2c12ea498f

ipc/mqueue: strengthen checks on mqueue creation

We already check the mq attr struct if it's passed in, but now that the
admin can set system wide defaults separate from maximums, it's actually
possible to set the defaults to something that would overflow.  So, if
there is no attr struct passed in to the open call, check the default
values.

While we are at it, simplify mq_attr_ok() by making it return 0 or an
error condition, so that way if we add more tests to it later, we have the
option of what error should be returned instead of the calling location
having to pick a possibly inaccurate error code.

[akpm@linux-foundation.org: s/ENOMEM/EOVERFLOW/]
Signed-off-by: Doug Ledford <dledford@redhat.com>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Manfred Spraul <manfred@colorfullife.com>
Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 18 additions and 9 deletions Side-by-side Diff

... ... @@ -680,26 +680,26 @@
680 680 unsigned long total_size;
681 681  
682 682 if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
683   - return 0;
  683 + return -EINVAL;
684 684 if (capable(CAP_SYS_RESOURCE)) {
685 685 if (attr->mq_maxmsg > HARD_MSGMAX ||
686 686 attr->mq_msgsize > HARD_MSGSIZEMAX)
687   - return 0;
  687 + return -EINVAL;
688 688 } else {
689 689 if (attr->mq_maxmsg > ipc_ns->mq_msg_max ||
690 690 attr->mq_msgsize > ipc_ns->mq_msgsize_max)
691   - return 0;
  691 + return -EINVAL;
692 692 }
693 693 /* check for overflow */
694 694 if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
695   - return 0;
  695 + return -EOVERFLOW;
696 696 mq_treesize = attr->mq_maxmsg * sizeof(struct msg_msg) +
697 697 min_t(unsigned int, attr->mq_maxmsg, MQ_PRIO_MAX) *
698 698 sizeof(struct posix_msg_tree_node);
699 699 total_size = attr->mq_maxmsg * attr->mq_msgsize;
700 700 if (total_size + mq_treesize < total_size)
701   - return 0;
702   - return 1;
  701 + return -EOVERFLOW;
  702 + return 0;
703 703 }
704 704  
705 705 /*
706 706  
707 707  
... ... @@ -714,12 +714,21 @@
714 714 int ret;
715 715  
716 716 if (attr) {
717   - if (!mq_attr_ok(ipc_ns, attr)) {
718   - ret = -EINVAL;
  717 + ret = mq_attr_ok(ipc_ns, attr);
  718 + if (ret)
719 719 goto out;
720   - }
721 720 /* store for use during create */
722 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 734 mode &= ~current_umask();