summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wright <chrisw@osdl.org>2004-06-17 17:57:18 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-06-17 17:57:18 -0700
commitb1cae1ec2c69ab3ca6ad80a86e16d9a87b12daed (patch)
tree53981f47917ad6747779c8058f0b6e4835f6ac59
parent9d9f6e8b61400f3292be2a85b6aa84d3e47a60c8 (diff)
[PATCH] RLIM: add mq_attr_ok() helper
Add helper function mq_attr_ok() to do mq_attr sanity checking, and do some extra overlow checking. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--ipc/mqueue.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 40a8d414e3ba..a88fc89eaa1c 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -534,6 +534,28 @@ static void remove_notification(struct mqueue_inode_info *info)
info->notify_owner = 0;
}
+static int mq_attr_ok(struct mq_attr *attr)
+{
+ if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
+ return 0;
+ if (capable(CAP_SYS_RESOURCE)) {
+ if (attr->mq_maxmsg > HARD_MSGMAX)
+ return 0;
+ } else {
+ if (attr->mq_maxmsg > msg_max ||
+ attr->mq_msgsize > msgsize_max)
+ return 0;
+ }
+ /* check for overflow */
+ if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
+ return 0;
+ if ((unsigned long)(attr->mq_maxmsg * attr->mq_msgsize) +
+ (attr->mq_maxmsg * sizeof (struct msg_msg *)) <
+ (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize))
+ return 0;
+ return 1;
+}
+
/*
* Invoked when creating a new queue via sys_mq_open
*/
@@ -547,17 +569,8 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
if (u_attr != NULL) {
if (copy_from_user(&attr, u_attr, sizeof(attr)))
return ERR_PTR(-EFAULT);
-
- if (attr.mq_maxmsg <= 0 || attr.mq_msgsize <= 0)
+ if (!mq_attr_ok(&attr))
return ERR_PTR(-EINVAL);
- if (capable(CAP_SYS_RESOURCE)) {
- if (attr.mq_maxmsg > HARD_MSGMAX)
- return ERR_PTR(-EINVAL);
- } else {
- if (attr.mq_maxmsg > msg_max ||
- attr.mq_msgsize > msgsize_max)
- return ERR_PTR(-EINVAL);
- }
/* store for use during create */
dentry->d_fsdata = &attr;
}