Re: message queue limits

From: Marcelo Tosatti
Date: Fri Apr 16 2004 - 09:42:20 EST


On Thu, Apr 15, 2004 at 05:55:57PM +0200, Manfred Spraul wrote:
> Marcelo Tosatti wrote:
>
> >On Sun, Apr 11, 2004 at 10:48:28PM -0700, Ulrich Drepper wrote:
> >
> >
> >>Something has to change in the way message queues are created.
> >>Currently it is possible for an unprivileged user to exhaust all mq
> >>slots so that only root can create a few more. Any other unprivileged
> >>user has no change to create anything.
> >>
> >>I think it is necessary to create a per-user limit instead of a
> >>system-wide limit.
> >>
> >>
> >
> >Manfred,
> >
> >Are you looking into this already? I'm doing so for queued signals
> >(max_nr_signals global limit).
> >
> >
> Ahm, not really. Actually:
> I had noticed the queued signal report on lkml and decided to wait for
> the patch that fixes the signal limit. I assume I'll be able to clone
> the fix and apply it to ipc/mqueue.c.

Ulrich, Andrew, Manfred,

This should be working, but for some reason rlim[RLIMIT_MSGQUEUE].rlim_cur of
all tasks is 0, remembering it sets init_tasks's value at ipc/mqueue.c's __init function:

init_task.rlim[RLIMIT_MSGQUEUE].rlim_cur = 64;
init_task.rlim[RLIMIT_MSGQUEUE].rlim_max = 64;

Probably something stupid.

It may be interesting to move the mqueue pending count to the new task at "setuid()",

diff -Nur linux-2.6.5.org/include/linux/sched.h linux-2.6.5/include/linux/sched.h
--- linux-2.6.5.org/include/linux/sched.h 2004-04-15 19:20:57.000000000 -0300
+++ linux-2.6.5/include/linux/sched.h 2004-04-15 20:25:18.000000000 -0300
@@ -310,6 +310,9 @@
atomic_t __count; /* reference count */
atomic_t processes; /* How many processes does this user have? */
atomic_t files; /* How many open files does this user have? */
+ atomic_t signal_pending; /* How many pending signals does this user have? */
+ /* protected by mq_lock */
+ int msg_queues; /* How many message queues does this user have? */

/* Hash table maintenance information */
struct list_head uidhash_list;
diff -Nur linux-2.6.5.org/ipc/mqueue.c linux-2.6.5/ipc/mqueue.c
--- linux-2.6.5.org/ipc/mqueue.c 2004-04-15 19:20:57.000000000 -0300
+++ linux-2.6.5/ipc/mqueue.c 2004-04-16 10:07:13.000000000 -0300
@@ -43,7 +43,7 @@
#define CTL_MSGSIZEMAX 4

/* default values */
-#define DFLT_QUEUESMAX 64 /* max number of message queues */
+#define DFLT_QUEUESMAX 256 /* max number of message queues */
#define DFLT_MSGMAX 40 /* max number of messages in each queue */
#define HARD_MSGMAX (131072/sizeof(void*))
#define DFLT_MSGSIZEMAX 16384 /* max message size */
@@ -217,6 +217,14 @@

spin_lock(&mq_lock);
queues_count--;
+
+ /*
+ * If we create mqueues, then "setuid()", and destroy
+ * mqueues later on (with the new uid), msg_queues
+ * can get negative.
+ */
+ if (current->user->msg_queues > 0)
+ current->user->msg_queues--;
spin_unlock(&mq_lock);
}

@@ -225,13 +233,16 @@
{
struct inode *inode;
int error;
+ struct task_struct *p = current;

spin_lock(&mq_lock);
- if (queues_count >= queues_max && !capable(CAP_SYS_RESOURCE)) {
+ if (queues_count >= queues_max && !capable(CAP_SYS_RESOURCE) &&
+ p->user->msg_queues >= p->rlim[RLIMIT_MSGQUEUE].rlim_cur)
error = -ENOSPC;
goto out_lock;
- }
+
queues_count++;
+ p->user->msg_queues++;
spin_unlock(&mq_lock);

inode = mqueue_get_inode(dir->i_sb, mode);
@@ -239,6 +250,7 @@
error = -ENOMEM;
spin_lock(&mq_lock);
queues_count--;
+ p->user->msg_queues--;
goto out_lock;
}

@@ -1202,6 +1214,9 @@
/* internal initialization - not common for vfs */
queues_count = 0;
spin_lock_init(&mq_lock);
+
+ init_task.rlim[RLIMIT_MSGQUEUE].rlim_cur = 64;
+ init_task.rlim[RLIMIT_MSGQUEUE].rlim_max = 64;

return 0;

diff -Nur linux-2.6.5.org/kernel/user.c linux-2.6.5/kernel/user.c
--- linux-2.6.5.org/kernel/user.c 2004-04-15 11:14:05.000000000 -0300
+++ linux-2.6.5/kernel/user.c 2004-04-16 10:14:00.000000000 -0300
@@ -30,7 +30,9 @@
struct user_struct root_user = {
.__count = ATOMIC_INIT(1),
.processes = ATOMIC_INIT(1),
- .files = ATOMIC_INIT(0)
+ .files = ATOMIC_INIT(0),
+ .signal_pending = ATOMIC_INIT(0),
+ .msg_queues = 0
};

/*
@@ -98,6 +100,9 @@
atomic_set(&new->processes, 0);
atomic_set(&new->files, 0);

+ new->msg_queues = 0;
+
+
/*
* Before adding this, check whether we raced
* on adding the same user already..
--- linux-2.6.5.org/include/asm-i386/resource.h 2004-04-15 11:13:28.000000000 -0300
+++ linux-2.6.5/include/asm-i386/resource.h 2004-04-15 19:26:25.000000000 -0300
@@ -16,8 +16,10 @@
#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
#define RLIMIT_AS 9 /* address space limit */
#define RLIMIT_LOCKS 10 /* maximum file locks held */
+#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
+#define RLIMIT_MSGQUEUE 12 /* max number of POSIX msg queues */

-#define RLIM_NLIMITS 11
+#define RLIM_NLIMITS 13

/*
* SuS says limits have to be unsigned.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/