Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 05c1b290 authored by Al Viro's avatar Al Viro
Browse files

mqueue: fold mq_attr_ok() into mqueue_get_inode()



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent af4a5372
Loading
Loading
Loading
Loading
+21 −50
Original line number Diff line number Diff line
@@ -270,13 +270,30 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
		 * that means the min(mq_maxmsg, max_priorities) * struct
		 * posix_msg_tree_node.
		 */

		ret = -EINVAL;
		if (info->attr.mq_maxmsg <= 0 || info->attr.mq_msgsize <= 0)
			goto out_inode;
		if (capable(CAP_SYS_RESOURCE)) {
			if (info->attr.mq_maxmsg > HARD_MSGMAX ||
			    info->attr.mq_msgsize > HARD_MSGSIZEMAX)
				goto out_inode;
		} else {
			if (info->attr.mq_maxmsg > ipc_ns->mq_msg_max ||
					info->attr.mq_msgsize > ipc_ns->mq_msgsize_max)
				goto out_inode;
		}
		ret = -EOVERFLOW;
		/* check for overflow */
		if (info->attr.mq_msgsize > ULONG_MAX/info->attr.mq_maxmsg)
			goto out_inode;
		mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
			min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
			sizeof(struct posix_msg_tree_node);

		mq_bytes = mq_treesize + (info->attr.mq_maxmsg *
					  info->attr.mq_msgsize);

		mq_bytes = info->attr.mq_maxmsg * info->attr.mq_msgsize;
		if (mq_bytes + mq_treesize < mq_bytes)
			goto out_inode;
		mq_bytes += mq_treesize;
		spin_lock(&mq_lock);
		if (u->mq_bytes + mq_bytes < u->mq_bytes ||
		    u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
@@ -696,34 +713,6 @@ static void remove_notification(struct mqueue_inode_info *info)
	info->notify_user_ns = NULL;
}

static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
{
	int mq_treesize;
	unsigned long total_size;

	if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
		return -EINVAL;
	if (capable(CAP_SYS_RESOURCE)) {
		if (attr->mq_maxmsg > HARD_MSGMAX ||
		    attr->mq_msgsize > HARD_MSGSIZEMAX)
			return -EINVAL;
	} else {
		if (attr->mq_maxmsg > ipc_ns->mq_msg_max ||
				attr->mq_msgsize > ipc_ns->mq_msgsize_max)
			return -EINVAL;
	}
	/* check for overflow */
	if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
		return -EOVERFLOW;
	mq_treesize = attr->mq_maxmsg * sizeof(struct msg_msg) +
		min_t(unsigned int, attr->mq_maxmsg, MQ_PRIO_MAX) *
		sizeof(struct posix_msg_tree_node);
	total_size = attr->mq_maxmsg * attr->mq_msgsize;
	if (total_size + mq_treesize < total_size)
		return -EOVERFLOW;
	return 0;
}

/*
 * Invoked when creating a new queue via sys_mq_open
 */
@@ -731,24 +720,6 @@ static int do_create(struct ipc_namespace *ipc_ns, struct inode *dir,
			struct path *path, int oflag, umode_t mode,
			struct mq_attr *attr)
{
	int ret;

	if (attr) {
		ret = mq_attr_ok(ipc_ns, attr);
		if (ret)
			return ret;
	} else {
		struct mq_attr def_attr;

		def_attr.mq_maxmsg = min(ipc_ns->mq_msg_max,
					 ipc_ns->mq_msg_default);
		def_attr.mq_msgsize = min(ipc_ns->mq_msgsize_max,
					  ipc_ns->mq_msgsize_default);
		ret = mq_attr_ok(ipc_ns, &def_attr);
		if (ret)
			return ret;
	}

	return vfs_mkobj(path->dentry, mode & ~current_umask(),
			mqueue_create_attr, attr);
}