2004-04-19 21:27:29

by Marcelo Tosatti

[permalink] [raw]
Subject: [PATCH] per-user signal pending and message queue limits

(forgot the subject on the first message)

Andrew,

Here goes the signal pending & POSIX mqueue's per-uid limit patch.

Initialization has been moved to include/asm-i386/resource.h, as you suggested.

The global mqueue limit has been increased to 256 (64 per user), and the global
signal pending limit to 4096 (1024 per user).

This has been well tested.

If you are OK with it for inclusion (-mm) I'll generate the arch-dependant
changes for the other architectures.

Comments are welcome.

diff -Nur --show-c-function linux-2.6.5.org/arch/i386/kernel/init_task.c linux-2.6.5/arch/i386/kernel/init_task.c
--- linux-2.6.5.org/arch/i386/kernel/init_task.c 2004-04-15 11:13:32.000000000 -0300
+++ linux-2.6.5/arch/i386/kernel/init_task.c 2004-04-17 01:25:59.000000000 -0300
@@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/fs.h>
+#include <linux/mqueue.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>
diff -Nur --show-c-function linux-2.6.5.org/include/asm-i386/resource.h linux-2.6.5/include/asm-i386/resource.h
--- 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-17 02:36:31.000000000 -0300
@@ -16,8 +16,11 @@
#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 13

-#define RLIM_NLIMITS 11

/*
* SuS says limits have to be unsigned.
@@ -40,6 +43,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { IR_SIGNALS, IR_SIGNALS }, \
+ { IR_MSGQUEUE, IR_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.5.org/include/linux/mqueue.h linux-2.6.5/include/linux/mqueue.h
--- linux-2.6.5.org/include/linux/mqueue.h 2004-04-15 19:20:57.000000000 -0300
+++ linux-2.6.5/include/linux/mqueue.h 2004-04-17 02:36:25.000000000 -0300
@@ -21,6 +21,8 @@
#include <linux/types.h>

#define MQ_PRIO_MAX 32768
+#define DFLT_QUEUESMAX 256
+#define IR_MSGQUEUE (DFLT_QUEUESMAX / 4)

struct mq_attr {
long mq_flags; /* message queue flags */
diff -Nur --show-c-function 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-17 03:48:31.000000000 -0300
@@ -281,6 +281,7 @@ struct signal_struct {
int leader;

struct tty_struct *tty; /* NULL if no tty */
+ atomic_t sigpending;
};

/*
@@ -310,6 +311,9 @@ struct user_struct {
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 --show-c-function linux-2.6.5.org/include/linux/signal.h linux-2.6.5/include/linux/signal.h
--- linux-2.6.5.org/include/linux/signal.h 2004-04-15 11:13:23.000000000 -0300
+++ linux-2.6.5/include/linux/signal.h 2004-04-17 02:34:53.000000000 -0300
@@ -7,6 +7,10 @@
#include <asm/siginfo.h>

#ifdef __KERNEL__
+
+#define MAX_QUEUED_SIGNALS 4096
+#define IR_SIGNALS (MAX_QUEUED_SIGNALS/4)
+
/*
* Real Time signals may be queued.
*/
diff -Nur --show-c-function 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-19 16:43:15.539968016 -0300
@@ -43,7 +43,6 @@
#define CTL_MSGSIZEMAX 4

/* default values */
-#define DFLT_QUEUESMAX 64 /* 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 +216,14 @@ static void mqueue_delete_inode(struct i

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 +232,18 @@ static int mqueue_create(struct inode *d
{
struct inode *inode;
int error;
+ struct task_struct *p = current;

spin_lock(&mq_lock);
- if (queues_count >= queues_max && !capable(CAP_SYS_RESOURCE)) {
+ if (!capable(CAP_SYS_RESOURCE) && (queues_count >= queues_max ||
+ 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 +251,7 @@ static int mqueue_create(struct inode *d
error = -ENOMEM;
spin_lock(&mq_lock);
queues_count--;
+ p->user->msg_queues--;
goto out_lock;
}

diff -Nur --show-c-function linux-2.6.5.org/kernel/signal.c linux-2.6.5/kernel/signal.c
--- linux-2.6.5.org/kernel/signal.c 2004-04-15 19:20:57.000000000 -0300
+++ linux-2.6.5/kernel/signal.c 2004-04-19 17:59:40.441956968 -0300
@@ -32,7 +32,7 @@
static kmem_cache_t *sigqueue_cachep;

atomic_t nr_queued_signals;
-int max_queued_signals = 1024;
+int max_queued_signals = MAX_QUEUED_SIGNALS;

/*
* In POSIX a signal is sent either to a specific thread (Linux task)
@@ -268,10 +268,13 @@ struct sigqueue *__sigqueue_alloc(void)
{
struct sigqueue *q = 0;

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&nr_queued_signals) < max_queued_signals &&
+ atomic_read(&current->user->signal_pending) <=
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
if (q) {
atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
INIT_LIST_HEAD(&q->list);
q->flags = 0;
q->lock = 0;
@@ -285,6 +288,14 @@ static inline void __sigqueue_free(struc
return;
kmem_cache_free(sigqueue_cachep, q);
atomic_dec(&nr_queued_signals);
+
+ /*
+ * Decrease per-user sigpending count. Check
+ * for negative value, we might have done setuid()
+ * with pending signals.
+ */
+ if (atomic_read(&current->user->signal_pending) > 0)
+ atomic_dec(&current->user->signal_pending);
}

static void flush_sigqueue(struct sigpending *queue)
@@ -701,11 +712,15 @@ static int send_signal(int sig, struct s
make sure at least one signal gets delivered and don't
pass on the info struct. */

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&nr_queued_signals) < max_queued_signals &&
+ atomic_read(&current->user->signal_pending) <=
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);

if (q) {
atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
+
q->flags = 0;
list_add_tail(&q->list, &signals->list);
switch ((unsigned long) info) {
diff -Nur --show-c-function 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-19 15:08:14.000000000 -0300
@@ -30,7 +30,9 @@ static spinlock_t uidhash_lock = SPIN_LO
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
};

/*
@@ -97,6 +99,9 @@ struct user_struct * alloc_uid(uid_t uid
atomic_set(&new->__count, 1);
atomic_set(&new->processes, 0);
atomic_set(&new->files, 0);
+ atomic_set(&new->signal_pending, 0);
+
+ new->msg_queues = 0;

/*
* Before adding this, check whether we raced

----- End forwarded message -----


2004-04-19 22:50:19

by Jakub Jelinek

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

On Mon, Apr 19, 2004 at 06:28:10PM -0300, Marcelo Tosatti wrote:
> Andrew,
>
> Here goes the signal pending & POSIX mqueue's per-uid limit patch.
>
> Initialization has been moved to include/asm-i386/resource.h, as you suggested.
>
> The global mqueue limit has been increased to 256 (64 per user), and the global
> signal pending limit to 4096 (1024 per user).
>
> This has been well tested.
>
> If you are OK with it for inclusion (-mm) I'll generate the arch-dependant
> changes for the other architectures.
>
> Comments are welcome.

I wonder if it is a good idea to base mqueue limitation on the number of
message queues and not take into account how big they are.
64 message queues with 1 byte msgsize and 1 maxmsg is certainly quite
harmless and the system could have even more queues for such a user,
while 64 message queues with 16K msgsize (current default) and 40 maxmsg
(also default) eats ~ 40M of kernel memory.

Jakub

2004-04-19 22:57:20

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

Marcelo Tosatti <[email protected]> wrote:
>
> (forgot the subject on the first message)
>
> Andrew,
>
> Here goes the signal pending & POSIX mqueue's per-uid limit patch.
>
> Initialization has been moved to include/asm-i386/resource.h, as you suggested.
>
> The global mqueue limit has been increased to 256 (64 per user), and the global
> signal pending limit to 4096 (1024 per user).
>
> This has been well tested.
>
> If you are OK with it for inclusion (-mm) I'll generate the arch-dependant
> changes for the other architectures.

yes, please.

> { RLIM_INFINITY, RLIM_INFINITY }, \
> + { IR_SIGNALS, IR_SIGNALS }, \
> + { IR_MSGQUEUE, IR_MSGQUEUE }, \

What does "IR" stand for here? Can a more meaningful abbreviation be chosen?


2004-04-20 14:15:01

by Marcelo Tosatti

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

On Mon, Apr 19, 2004 at 06:49:40PM -0400, Jakub Jelinek wrote:
> On Mon, Apr 19, 2004 at 06:28:10PM -0300, Marcelo Tosatti wrote:
> > Andrew,
> >
> > Here goes the signal pending & POSIX mqueue's per-uid limit patch.
> >
> > Initialization has been moved to include/asm-i386/resource.h, as you suggested.
> >
> > The global mqueue limit has been increased to 256 (64 per user), and the global
> > signal pending limit to 4096 (1024 per user).
> >
> > This has been well tested.
> >
> > If you are OK with it for inclusion (-mm) I'll generate the arch-dependant
> > changes for the other architectures.
> >
> > Comments are welcome.
>
> I wonder if it is a good idea to base mqueue limitation on the number of
> message queues and not take into account how big they are.
> 64 message queues with 1 byte msgsize and 1 maxmsg is certainly quite
> harmless and the system could have even more queues for such a user,
> while 64 message queues with 16K msgsize (current default) and 40 maxmsg
> (also default) eats ~ 40M of kernel memory.

Indeed, it seems more correct to account for something else than "nr of message queues".

Memory occupied sounds better, yeap?

I'm sending the patch anyway, we can use the same RLIMIT_MSGQUEUE and user->msg_queues later
on with another meaning.

Here it goes the update version, Andrew:

diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/arch/i386/kernel/init_task.c linux-2.6.6-rc1-mm1/arch/i386/kernel/init_task.c
--- linux-2.6.6-rc1-mm1.orig/arch/i386/kernel/init_task.c 2004-04-20 09:53:30.542659216 -0300
+++ linux-2.6.6-rc1-mm1/arch/i386/kernel/init_task.c 2004-04-20 09:59:46.330530776 -0300
@@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/fs.h>
+#include <linux/mqueue.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-alpha/resource.h linux-2.6.6-rc1-mm1/include/asm-alpha/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-alpha/resource.h 2004-04-20 09:53:22.648859256 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-alpha/resource.h 2004-04-20 10:22:29.435307352 -0300
@@ -16,8 +16,10 @@
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
#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. Fine, it's unsigned, but
@@ -41,6 +43,8 @@
{LONG_MAX, LONG_MAX}, /* RLIMIT_NPROC */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_MEMLOCK */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_LOCKS */ \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, /* RLIMIT_SIGPENDING */ \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, /* RLIMIT_MSGQUEUE */ \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-arm/resource.h linux-2.6.6-rc1-mm1/include/asm-arm/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-arm/resource.h 2004-04-20 09:53:21.870977512 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-arm/resource.h 2004-04-20 10:23:34.019489064 -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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-arm26/resource.h linux-2.6.6-rc1-mm1/include/asm-arm26/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-arm26/resource.h 2004-04-20 09:53:25.795380912 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-arm26/resource.h 2004-04-20 10:24:14.266370608 -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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-cris/resource.h linux-2.6.6-rc1-mm1/include/asm-cris/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-cris/resource.h 2004-04-20 09:53:25.351448400 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-cris/resource.h 2004-04-20 10:32:05.784688928 -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.
@@ -40,6 +42,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-h8300/resource.h linux-2.6.6-rc1-mm1/include/asm-h8300/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-h8300/resource.h 2004-04-20 09:53:24.789533824 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-h8300/resource.h 2004-04-20 10:32:51.974666984 -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.
@@ -40,6 +42,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-i386/resource.h linux-2.6.6-rc1-mm1/include/asm-i386/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-i386/resource.h 2004-04-20 09:53:23.662705128 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-i386/resource.h 2004-04-20 09:59:46.360526216 -0300
@@ -16,8 +16,11 @@
#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 13

-#define RLIM_NLIMITS 11

/*
* SuS says limits have to be unsigned.
@@ -40,6 +43,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-ia64/resource.h linux-2.6.6-rc1-mm1/include/asm-ia64/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-ia64/resource.h 2004-04-20 09:53:17.076706352 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-ia64/resource.h 2004-04-20 10:34:15.530964496 -0300
@@ -23,8 +23,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.
@@ -47,6 +49,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

# endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-m68k/resource.h linux-2.6.6-rc1-mm1/include/asm-m68k/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-m68k/resource.h 2004-04-20 09:53:19.214381376 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-m68k/resource.h 2004-04-20 10:35:09.442768656 -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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-mips/resource.h linux-2.6.6-rc1-mm1/include/asm-mips/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-mips/resource.h 2004-04-20 09:53:14.563088480 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-mips/resource.h 2004-04-20 10:35:51.914312000 -0300
@@ -1,4 +1,4 @@
-/*
+ /*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -23,8 +23,10 @@
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
#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 /* Number of limit flavors. */
+#define RLIM_NLIMITS 13 /* Number of limit flavors. */

#ifdef __KERNEL__

@@ -54,6 +56,8 @@
{ 0, 0 }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-parisc/resource.h linux-2.6.6-rc1-mm1/include/asm-parisc/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-parisc/resource.h 2004-04-20 09:53:12.274436408 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-parisc/resource.h 2004-04-20 10:36:19.905056760 -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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-ppc/resource.h linux-2.6.6-rc1-mm1/include/asm-ppc/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-ppc/resource.h 2004-04-20 09:53:18.942422720 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-ppc/resource.h 2004-04-20 10:38:08.781505024 -0300
@@ -12,8 +12,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

#ifdef __KERNEL__

@@ -37,6 +39,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-ppc64/resource.h linux-2.6.6-rc1-mm1/include/asm-ppc64/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-ppc64/resource.h 2004-04-20 09:53:12.590388376 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-ppc64/resource.h 2004-04-20 10:38:54.790510592 -0300
@@ -21,8 +21,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

#ifdef __KERNEL__

@@ -46,6 +48,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-s390/resource.h linux-2.6.6-rc1-mm1/include/asm-s390/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-s390/resource.h 2004-04-20 09:53:24.491579120 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-s390/resource.h 2004-04-20 10:39:45.573790360 -0300
@@ -24,7 +24,9 @@
#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

/*
@@ -48,6 +50,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-sh/resource.h linux-2.6.6-rc1-mm1/include/asm-sh/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-sh/resource.h 2004-04-20 09:53:26.883215536 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-sh/resource.h 2004-04-20 10:41:58.536576944 -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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-sparc/resource.h linux-2.6.6-rc1-mm1/include/asm-sparc/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-sparc/resource.h 2004-04-20 09:53:22.190928872 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-sparc/resource.h 2004-04-20 10:42:39.531344792 -0300
@@ -22,8 +22,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.
@@ -45,6 +47,9 @@
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY} \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-sparc64/resource.h linux-2.6.6-rc1-mm1/include/asm-sparc64/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-sparc64/resource.h 2004-04-20 09:53:25.468430616 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-sparc64/resource.h 2004-04-20 10:43:35.636815464 -0300
@@ -22,8 +22,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.
@@ -44,6 +46,8 @@
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY} \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-v850/resource.h linux-2.6.6-rc1-mm1/include/asm-v850/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-v850/resource.h 2004-04-20 09:53:26.010348232 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-v850/resource.h 2004-04-20 10:44:20.850941872 -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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/asm-x86_64/resource.h linux-2.6.6-rc1-mm1/include/asm-x86_64/resource.h
--- linux-2.6.6-rc1-mm1.orig/include/asm-x86_64/resource.h 2004-04-20 09:53:17.252679600 -0300
+++ linux-2.6.6-rc1-mm1/include/asm-x86_64/resource.h 2004-04-20 10:44:56.474526264 -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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/linux/mqueue.h linux-2.6.6-rc1-mm1/include/linux/mqueue.h
--- linux-2.6.6-rc1-mm1.orig/include/linux/mqueue.h 2004-04-20 09:53:18.864434576 -0300
+++ linux-2.6.6-rc1-mm1/include/linux/mqueue.h 2004-04-20 09:59:46.360526216 -0300
@@ -21,6 +21,8 @@
#include <linux/types.h>

#define MQ_PRIO_MAX 32768
+#define DFLT_QUEUESMAX 256
+#define MAX_USER_MSGQUEUE (DFLT_QUEUESMAX / 4)

struct mq_attr {
long mq_flags; /* message queue flags */
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/include/linux/sched.h linux-2.6.6-rc1-mm1/include/linux/sched.h
--- linux-2.6.6-rc1-mm1.orig/include/linux/sched.h 2004-04-20 09:53:17.856587792 -0300
+++ linux-2.6.6-rc1-mm1/include/linux/sched.h 2004-04-20 09:59:46.362525912 -0300
@@ -294,6 +294,7 @@ struct signal_struct {
int leader;

struct tty_struct *tty; /* NULL if no tty */
+ atomic_t sigpending;
};

/*
@@ -323,6 +324,9 @@ struct user_struct {
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 --show-c-function linux-2.6.6-rc1-mm1.orig/include/linux/signal.h linux-2.6.6-rc1-mm1/include/linux/signal.h
--- linux-2.6.6-rc1-mm1.orig/include/linux/signal.h 2004-04-20 09:53:17.925577304 -0300
+++ linux-2.6.6-rc1-mm1/include/linux/signal.h 2004-04-20 09:59:46.375523936 -0300
@@ -7,6 +7,10 @@
#include <asm/siginfo.h>

#ifdef __KERNEL__
+
+#define MAX_QUEUED_SIGNALS 4096
+#define MAX_USER_SIGNALS (MAX_QUEUED_SIGNALS/4)
+
/*
* Real Time signals may be queued.
*/
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/ipc/mqueue.c linux-2.6.6-rc1-mm1/ipc/mqueue.c
--- linux-2.6.6-rc1-mm1.orig/ipc/mqueue.c 2004-04-20 09:54:27.403015128 -0300
+++ linux-2.6.6-rc1-mm1/ipc/mqueue.c 2004-04-20 09:59:46.376523784 -0300
@@ -43,7 +43,6 @@
#define CTL_MSGSIZEMAX 4

/* default values */
-#define DFLT_QUEUESMAX 64 /* 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 +216,14 @@ static void mqueue_delete_inode(struct i

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 +232,18 @@ static int mqueue_create(struct inode *d
{
struct inode *inode;
int error;
+ struct task_struct *p = current;

spin_lock(&mq_lock);
- if (queues_count >= queues_max && !capable(CAP_SYS_RESOURCE)) {
+ if (!capable(CAP_SYS_RESOURCE) && (queues_count >= queues_max ||
+ 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 +251,7 @@ static int mqueue_create(struct inode *d
error = -ENOMEM;
spin_lock(&mq_lock);
queues_count--;
+ p->user->msg_queues--;
goto out_lock;
}

diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/kernel/signal.c linux-2.6.6-rc1-mm1/kernel/signal.c
--- linux-2.6.6-rc1-mm1.orig/kernel/signal.c 2004-04-20 09:54:26.747114840 -0300
+++ linux-2.6.6-rc1-mm1/kernel/signal.c 2004-04-20 09:59:46.378523480 -0300
@@ -32,7 +32,7 @@
static kmem_cache_t *sigqueue_cachep;

atomic_t nr_queued_signals;
-int max_queued_signals = 1024;
+int max_queued_signals = MAX_QUEUED_SIGNALS;

/*
* In POSIX a signal is sent either to a specific thread (Linux task)
@@ -268,10 +268,13 @@ struct sigqueue *__sigqueue_alloc(void)
{
struct sigqueue *q = 0;

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&nr_queued_signals) < max_queued_signals &&
+ atomic_read(&current->user->signal_pending) <=
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
if (q) {
atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
INIT_LIST_HEAD(&q->list);
q->flags = 0;
q->lock = 0;
@@ -285,6 +288,14 @@ static inline void __sigqueue_free(struc
return;
kmem_cache_free(sigqueue_cachep, q);
atomic_dec(&nr_queued_signals);
+
+ /*
+ * Decrease per-user sigpending count. Check
+ * for negative value, we might have done setuid()
+ * with pending signals.
+ */
+ if (atomic_read(&current->user->signal_pending) > 0)
+ atomic_dec(&current->user->signal_pending);
}

static void flush_sigqueue(struct sigpending *queue)
@@ -701,11 +712,15 @@ static int send_signal(int sig, struct s
make sure at least one signal gets delivered and don't
pass on the info struct. */

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&nr_queued_signals) < max_queued_signals &&
+ atomic_read(&current->user->signal_pending) <=
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);

if (q) {
atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
+
q->flags = 0;
list_add_tail(&q->list, &signals->list);
switch ((unsigned long) info) {
diff -Nur --show-c-function linux-2.6.6-rc1-mm1.orig/kernel/user.c linux-2.6.6-rc1-mm1/kernel/user.c
--- linux-2.6.6-rc1-mm1.orig/kernel/user.c 2004-04-20 09:54:26.716119552 -0300
+++ linux-2.6.6-rc1-mm1/kernel/user.c 2004-04-20 09:59:46.379523328 -0300
@@ -30,7 +30,9 @@ static spinlock_t uidhash_lock = SPIN_LO
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
};

/*
@@ -97,6 +99,9 @@ struct user_struct * alloc_uid(uid_t uid
atomic_set(&new->__count, 1);
atomic_set(&new->processes, 0);
atomic_set(&new->files, 0);
+ atomic_set(&new->signal_pending, 0);
+
+ new->msg_queues = 0;

/*
* Before adding this, check whether we raced




2004-04-20 18:06:19

by Manfred Spraul

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

Marcelo Tosatti wrote:

>Indeed, it seems more correct to account for something else than "nr of message queues".
>
>Memory occupied sounds better, yeap?
>
>
I agree, but note that there is one hidden problem:
There can be one notification for each registered message queue. If
there are more than ~560 queues and one process wants to install
SIGEV_THREAD notification handlers for all of them, then the netfilter
code will run against the socket rmem limit and mq_notify will block.
_If_ there are users that do that we'll have to bypass the normal
sk_rmem_alloc and add an mqueue specific limit.

--
Manfred


2004-04-20 22:50:22

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

Marcelo Tosatti <[email protected]> wrote:
>
> I wonder if it is a good idea to base mqueue limitation on the number of
> > message queues and not take into account how big they are.
> > 64 message queues with 1 byte msgsize and 1 maxmsg is certainly quite
> > harmless and the system could have even more queues for such a user,
> > while 64 message queues with 16K msgsize (current default) and 40 maxmsg
> > (also default) eats ~ 40M of kernel memory.
>
> Indeed, it seems more correct to account for something else than "nr of message queues".
>
> Memory occupied sounds better, yeap?
>
> I'm sending the patch anyway, we can use the same RLIMIT_MSGQUEUE and user->msg_queues later
> on with another meaning.
>
> Here it goes the update version, Andrew:

But we still have the global mq and signal limits? These permit local
denials of service attacks. See
http://seclists.org/lists/linux-kernel/2004/Apr/2065.html

The major advantage of your work is that we can now remove those limits.
You'll be needing a 2.4 backport ;)

2004-04-20 23:14:26

by Marcelo Tosatti

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

On Tue, Apr 20, 2004 at 01:04:39PM -0700, Andrew Morton wrote:
> Marcelo Tosatti <[email protected]> wrote:
> >
> > I wonder if it is a good idea to base mqueue limitation on the number of
> > > message queues and not take into account how big they are.
> > > 64 message queues with 1 byte msgsize and 1 maxmsg is certainly quite
> > > harmless and the system could have even more queues for such a user,
> > > while 64 message queues with 16K msgsize (current default) and 40 maxmsg
> > > (also default) eats ~ 40M of kernel memory.
> >
> > Indeed, it seems more correct to account for something else than "nr of message queues".
> >
> > Memory occupied sounds better, yeap?
> >
> > I'm sending the patch anyway, we can use the same RLIMIT_MSGQUEUE and user->msg_queues later
> > on with another meaning.
> >
> > Here it goes the update version, Andrew:
>
> But we still have the global mq and signal limits? These permit local
> denials of service attacks. See
> http://seclists.org/lists/linux-kernel/2004/Apr/2065.html

Right, but one user can't starve the whole system anymore. You need 4 users starving
their quotas for it to become a local denial of service attack. But you are right,
we can remove the global pending signal. I will prepare and test
another patch tomorrow morning.

As for mqueues, currently root is allowed to allocate infinite number of mqueues. We
want to remove that and calculate on the amount of memory allocated. I'll also think
about it and come with an implementation tomorrow morning.

> The major advantage of your work is that we can now remove those limits.
> You'll be needing a 2.4 backport ;)

Yeap. :)

And we also need to do the userspace part. ulimit is part of bash, so
probably all shell's should be awared of this? I never looked
how "ulimit" utility works.

2004-04-20 23:35:07

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

Marcelo Tosatti <[email protected]> wrote:
>
> > The major advantage of your work is that we can now remove those limits.
> > You'll be needing a 2.4 backport ;)
>
> Yeap. :)
>
> And we also need to do the userspace part. ulimit is part of bash, so
> probably all shell's should be awared of this? I never looked
> how "ulimit" utility works.

yup, the shells need to be changed, which is really awkward. I was wrong
about how bash and zsh handle `ulimit 4 1024'.

Really the shells _should_ permit ulimit-by-number for this very reason.

Adding new ulimits is nice - it's a shame that the shells make it hard to
use.

2004-04-21 20:53:58

by Marcelo Tosatti

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

On Tue, Apr 20, 2004 at 04:34:43PM -0700, Andrew Morton wrote:
> Marcelo Tosatti <[email protected]> wrote:
> >
> > > The major advantage of your work is that we can now remove those limits.
> > > You'll be needing a 2.4 backport ;)
> >
> > Yeap. :)
> >
> > And we also need to do the userspace part. ulimit is part of bash, so
> > probably all shell's should be awared of this? I never looked
> > how "ulimit" utility works.
>
> yup, the shells need to be changed, which is really awkward. I was wrong
> about how bash and zsh handle `ulimit 4 1024'.
>
> Really the shells _should_ permit ulimit-by-number for this very reason.
>
> Adding new ulimits is nice - it's a shame that the shells make it hard to
> use.

I'm thinking about how to do the mqueue "kernel allocated memory" accounting,
and I have a problem. A user can create an mqueue of given size via sys_mq_open()
using "msg_attr" structure (will be created in do_create). I can account for how much
memory has been allocated, but I can't at "deaccount" at kfree() time (this memory
is stored in inode->(mqueue_inode_info *)info->messages), because I dont know how big
it is (its user selectable via "msg_attr" structure).

What can be done about this?

Creating a data structure to account for "allocation->allocation size"
sounds overly complicated at first, but might be necessary if correct
accounting is necessary?

Gracias

2004-04-22 05:34:23

by Manfred Spraul

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

Marcelo Tosatti wrote:

>I'm thinking about how to do the mqueue "kernel allocated memory" accounting,
>and I have a problem. A user can create an mqueue of given size via sys_mq_open()
>using "msg_attr" structure (will be created in do_create). I can account for how much
>memory has been allocated, but I can't at "deaccount" at kfree() time (this memory
>is stored in inode->(mqueue_inode_info *)info->messages), because I dont know how big
>it is (its user selectable via "msg_attr" structure).
>
>
Why not? mqueue_delete_inode can look at info->attr.mq_maxmsg and
info->attr.mq_curmsg.

--
Manfred

2004-04-27 14:54:22

by Marcelo Tosatti

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

On Thu, Apr 22, 2004 at 07:33:56AM +0200, Manfred Spraul wrote:
> Marcelo Tosatti wrote:
>
> >I'm thinking about how to do the mqueue "kernel allocated memory"
> >accounting, and I have a problem. A user can create an mqueue of given
> >size via sys_mq_open()
> >using "msg_attr" structure (will be created in do_create). I can account
> >for how much memory has been allocated, but I can't at "deaccount" at
> >kfree() time (this memory is stored in inode->(mqueue_inode_info
> >*)info->messages), because I dont know how big
> >it is (its user selectable via "msg_attr" structure).
> >
> >
> Why not? mqueue_delete_inode can look at info->attr.mq_maxmsg and
> info->attr.mq_curmsg.

Hi,

Here goes the latest signal/mqueue per-uid limits patch. It now does:

- Create per-user signal limits, remove global limit

- Create per-user message queue limits, accounting is
now done on memory-allocated (queue creation and message
allocation). Note: it might be nice to move deaccounting
inside free_msg().

I added an int to mqueue inode and to "struct msg_msg" (to save
the UID of inode creator, to guarantee deaccounting is done
correctly if another UID deletes the entries (eg root)). I wonder
about cache locality. Has anyone cared enough to align the mqueue
structures? Dont think so... Does it impact performance?

Thanks Andrew, Manfred and Jakub for their comments.

Attached are "mqsend.c" and "mqrec.c", two simple programs (copied from
libmqueue) which I used for testing, in case anyone is interested.

Comments are welcome

diff -Nur --show-c-function a/linux-2.6.5/arch/i386/kernel/init_task.c linux-2.6.5/arch/i386/kernel/init_task.c
--- a/linux-2.6.5/arch/i386/kernel/init_task.c 2004-04-04 00:38:20.000000000 -0300
+++ linux-2.6.5/arch/i386/kernel/init_task.c 2004-04-27 08:32:46.000000000 -0300
@@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/fs.h>
+#include <linux/mqueue.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>
diff -Nur --show-c-function a/linux-2.6.5/include/asm-alpha/resource.h linux-2.6.5/include/asm-alpha/resource.h
--- a/linux-2.6.5/include/asm-alpha/resource.h 2004-04-04 00:36:17.000000000 -0300
+++ linux-2.6.5/include/asm-alpha/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -16,8 +16,10 @@
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
#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. Fine, it's unsigned, but
@@ -41,6 +43,8 @@
{LONG_MAX, LONG_MAX}, /* RLIMIT_NPROC */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_MEMLOCK */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_LOCKS */ \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, /* RLIMIT_SIGPENDING */ \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, /* RLIMIT_MSGQUEUE */ \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-arm/resource.h linux-2.6.5/include/asm-arm/resource.h
--- a/linux-2.6.5/include/asm-arm/resource.h 2004-04-04 00:38:10.000000000 -0300
+++ linux-2.6.5/include/asm-arm/resource.h 2004-04-27 08:32:46.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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-arm26/resource.h linux-2.6.5/include/asm-arm26/resource.h
--- a/linux-2.6.5/include/asm-arm26/resource.h 2004-04-04 00:36:14.000000000 -0300
+++ linux-2.6.5/include/asm-arm26/resource.h 2004-04-27 08:32:46.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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-cris/resource.h linux-2.6.5/include/asm-cris/resource.h
--- a/linux-2.6.5/include/asm-cris/resource.h 2004-04-04 00:37:36.000000000 -0300
+++ linux-2.6.5/include/asm-cris/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-h8300/resource.h linux-2.6.5/include/asm-h8300/resource.h
--- a/linux-2.6.5/include/asm-h8300/resource.h 2004-04-04 00:36:16.000000000 -0300
+++ linux-2.6.5/include/asm-h8300/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-i386/resource.h linux-2.6.5/include/asm-i386/resource.h
--- a/linux-2.6.5/include/asm-i386/resource.h 2004-04-04 00:36:24.000000000 -0300
+++ linux-2.6.5/include/asm-i386/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -16,8 +16,11 @@
#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 13

-#define RLIM_NLIMITS 11

/*
* SuS says limits have to be unsigned.
@@ -40,6 +43,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-ia64/resource.h linux-2.6.5/include/asm-ia64/resource.h
--- a/linux-2.6.5/include/asm-ia64/resource.h 2004-04-04 00:37:39.000000000 -0300
+++ linux-2.6.5/include/asm-ia64/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -23,8 +23,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.
@@ -47,6 +49,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

# endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-m68k/resource.h linux-2.6.5/include/asm-m68k/resource.h
--- a/linux-2.6.5/include/asm-m68k/resource.h 2004-04-04 00:36:14.000000000 -0300
+++ linux-2.6.5/include/asm-m68k/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-mips/resource.h linux-2.6.5/include/asm-mips/resource.h
--- a/linux-2.6.5/include/asm-mips/resource.h 2004-04-04 00:38:06.000000000 -0300
+++ linux-2.6.5/include/asm-mips/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -1,4 +1,4 @@
-/*
+ /*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -23,8 +23,10 @@
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
#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 /* Number of limit flavors. */
+#define RLIM_NLIMITS 13 /* Number of limit flavors. */

#ifdef __KERNEL__

@@ -54,6 +56,8 @@
{ 0, 0 }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-parisc/resource.h linux-2.6.5/include/asm-parisc/resource.h
--- a/linux-2.6.5/include/asm-parisc/resource.h 2004-04-04 00:37:37.000000000 -0300
+++ linux-2.6.5/include/asm-parisc/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-ppc/resource.h linux-2.6.5/include/asm-ppc/resource.h
--- a/linux-2.6.5/include/asm-ppc/resource.h 2004-04-04 00:36:57.000000000 -0300
+++ linux-2.6.5/include/asm-ppc/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -12,8 +12,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

#ifdef __KERNEL__

@@ -37,6 +39,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-ppc64/resource.h linux-2.6.5/include/asm-ppc64/resource.h
--- a/linux-2.6.5/include/asm-ppc64/resource.h 2004-04-04 00:37:37.000000000 -0300
+++ linux-2.6.5/include/asm-ppc64/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -21,8 +21,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

#ifdef __KERNEL__

@@ -46,6 +48,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-s390/resource.h linux-2.6.5/include/asm-s390/resource.h
--- a/linux-2.6.5/include/asm-s390/resource.h 2004-04-04 00:36:55.000000000 -0300
+++ linux-2.6.5/include/asm-s390/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -24,7 +24,9 @@
#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

/*
@@ -48,6 +50,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-sh/resource.h linux-2.6.5/include/asm-sh/resource.h
--- a/linux-2.6.5/include/asm-sh/resource.h 2004-04-04 00:37:36.000000000 -0300
+++ linux-2.6.5/include/asm-sh/resource.h 2004-04-27 08:32:46.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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-sparc/resource.h linux-2.6.5/include/asm-sparc/resource.h
--- a/linux-2.6.5/include/asm-sparc/resource.h 2004-04-04 00:36:18.000000000 -0300
+++ linux-2.6.5/include/asm-sparc/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -22,8 +22,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.
@@ -45,6 +47,9 @@
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY} \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-sparc64/resource.h linux-2.6.5/include/asm-sparc64/resource.h
--- a/linux-2.6.5/include/asm-sparc64/resource.h 2004-04-04 00:36:15.000000000 -0300
+++ linux-2.6.5/include/asm-sparc64/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -22,8 +22,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.
@@ -44,6 +46,8 @@
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY} \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-v850/resource.h linux-2.6.5/include/asm-v850/resource.h
--- a/linux-2.6.5/include/asm-v850/resource.h 2004-04-04 00:36:16.000000000 -0300
+++ linux-2.6.5/include/asm-v850/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-x86_64/resource.h linux-2.6.5/include/asm-x86_64/resource.h
--- a/linux-2.6.5/include/asm-x86_64/resource.h 2004-04-04 00:37:37.000000000 -0300
+++ linux-2.6.5/include/asm-x86_64/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/linux/mqueue.h linux-2.6.5/include/linux/mqueue.h
--- a/linux-2.6.5/include/linux/mqueue.h 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/include/linux/mqueue.h 2004-04-27 11:12:38.000000000 -0300
@@ -19,6 +19,10 @@
#define _LINUX_MQUEUE_H

#define MQ_PRIO_MAX 32768
+#define DFLT_QUEUESMAX 256
+
+/* per-uid limit of kernel memory used by mqueue, in bytes */
+#define MAX_USER_MSGQUEUE 16384

typedef int mqd_t;

diff -Nur --show-c-function a/linux-2.6.5/include/linux/msg.h linux-2.6.5/include/linux/msg.h
--- a/linux-2.6.5/include/linux/msg.h 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/include/linux/msg.h 2004-04-27 08:57:32.000000000 -0300
@@ -71,6 +71,7 @@ struct msg_msg {
int m_ts; /* message text size */
struct msg_msgseg* next;
void *security;
+ int sender; /* who sent this message */
/* the actual message follows immediately */
};

diff -Nur --show-c-function a/linux-2.6.5/include/linux/sched.h linux-2.6.5/include/linux/sched.h
--- a/linux-2.6.5/include/linux/sched.h 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/include/linux/sched.h 2004-04-27 08:32:46.000000000 -0300
@@ -278,6 +278,7 @@ struct signal_struct {
int leader;

struct tty_struct *tty; /* NULL if no tty */
+ atomic_t sigpending;
};

/*
@@ -307,6 +308,9 @@ struct user_struct {
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 --show-c-function a/linux-2.6.5/include/linux/signal.h linux-2.6.5/include/linux/signal.h
--- a/linux-2.6.5/include/linux/signal.h 2004-04-04 00:36:26.000000000 -0300
+++ linux-2.6.5/include/linux/signal.h 2004-04-27 08:32:46.000000000 -0300
@@ -7,6 +7,10 @@
#include <asm/siginfo.h>

#ifdef __KERNEL__
+
+#define MAX_QUEUED_SIGNALS 4096
+#define MAX_USER_SIGNALS (MAX_QUEUED_SIGNALS/4)
+
/*
* Real Time signals may be queued.
*/
diff -Nur --show-c-function a/linux-2.6.5/ipc/mqueue.c linux-2.6.5/ipc/mqueue.c
--- a/linux-2.6.5/ipc/mqueue.c 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/ipc/mqueue.c 2004-04-27 11:02:28.000000000 -0300
@@ -43,7 +43,6 @@
#define CTL_MSGSIZEMAX 4

/* default values */
-#define DFLT_QUEUESMAX 64 /* 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 */
@@ -60,6 +59,7 @@ struct mqueue_inode_info {
struct msg_msg **messages;

pid_t notify_owner; /* != 0 means notification registered */
+ uid_t creator_id; /* UID of creator, for resource accouting */
struct sigevent notify;
struct file *notify_filp;

@@ -110,6 +110,7 @@ static struct inode *mqueue_get_inode(st

if (S_ISREG(mode)) {
struct mqueue_inode_info *info;
+ struct task_struct *p = current;

inode->i_fop = &mqueue_file_operations;
inode->i_size = FILENT_SIZE;
@@ -124,7 +125,19 @@ static struct inode *mqueue_get_inode(st
memset(&info->attr, 0, sizeof(info->attr));
info->attr.mq_maxmsg = DFLT_MSGMAX;
info->attr.mq_msgsize = DFLT_MSGSIZEMAX;
+
+ if (p->user->msg_queues +
+ (DFLT_MSGMAX * sizeof(struct msg_msg *)) >=
+ p->rlim[RLIMIT_MSGQUEUE].rlim_cur)
+ return NULL;
+
info->messages = kmalloc(DFLT_MSGMAX * sizeof(struct msg_msg *), GFP_KERNEL);
+ info->creator_id = current->uid;
+
+ spin_lock(&mq_lock);
+ p->user->msg_queues += (DFLT_MSGMAX * sizeof(struct msg_msg *));
+ spin_unlock(&mq_lock);
+
if (!info->messages) {
make_bad_inode(inode);
iput(inode);
@@ -197,22 +210,32 @@ static void mqueue_destroy_inode(struct
static void mqueue_delete_inode(struct inode *inode)
{
struct mqueue_inode_info *info;
+ struct user_struct *user;
int i;

if (S_ISDIR(inode->i_mode)) {
clear_inode(inode);
return;
}
+
info = MQUEUE_I(inode);
+
+ user = find_user(info->creator_id);
+ if (!user)
+ BUG();
spin_lock(&info->lock);
- for (i = 0; i < info->attr.mq_curmsgs; i++)
+ for (i = 0; i < info->attr.mq_curmsgs; i++) {
+ user->msg_queues -= info->messages[i]->m_ts;
free_msg(info->messages[i]);
+ }
kfree(info->messages);
spin_unlock(&info->lock);

clear_inode(inode);

spin_lock(&mq_lock);
+ user->msg_queues -= (info->attr.mq_maxmsg *
+ sizeof(struct msg_msg *));
queues_count--;
spin_unlock(&mq_lock);
}
@@ -431,6 +454,9 @@ static void msg_insert(struct msg_msg *p

static inline struct msg_msg *msg_get(struct mqueue_inode_info *info)
{
+ struct user_struct *user;
+ user = find_user (info->messages[info->attr.mq_curmsgs-1]->sender);
+ user->msg_queues -= info->messages[info->attr.mq_curmsgs-1]->m_ts;
info->qsize -= info->messages[--info->attr.mq_curmsgs]->m_ts;
return info->messages[info->attr.mq_curmsgs];
}
@@ -594,6 +620,7 @@ static struct file *do_create(struct den
struct file *filp;
struct inode *inode;
struct mqueue_inode_info *info;
+ struct task_struct *p = current;
struct msg_msg **msgs = NULL;
struct mq_attr attr;
int ret;
@@ -612,15 +639,24 @@ static struct file *do_create(struct den
attr.mq_msgsize > msgsize_max)
return ERR_PTR(-EINVAL);
}
+ if(p->user->msg_queues + (attr.mq_maxmsg * sizeof(struct msg_msg *))
+ >= p->rlim[RLIMIT_MSGQUEUE].rlim_cur)
+ return ERR_PTR(-ENOMEM);
+
msgs = kmalloc(attr.mq_maxmsg * sizeof(*msgs), GFP_KERNEL);
if (!msgs)
return ERR_PTR(-ENOMEM);
+
+ spin_lock(&mq_lock);
+ current->user->msg_queues += (attr.mq_maxmsg * sizeof(*msgs));
+ spin_unlock(&mq_lock);
} else {
msgs = NULL;
}

ret = vfs_create(dir->d_inode, dentry, mode, NULL);
if (ret) {
+ /* kfree(msgs): msgs can be NULL -mt */
kfree(msgs);
return ERR_PTR(ret);
}
@@ -631,8 +667,15 @@ static struct file *do_create(struct den
if (msgs) {
info->attr.mq_maxmsg = attr.mq_maxmsg;
info->attr.mq_msgsize = attr.mq_msgsize;
+ spin_lock(&mq_lock);
+ current->user->msg_queues -= (info->attr.mq_maxmsg
+ * sizeof (struct msg_msg *));
+ if (current->user->msg_queues < 0)
+ current->user->msg_queues = 0;
+ spin_unlock(&mq_lock);
kfree(info->messages);
info->messages = msgs;
+ info->creator_id = current->uid;
}

filp = dentry_open(dentry, mqueue_mnt, oflag);
@@ -849,6 +892,10 @@ asmlinkage long sys_mq_timedsend(mqd_t m
goto out_fput;
}

+ if(current->user->msg_queues + msg_len
+ >= current->rlim[RLIMIT_MSGQUEUE].rlim_cur)
+ goto out_fput;
+
/* First try to allocate memory, before doing anything with
* existing queues. */
msg_ptr = load_msg((void *)u_msg_ptr, msg_len);
@@ -858,6 +905,13 @@ asmlinkage long sys_mq_timedsend(mqd_t m
}
msg_ptr->m_ts = msg_len;
msg_ptr->m_type = msg_prio;
+ msg_ptr->sender = current->uid;
+
+ spin_lock(&mq_lock);
+
+ current->user->msg_queues += msg_len;
+
+ spin_unlock(&mq_lock);

spin_lock(&info->lock);

@@ -870,8 +924,12 @@ asmlinkage long sys_mq_timedsend(mqd_t m
wait.msg = (void *) msg_ptr;
wait.state = STATE_NONE;
ret = wq_sleep(info, SEND, timeout, &wait);
- if (ret < 0)
+ if (ret < 0) {
free_msg(msg_ptr);
+ spin_lock(&mq_lock);
+ current->user->msg_queues -= msg_len;
+ spin_unlock(&mq_lock);
+ }
}
} else {
receiver = wq_get_first_waiter(info, RECV);
diff -Nur --show-c-function a/linux-2.6.5/kernel/signal.c linux-2.6.5/kernel/signal.c
--- a/linux-2.6.5/kernel/signal.c 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/kernel/signal.c 2004-04-27 11:05:08.000000000 -0300
@@ -31,8 +31,7 @@

static kmem_cache_t *sigqueue_cachep;

-atomic_t nr_queued_signals;
-int max_queued_signals = 1024;
+int max_queued_signals = MAX_QUEUED_SIGNALS;

/*
* In POSIX a signal is sent either to a specific thread (Linux task)
@@ -268,10 +267,11 @@ struct sigqueue *__sigqueue_alloc(void)
{
struct sigqueue *q = 0;

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&current->user->signal_pending) <=
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
if (q) {
- atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
INIT_LIST_HEAD(&q->list);
q->flags = 0;
q->lock = 0;
@@ -284,7 +284,14 @@ static inline void __sigqueue_free(struc
if (q->flags & SIGQUEUE_PREALLOC)
return;
kmem_cache_free(sigqueue_cachep, q);
- atomic_dec(&nr_queued_signals);
+
+ /*
+ * Decrease per-user sigpending count. Check
+ * for negative value, we might have done setuid()
+ * with pending signals.
+ */
+ if (atomic_read(&current->user->signal_pending) > 0)
+ atomic_dec(&current->user->signal_pending);
}

static void flush_sigqueue(struct sigpending *queue)
@@ -700,11 +707,13 @@ static int send_signal(int sig, struct s
make sure at least one signal gets delivered and don't
pass on the info struct. */

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&current->user->signal_pending) <=
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);

if (q) {
- atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
+
q->flags = 0;
list_add_tail(&q->list, &signals->list);
switch ((unsigned long) info) {
diff -Nur --show-c-function a/linux-2.6.5/kernel/sysctl.c linux-2.6.5/kernel/sysctl.c
--- a/linux-2.6.5/kernel/sysctl.c 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/kernel/sysctl.c 2004-04-27 11:05:48.000000000 -0300
@@ -53,7 +53,6 @@ extern int C_A_D;
extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
extern int max_threads;
-extern atomic_t nr_queued_signals;
extern int max_queued_signals;
extern int sysrq_enabled;
extern int core_uses_pid;
@@ -419,14 +418,6 @@ static ctl_table kern_table[] = {
},
#endif
{
- .ctl_name = KERN_RTSIGNR,
- .procname = "rtsig-nr",
- .data = &nr_queued_signals,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- },
- {
.ctl_name = KERN_RTSIGMAX,
.procname = "rtsig-max",
.data = &max_queued_signals,
diff -Nur --show-c-function a/linux-2.6.5/kernel/user.c linux-2.6.5/kernel/user.c
--- a/linux-2.6.5/kernel/user.c 2004-04-04 00:36:56.000000000 -0300
+++ linux-2.6.5/kernel/user.c 2004-04-27 08:32:46.000000000 -0300
@@ -30,7 +30,9 @@ static spinlock_t uidhash_lock = SPIN_LO
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
};

/*
@@ -97,6 +99,9 @@ struct user_struct * alloc_uid(uid_t uid
atomic_set(&new->__count, 1);
atomic_set(&new->processes, 0);
atomic_set(&new->files, 0);
+ atomic_set(&new->signal_pending, 0);
+
+ new->msg_queues = 0;

/*
* Before adding this, check whether we raced


Attachments:
(No filename) (30.42 kB)
mqsend.c (1.67 kB)
mqrec.c (2.08 kB)
Download all attachments

2004-04-27 18:24:28

by Manfred Spraul

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

Marcelo Tosatti wrote:

>@@ -849,6 +892,10 @@ asmlinkage long sys_mq_timedsend(mqd_t m
> goto out_fput;
> }
>
>+ if(current->user->msg_queues + msg_len
>+ >= current->rlim[RLIMIT_MSGQUEUE].rlim_cur)
>+ goto out_fput;
>+
>
I don't like that:
The opengroup manpage doesn't mention out of memory as an error code for
mq_send(). I'd prefer if mq_open would check that
->mq_maxmsg*->mq_msgsize is below the limit and reserve the memory,
without further checks at send/receive time.

--
Manfred

2004-04-28 19:31:03

by Marcelo Tosatti

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

On Tue, Apr 27, 2004 at 08:09:35PM +0200, Manfred Spraul wrote:
> Marcelo Tosatti wrote:
>
> >@@ -849,6 +892,10 @@ asmlinkage long sys_mq_timedsend(mqd_t m
> > goto out_fput;
> > }
> >
> >+ if(current->user->msg_queues + msg_len
> >+ >= current->rlim[RLIMIT_MSGQUEUE].rlim_cur)
> >+ goto out_fput;
> >+
> >
> I don't like that:
> The opengroup manpage doesn't mention out of memory as an error code for
> mq_send(). I'd prefer if mq_open would check that
> ->mq_maxmsg*->mq_msgsize is below the limit and reserve the memory,
> without further checks at send/receive time.

I personally think that sucks, because the default maximum message size
is 16k, and the maximum nr of messages is 40 per-queue. That means
accounting 655k for each queue created.

Accounting at mq_send/mq_recv is more fine grained. But I understand and agree with you
on that we should comply with the opengroup man page (the manpage should be changed IMHO).

I decrease the maximum size to 8192 and the max nr messages per queue to 10.

This should be OK for inclusion into -mm now, if no other comment is made.

Here it is:

diff -Nur --show-c-function a/linux-2.6.5/arch/i386/kernel/init_task.c linux-2.6.5/arch/i386/kernel/init_task.c
--- a/linux-2.6.5/arch/i386/kernel/init_task.c 2004-04-04 00:38:20.000000000 -0300
+++ linux-2.6.5/arch/i386/kernel/init_task.c 2004-04-27 08:32:46.000000000 -0300
@@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/fs.h>
+#include <linux/mqueue.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>
diff -Nur --show-c-function a/linux-2.6.5/include/asm-alpha/resource.h linux-2.6.5/include/asm-alpha/resource.h
--- a/linux-2.6.5/include/asm-alpha/resource.h 2004-04-04 00:36:17.000000000 -0300
+++ linux-2.6.5/include/asm-alpha/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -16,8 +16,10 @@
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
#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. Fine, it's unsigned, but
@@ -41,6 +43,8 @@
{LONG_MAX, LONG_MAX}, /* RLIMIT_NPROC */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_MEMLOCK */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_LOCKS */ \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, /* RLIMIT_SIGPENDING */ \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, /* RLIMIT_MSGQUEUE */ \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-arm/resource.h linux-2.6.5/include/asm-arm/resource.h
--- a/linux-2.6.5/include/asm-arm/resource.h 2004-04-04 00:38:10.000000000 -0300
+++ linux-2.6.5/include/asm-arm/resource.h 2004-04-27 08:32:46.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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-arm26/resource.h linux-2.6.5/include/asm-arm26/resource.h
--- a/linux-2.6.5/include/asm-arm26/resource.h 2004-04-04 00:36:14.000000000 -0300
+++ linux-2.6.5/include/asm-arm26/resource.h 2004-04-27 08:32:46.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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-cris/resource.h linux-2.6.5/include/asm-cris/resource.h
--- a/linux-2.6.5/include/asm-cris/resource.h 2004-04-04 00:37:36.000000000 -0300
+++ linux-2.6.5/include/asm-cris/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-h8300/resource.h linux-2.6.5/include/asm-h8300/resource.h
--- a/linux-2.6.5/include/asm-h8300/resource.h 2004-04-04 00:36:16.000000000 -0300
+++ linux-2.6.5/include/asm-h8300/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-i386/resource.h linux-2.6.5/include/asm-i386/resource.h
--- a/linux-2.6.5/include/asm-i386/resource.h 2004-04-04 00:36:24.000000000 -0300
+++ linux-2.6.5/include/asm-i386/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -16,8 +16,11 @@
#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 13

-#define RLIM_NLIMITS 11

/*
* SuS says limits have to be unsigned.
@@ -40,6 +43,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-ia64/resource.h linux-2.6.5/include/asm-ia64/resource.h
--- a/linux-2.6.5/include/asm-ia64/resource.h 2004-04-04 00:37:39.000000000 -0300
+++ linux-2.6.5/include/asm-ia64/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -23,8 +23,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.
@@ -47,6 +49,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

# endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-m68k/resource.h linux-2.6.5/include/asm-m68k/resource.h
--- a/linux-2.6.5/include/asm-m68k/resource.h 2004-04-04 00:36:14.000000000 -0300
+++ linux-2.6.5/include/asm-m68k/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-mips/resource.h linux-2.6.5/include/asm-mips/resource.h
--- a/linux-2.6.5/include/asm-mips/resource.h 2004-04-04 00:38:06.000000000 -0300
+++ linux-2.6.5/include/asm-mips/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -23,8 +23,10 @@
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
#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 /* Number of limit flavors. */
+#define RLIM_NLIMITS 13 /* Number of limit flavors. */

#ifdef __KERNEL__

@@ -54,6 +56,8 @@
{ 0, 0 }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-parisc/resource.h linux-2.6.5/include/asm-parisc/resource.h
--- a/linux-2.6.5/include/asm-parisc/resource.h 2004-04-04 00:37:37.000000000 -0300
+++ linux-2.6.5/include/asm-parisc/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-ppc/resource.h linux-2.6.5/include/asm-ppc/resource.h
--- a/linux-2.6.5/include/asm-ppc/resource.h 2004-04-04 00:36:57.000000000 -0300
+++ linux-2.6.5/include/asm-ppc/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -12,8 +12,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

#ifdef __KERNEL__

@@ -37,6 +39,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-ppc64/resource.h linux-2.6.5/include/asm-ppc64/resource.h
--- a/linux-2.6.5/include/asm-ppc64/resource.h 2004-04-04 00:37:37.000000000 -0300
+++ linux-2.6.5/include/asm-ppc64/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -21,8 +21,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

#ifdef __KERNEL__

@@ -46,6 +48,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-s390/resource.h linux-2.6.5/include/asm-s390/resource.h
--- a/linux-2.6.5/include/asm-s390/resource.h 2004-04-04 00:36:55.000000000 -0300
+++ linux-2.6.5/include/asm-s390/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -24,7 +24,9 @@
#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

/*
@@ -48,6 +50,9 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-sh/resource.h linux-2.6.5/include/asm-sh/resource.h
--- a/linux-2.6.5/include/asm-sh/resource.h 2004-04-04 00:37:36.000000000 -0300
+++ linux-2.6.5/include/asm-sh/resource.h 2004-04-27 08:32:46.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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-sparc/resource.h linux-2.6.5/include/asm-sparc/resource.h
--- a/linux-2.6.5/include/asm-sparc/resource.h 2004-04-04 00:36:18.000000000 -0300
+++ linux-2.6.5/include/asm-sparc/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -22,8 +22,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.
@@ -45,6 +47,9 @@
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY} \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
+
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-sparc64/resource.h linux-2.6.5/include/asm-sparc64/resource.h
--- a/linux-2.6.5/include/asm-sparc64/resource.h 2004-04-04 00:36:15.000000000 -0300
+++ linux-2.6.5/include/asm-sparc64/resource.h 2004-04-27 08:32:46.000000000 -0300
@@ -22,8 +22,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.
@@ -44,6 +46,8 @@
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY} \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-v850/resource.h linux-2.6.5/include/asm-v850/resource.h
--- a/linux-2.6.5/include/asm-v850/resource.h 2004-04-04 00:36:16.000000000 -0300
+++ linux-2.6.5/include/asm-v850/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/asm-x86_64/resource.h linux-2.6.5/include/asm-x86_64/resource.h
--- a/linux-2.6.5/include/asm-x86_64/resource.h 2004-04-04 00:37:37.000000000 -0300
+++ linux-2.6.5/include/asm-x86_64/resource.h 2004-04-27 08:32:46.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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, \
}

#endif /* __KERNEL__ */
diff -Nur --show-c-function a/linux-2.6.5/include/linux/mqueue.h linux-2.6.5/include/linux/mqueue.h
--- a/linux-2.6.5/include/linux/mqueue.h 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/include/linux/mqueue.h 2004-04-28 11:30:57.000000000 -0300
@@ -19,6 +19,10 @@
#define _LINUX_MQUEUE_H

#define MQ_PRIO_MAX 32768
+#define DFLT_QUEUESMAX 256
+
+/* per-uid limit of kernel memory used by mqueue, in bytes */
+#define MAX_USER_MSGQUEUE 819200

typedef int mqd_t;

diff -Nur --show-c-function a/linux-2.6.5/include/linux/sched.h linux-2.6.5/include/linux/sched.h
--- a/linux-2.6.5/include/linux/sched.h 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/include/linux/sched.h 2004-04-27 08:32:46.000000000 -0300
@@ -278,6 +278,7 @@ struct signal_struct {
int leader;

struct tty_struct *tty; /* NULL if no tty */
+ atomic_t sigpending;
};

/*
@@ -307,6 +308,9 @@ struct user_struct {
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 --show-c-function a/linux-2.6.5/include/linux/signal.h linux-2.6.5/include/linux/signal.h
--- a/linux-2.6.5/include/linux/signal.h 2004-04-04 00:36:26.000000000 -0300
+++ linux-2.6.5/include/linux/signal.h 2004-04-27 08:32:46.000000000 -0300
@@ -7,6 +7,10 @@
#include <asm/siginfo.h>

#ifdef __KERNEL__
+
+#define MAX_QUEUED_SIGNALS 4096
+#define MAX_USER_SIGNALS (MAX_QUEUED_SIGNALS/4)
+
/*
* Real Time signals may be queued.
*/
diff -Nur --show-c-function a/linux-2.6.5/ipc/mqueue.c linux-2.6.5/ipc/mqueue.c
--- a/linux-2.6.5/ipc/mqueue.c 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/ipc/mqueue.c 2004-04-28 11:49:05.477005216 -0300
@@ -43,10 +43,9 @@
#define CTL_MSGSIZEMAX 4

/* default values */
-#define DFLT_QUEUESMAX 64 /* max number of message queues */
-#define DFLT_MSGMAX 40 /* max number of messages in each queue */
+#define DFLT_MSGMAX 10 /* max number of messages in each queue */
#define HARD_MSGMAX (131072/sizeof(void*))
-#define DFLT_MSGSIZEMAX 16384 /* max message size */
+#define DFLT_MSGSIZEMAX 8192 /* max message size */

struct ext_wait_queue { /* queue of sleeping tasks */
struct task_struct *task;
@@ -60,6 +59,7 @@ struct mqueue_inode_info {
struct msg_msg **messages;

pid_t notify_owner; /* != 0 means notification registered */
+ uid_t creator_id; /* UID of creator, for resource accouting */
struct sigevent notify;
struct file *notify_filp;

@@ -110,6 +110,7 @@ static struct inode *mqueue_get_inode(st

if (S_ISREG(mode)) {
struct mqueue_inode_info *info;
+ struct task_struct *p = current;

inode->i_fop = &mqueue_file_operations;
inode->i_size = FILENT_SIZE;
@@ -124,7 +125,20 @@ static struct inode *mqueue_get_inode(st
memset(&info->attr, 0, sizeof(info->attr));
info->attr.mq_maxmsg = DFLT_MSGMAX;
info->attr.mq_msgsize = DFLT_MSGSIZEMAX;
+
+ if (p->user->msg_queues +
+ (DFLT_MSGMAX * sizeof(struct msg_msg *) +
+ (DFLT_MSGMAX * DFLT_MSGSIZEMAX)) >=
+ p->rlim[RLIMIT_MSGQUEUE].rlim_cur)
+ return NULL;
+
info->messages = kmalloc(DFLT_MSGMAX * sizeof(struct msg_msg *), GFP_KERNEL);
+ info->creator_id = current->uid;
+
+ spin_lock(&mq_lock);
+ p->user->msg_queues += (DFLT_MSGMAX * sizeof(struct msg_msg *) + (DFLT_MSGMAX * DFLT_MSGSIZEMAX));
+ spin_unlock(&mq_lock);
+
if (!info->messages) {
make_bad_inode(inode);
iput(inode);
@@ -197,22 +211,32 @@ static void mqueue_destroy_inode(struct
static void mqueue_delete_inode(struct inode *inode)
{
struct mqueue_inode_info *info;
+ struct user_struct *user;
int i;

if (S_ISDIR(inode->i_mode)) {
clear_inode(inode);
return;
}
+
info = MQUEUE_I(inode);
+
+ user = find_user(info->creator_id);
+ if (!user)
+ BUG();
spin_lock(&info->lock);
for (i = 0; i < info->attr.mq_curmsgs; i++)
free_msg(info->messages[i]);
+
kfree(info->messages);
spin_unlock(&info->lock);

clear_inode(inode);

spin_lock(&mq_lock);
+ user->msg_queues -= (info->attr.mq_maxmsg *
+ sizeof(struct msg_msg *) +
+ (info->attr.mq_maxmsg * info->attr.mq_msgsize));
queues_count--;
spin_unlock(&mq_lock);
}
@@ -594,6 +618,7 @@ static struct file *do_create(struct den
struct file *filp;
struct inode *inode;
struct mqueue_inode_info *info;
+ struct task_struct *p = current;
struct msg_msg **msgs = NULL;
struct mq_attr attr;
int ret;
@@ -612,15 +637,26 @@ static struct file *do_create(struct den
attr.mq_msgsize > msgsize_max)
return ERR_PTR(-EINVAL);
}
+ if(p->user->msg_queues+ ((attr.mq_maxmsg * sizeof(struct msg_msg *)
+ + (attr.mq_maxmsg * attr.mq_msgsize)))
+ >= p->rlim[RLIMIT_MSGQUEUE].rlim_cur)
+ return ERR_PTR(-ENOMEM);
+
msgs = kmalloc(attr.mq_maxmsg * sizeof(*msgs), GFP_KERNEL);
if (!msgs)
return ERR_PTR(-ENOMEM);
+
+ spin_lock(&mq_lock);
+ current->user->msg_queues += (attr.mq_maxmsg * sizeof(*msgs) +
+ (attr.mq_maxmsg * attr.mq_msgsize));
+ spin_unlock(&mq_lock);
} else {
msgs = NULL;
}

ret = vfs_create(dir->d_inode, dentry, mode, NULL);
if (ret) {
+ /* kfree(msgs): msgs can be NULL -mt */
kfree(msgs);
return ERR_PTR(ret);
}
@@ -631,8 +667,17 @@ static struct file *do_create(struct den
if (msgs) {
info->attr.mq_maxmsg = attr.mq_maxmsg;
info->attr.mq_msgsize = attr.mq_msgsize;
+ spin_lock(&mq_lock);
+ current->user->msg_queues -= (info->attr.mq_maxmsg
+ * sizeof (struct msg_msg *) +
+ (info->attr.mq_maxmsg *
+ info->attr.mq_msgsize));
+ if (current->user->msg_queues < 0)
+ current->user->msg_queues = 0;
+ spin_unlock(&mq_lock);
kfree(info->messages);
info->messages = msgs;
+ info->creator_id = current->uid;
}

filp = dentry_open(dentry, mqueue_mnt, oflag);
diff -Nur --show-c-function a/linux-2.6.5/kernel/signal.c linux-2.6.5/kernel/signal.c
--- a/linux-2.6.5/kernel/signal.c 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/kernel/signal.c 2004-04-27 11:05:08.000000000 -0300
@@ -31,8 +31,7 @@

static kmem_cache_t *sigqueue_cachep;

-atomic_t nr_queued_signals;
-int max_queued_signals = 1024;
+int max_queued_signals = MAX_QUEUED_SIGNALS;

/*
* In POSIX a signal is sent either to a specific thread (Linux task)
@@ -268,10 +267,11 @@ struct sigqueue *__sigqueue_alloc(void)
{
struct sigqueue *q = 0;

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&current->user->signal_pending) <=
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
if (q) {
- atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
INIT_LIST_HEAD(&q->list);
q->flags = 0;
q->lock = 0;
@@ -284,7 +284,14 @@ static inline void __sigqueue_free(struc
if (q->flags & SIGQUEUE_PREALLOC)
return;
kmem_cache_free(sigqueue_cachep, q);
- atomic_dec(&nr_queued_signals);
+
+ /*
+ * Decrease per-user sigpending count. Check
+ * for negative value, we might have done setuid()
+ * with pending signals.
+ */
+ if (atomic_read(&current->user->signal_pending) > 0)
+ atomic_dec(&current->user->signal_pending);
}

static void flush_sigqueue(struct sigpending *queue)
@@ -700,11 +707,13 @@ static int send_signal(int sig, struct s
make sure at least one signal gets delivered and don't
pass on the info struct. */

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&current->user->signal_pending) <=
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);

if (q) {
- atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
+
q->flags = 0;
list_add_tail(&q->list, &signals->list);
switch ((unsigned long) info) {
diff -Nur --show-c-function a/linux-2.6.5/kernel/sysctl.c linux-2.6.5/kernel/sysctl.c
--- a/linux-2.6.5/kernel/sysctl.c 2004-04-27 09:53:24.000000000 -0300
+++ linux-2.6.5/kernel/sysctl.c 2004-04-27 11:05:48.000000000 -0300
@@ -53,7 +53,6 @@ extern int C_A_D;
extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
extern int max_threads;
-extern atomic_t nr_queued_signals;
extern int max_queued_signals;
extern int sysrq_enabled;
extern int core_uses_pid;
@@ -419,14 +418,6 @@ static ctl_table kern_table[] = {
},
#endif
{
- .ctl_name = KERN_RTSIGNR,
- .procname = "rtsig-nr",
- .data = &nr_queued_signals,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- },
- {
.ctl_name = KERN_RTSIGMAX,
.procname = "rtsig-max",
.data = &max_queued_signals,
diff -Nur --show-c-function a/linux-2.6.5/kernel/user.c linux-2.6.5/kernel/user.c
--- a/linux-2.6.5/kernel/user.c 2004-04-04 00:36:56.000000000 -0300
+++ linux-2.6.5/kernel/user.c 2004-04-27 08:32:46.000000000 -0300
@@ -30,7 +30,9 @@ static spinlock_t uidhash_lock = SPIN_LO
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
};

/*
@@ -97,6 +99,9 @@ struct user_struct * alloc_uid(uid_t uid
atomic_set(&new->__count, 1);
atomic_set(&new->processes, 0);
atomic_set(&new->files, 0);
+ atomic_set(&new->signal_pending, 0);
+
+ new->msg_queues = 0;

/*
* Before adding this, check whether we raced

2004-04-28 21:13:07

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

Marcelo Tosatti <[email protected]> wrote:
>
> static void mqueue_delete_inode(struct inode *inode)
> {
> struct mqueue_inode_info *info;
> + struct user_struct *user;
> int i;
>
> if (S_ISDIR(inode->i_mode)) {
> clear_inode(inode);
> return;
> }
> +
> info = MQUEUE_I(inode);
> +
> + user = find_user(info->creator_id);
> + if (!user)
> + BUG();
> spin_lock(&info->lock);

hmm, look at that. find_user() forgot to take any locks. Maybe it's
relying on tasklist_lock? I think we need the below patch. Ingo, can you
please confirm?


Also, you'll need to do a free_uid() in here - find_user() takes a ref.

Also, I'm not sure that it's legit to go BUG if the user wasn't found. Is
it not possible that the user has gone away and it is root who is cleaning
up the inode?

Finally, my head is gently rotating wrt this patch. Could you please
maintain a description of what it does? We've made several significant
design decisions in here and that info really should be captured. The
relationship between the global and per-user limits, the sizing choices for
the per-user limits, etc. If it can be captured in brief code comments,
that's best. Otherwise for the changelog.

Thanks.


---

25-akpm/kernel/sys.c | 4 ++++
25-akpm/kernel/user.c | 13 ++++++++++++-
2 files changed, 16 insertions(+), 1 deletion(-)

diff -puN kernel/user.c~find_user-locking kernel/user.c
--- 25/kernel/user.c~find_user-locking Wed Apr 28 13:56:52 2004
+++ 25-akpm/kernel/user.c Wed Apr 28 13:58:28 2004
@@ -64,9 +64,20 @@ static inline struct user_struct *uid_ha
return NULL;
}

+/*
+ * Locate the user_struct for the passed UID. If found, take a ref on it. The
+ * caller must undo that ref with free_uid().
+ *
+ * If the user_struct could not be found, return NULL.
+ */
struct user_struct *find_user(uid_t uid)
{
- return uid_hash_find(uid, uidhashentry(uid));
+ struct user_struct *ret;
+
+ spin_lock(&uidhash_lock);
+ ret = uid_hash_find(uid, uidhashentry(uid));
+ spin_unlock(&uidhash_lock);
+ return ret;
}

void free_uid(struct user_struct *up)
diff -puN kernel/sys.c~find_user-locking kernel/sys.c
--- 25/kernel/sys.c~find_user-locking Wed Apr 28 13:58:42 2004
+++ 25-akpm/kernel/sys.c Wed Apr 28 13:59:54 2004
@@ -348,6 +348,8 @@ asmlinkage long sys_setpriority(int whic
if (p->uid == who)
error = set_one_prio(p, niceval, error);
while_each_thread(g, p);
+ if (who)
+ free_uid(user); /* For find_user() */
break;
}
out_unlock:
@@ -410,6 +412,8 @@ asmlinkage long sys_getpriority(int whic
retval = niceval;
}
while_each_thread(g, p);
+ if (who)
+ free_uid(user); /* for find_user() */
break;
}
out_unlock:

_

2004-04-29 01:34:56

by Chris Wright

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

* Marcelo Tosatti ([email protected]) wrote:
> This should be OK for inclusion into -mm now, if no other comment is made.

This patch doesn't account for sigqueue bits properly. The allocations
aren't always made in task context. So, it's trivial to illegitimately
drain off the new signal_pending counter, leaving the potential for the
original DoS unfixed. And the setuid issues still seem to be there,
right?

Couple other nits below:

Some bits need to be converted to tabs from spaces.

> diff -Nur --show-c-function a/linux-2.6.5/include/asm-s390/resource.h linux-2.6.5/include/asm-s390/resource.h
> --- a/linux-2.6.5/include/asm-s390/resource.h 2004-04-04 00:36:55.000000000 -0300
> +++ linux-2.6.5/include/asm-s390/resource.h 2004-04-27 08:32:46.000000000 -0300
> @@ -24,7 +24,9 @@
> #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

Missed this one.

> diff -Nur --show-c-function a/linux-2.6.5/include/asm-sparc/resource.h linux-2.6.5/include/asm-sparc/resource.h
> --- a/linux-2.6.5/include/asm-sparc/resource.h 2004-04-04 00:36:18.000000000 -0300
> +++ linux-2.6.5/include/asm-sparc/resource.h 2004-04-27 08:32:46.000000000 -0300
> @@ -22,8 +22,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.
> @@ -45,6 +47,9 @@
> {RLIM_INFINITY, RLIM_INFINITY}, \
> {RLIM_INFINITY, RLIM_INFINITY}, \
> {RLIM_INFINITY, RLIM_INFINITY} \
> + {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
> + {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\

Won't compile.

> diff -Nur --show-c-function a/linux-2.6.5/include/asm-sparc64/resource.h linux-2.6.5/include/asm-sparc64/resource.h
> --- a/linux-2.6.5/include/asm-sparc64/resource.h 2004-04-04 00:36:15.000000000 -0300
> +++ linux-2.6.5/include/asm-sparc64/resource.h 2004-04-27 08:32:46.000000000 -0300
> @@ -22,8 +22,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.
> @@ -44,6 +46,8 @@
> {RLIM_INFINITY, RLIM_INFINITY}, \
> {RLIM_INFINITY, RLIM_INFINITY}, \
> {RLIM_INFINITY, RLIM_INFINITY} \
> + {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
> + {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\

Ditto.

> +++ linux-2.6.5/include/linux/signal.h 2004-04-27 08:32:46.000000000 -0300
> @@ -7,6 +7,10 @@
> #include <asm/siginfo.h>
>
> #ifdef __KERNEL__
> +
> +#define MAX_QUEUED_SIGNALS 4096

Besides right below, is this really used anymore?

> +#define MAX_USER_SIGNALS (MAX_QUEUED_SIGNALS/4)

here.

> diff -Nur --show-c-function a/linux-2.6.5/kernel/signal.c linux-2.6.5/kernel/signal.c
> --- a/linux-2.6.5/kernel/signal.c 2004-04-27 09:53:24.000000000 -0300
> +++ linux-2.6.5/kernel/signal.c 2004-04-27 11:05:08.000000000 -0300
> @@ -31,8 +31,7 @@
>
> static kmem_cache_t *sigqueue_cachep;
>
> -atomic_t nr_queued_signals;
> -int max_queued_signals = 1024;
> +int max_queued_signals = MAX_QUEUED_SIGNALS;

and here, but max_queued_signals is no longer really relevant, right?
Should we removed both nr_queued_signals and max_queued_signals and the
associated sysctl's? Or leave it, and give CAP_SYS_RESOURCE the ability
to do a full override? I chose the latter, although I'm inclined to
drop that bit.

> static void flush_sigqueue(struct sigpending *queue)
> @@ -700,11 +707,13 @@ static int send_signal(int sig, struct s
> make sure at least one signal gets delivered and don't
> pass on the info struct. */
>
> - if (atomic_read(&nr_queued_signals) < max_queued_signals)
> + if (atomic_read(&current->user->signal_pending) <=

current may not be valid here.

I have a diff between your patch and what I'm testing, but it's
cluttered a bit by the fact that I've also merged it up to 2.6.6-rc3
I can send you the full patch if that's easier.

thanks,
-chris
--
Linux Security Modules http://lsm.immunix.org http://lsm.bkbits.net

2004-04-29 12:19:00

by Marcelo Tosatti

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

On Wed, Apr 28, 2004 at 06:33:15PM -0700, Chris Wright wrote:
> * Marcelo Tosatti ([email protected]) wrote:
> > This should be OK for inclusion into -mm now, if no other comment is made.
>
> This patch doesn't account for sigqueue bits properly. The allocations
> aren't always made in task context. So, it's trivial to illegitimately
> drain off the new signal_pending counter, leaving the potential for the
> original DoS unfixed.

How?

> And the setuid issues still seem to be there,
> right?

The setuid issues are not there anymore in mqueue (because of find_user(info->creator_id) at
mqueue_delete_inode() time. The issue is still present with signal accounting, but
we have a "> 0" check for that. And usually only root/CAP_SET_SUID is able to hurt himself (get
unaccountable values in its quota). I dont think this really matters yet.

> Couple other nits below:
>
> Some bits need to be converted to tabs from spaces.

Yeap, there are some places where the "MAX_USER_SIGNALS" "MAX_USER_MSGQUEUE" names
get too big in the RLIM_INIT resource.h definition. I'm bad at coming up with names.
Any better suggestion for that (has to be smaller and meaningful). It means "maximum
pending signals per user".

> Ditto.

Alright, needs to be fixed.

> > +++ linux-2.6.5/include/linux/signal.h 2004-04-27 08:32:46.000000000 -0300
> > @@ -7,6 +7,10 @@
> > #include <asm/siginfo.h>
> >
> > #ifdef __KERNEL__
> > +
> > +#define MAX_QUEUED_SIGNALS 4096
>
> Besides right below, is this really used anymore?
>
> > +#define MAX_USER_SIGNALS (MAX_QUEUED_SIGNALS/4)
>
> here.

Not really. Can replace with MAX_USER_SIGNALS 1024...

> > diff -Nur --show-c-function a/linux-2.6.5/kernel/signal.c linux-2.6.5/kernel/signal.c
> > --- a/linux-2.6.5/kernel/signal.c 2004-04-27 09:53:24.000000000 -0300
> > +++ linux-2.6.5/kernel/signal.c 2004-04-27 11:05:08.000000000 -0300
> > @@ -31,8 +31,7 @@
> >
> > static kmem_cache_t *sigqueue_cachep;
> >
> > -atomic_t nr_queued_signals;
> > -int max_queued_signals = 1024;
> > +int max_queued_signals = MAX_QUEUED_SIGNALS;
>
> and here, but max_queued_signals is no longer really relevant, right?
> Should we removed both nr_queued_signals and max_queued_signals and the
> associated sysctl's? Or leave it, and give CAP_SYS_RESOURCE the ability
> to do a full override? I chose the latter, although I'm inclined to
> drop that bit.
>
> > static void flush_sigqueue(struct sigpending *queue)
> > @@ -700,11 +707,13 @@ static int send_signal(int sig, struct s
> > make sure at least one signal gets delivered and don't
> > pass on the info struct. */
> >
> > - if (atomic_read(&nr_queued_signals) < max_queued_signals)
> > + if (atomic_read(&current->user->signal_pending) <=
>
> current may not be valid here.
>
> I have a diff between your patch and what I'm testing, but it's
> cluttered a bit by the fact that I've also merged it up to 2.6.6-rc3
> I can send you the full patch if that's easier.

Please do so. Thanks!!

2004-04-29 20:01:20

by Chris Wright

[permalink] [raw]
Subject: Re: [PATCH] per-user signal pending and message queue limits

* Marcelo Tosatti ([email protected]) wrote:
> On Wed, Apr 28, 2004 at 06:33:15PM -0700, Chris Wright wrote:
> > * Marcelo Tosatti ([email protected]) wrote:
> > > This should be OK for inclusion into -mm now, if no other comment is made.
> >
> > This patch doesn't account for sigqueue bits properly. The allocations
> > aren't always made in task context. So, it's trivial to illegitimately
> > drain off the new signal_pending counter, leaving the potential for the
> > original DoS unfixed.
>
> How?

Take the normal loop that started the sigqueue DoS discussion (block the
signal and queue up the max amount). In another shell (same user), just
hit ^C. This will generate the signal in interrupt context, but
decrease the user count in task context. This way you can drain off
your counter.

> > And the setuid issues still seem to be there,
> > right?
>
> The setuid issues are not there anymore in mqueue (because of find_user(info->creator_id) at
> mqueue_delete_inode() time. The issue is still present with signal accounting, but
> we have a "> 0" check for that. And usually only root/CAP_SET_SUID is able to hurt himself (get
> unaccountable values in its quota). I dont think this really matters yet.

Yes, I only mean the signal side, not the mqueue side. And I realize my
test is perhaps overly contrived, but it allows me to bleed off the
wrong user similar to above. Issue is, do we care who allocates the
sigqueue structure, or who it's getting queued to? In most cases it's
irrelevant because you have to have permission to send the signal.

> > I have a diff between your patch and what I'm testing, but it's
> > cluttered a bit by the fact that I've also merged it up to 2.6.6-rc3
> > I can send you the full patch if that's easier.
>
> Please do so. Thanks!!

OK, here it is.

thanks,
-chris
--
Linux Security Modules http://lsm.immunix.org http://lsm.bkbits.net

===== arch/i386/kernel/init_task.c 1.9 vs edited =====
--- 1.9/arch/i386/kernel/init_task.c Thu Mar 18 22:03:08 2004
+++ edited/arch/i386/kernel/init_task.c Thu Apr 29 12:18:13 2004
@@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/fs.h>
+#include <linux/mqueue.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>
===== include/asm-alpha/resource.h 1.1 vs edited =====
--- 1.1/include/asm-alpha/resource.h Tue Feb 5 09:39:46 2002
+++ edited/include/asm-alpha/resource.h Thu Apr 29 12:18:13 2004
@@ -16,8 +16,10 @@
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
#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. Fine, it's unsigned, but
@@ -41,6 +43,8 @@
{LONG_MAX, LONG_MAX}, /* RLIMIT_NPROC */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_MEMLOCK */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_LOCKS */ \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, /* RLIMIT_SIGPENDING */ \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE}, /* RLIMIT_MSGQUEUE */ \
}

#endif /* __KERNEL__ */
===== include/asm-arm/resource.h 1.1 vs edited =====
--- 1.1/include/asm-arm/resource.h Tue Feb 5 09:39:52 2002
+++ edited/include/asm-arm/resource.h Thu Apr 29 12:18:13 2004
@@ -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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
===== include/asm-arm26/resource.h 1.1 vs edited =====
--- 1.1/include/asm-arm26/resource.h Wed Jun 4 04:14:10 2003
+++ edited/include/asm-arm26/resource.h Thu Apr 29 12:18:13 2004
@@ -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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
===== include/asm-cris/resource.h 1.1 vs edited =====
--- 1.1/include/asm-cris/resource.h Tue Feb 5 09:56:43 2002
+++ edited/include/asm-cris/resource.h Thu Apr 29 12:18:13 2004
@@ -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.
@@ -38,8 +40,10 @@
{ 0, 0 }, \
{ INR_OPEN, INR_OPEN }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
- { RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-h8300/resource.h 1.1 vs edited =====
--- 1.1/include/asm-h8300/resource.h Sun Feb 16 16:01:58 2003
+++ edited/include/asm-h8300/resource.h Thu Apr 29 12:18:13 2004
@@ -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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-i386/resource.h 1.1 vs edited =====
--- 1.1/include/asm-i386/resource.h Tue Feb 5 09:39:44 2002
+++ edited/include/asm-i386/resource.h Thu Apr 29 12:18:13 2004
@@ -16,8 +16,11 @@
#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 13

-#define RLIM_NLIMITS 11

/*
* SuS says limits have to be unsigned.
@@ -39,7 +42,9 @@
{ INR_OPEN, INR_OPEN }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
- { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-ia64/resource.h 1.3 vs edited =====
--- 1.3/include/asm-ia64/resource.h Fri Jan 23 10:52:25 2004
+++ edited/include/asm-ia64/resource.h Thu Apr 29 12:18:13 2004
@@ -23,8 +23,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.
@@ -47,6 +49,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

# endif /* __KERNEL__ */
===== include/asm-m68k/resource.h 1.2 vs edited =====
--- 1.2/include/asm-m68k/resource.h Fri Nov 9 05:47:28 2001
+++ edited/include/asm-m68k/resource.h Thu Apr 29 12:18:13 2004
@@ -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.
@@ -39,7 +41,9 @@
{ INR_OPEN, INR_OPEN }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
- { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-mips/resource.h 1.3 vs edited =====
--- 1.3/include/asm-mips/resource.h Mon Jul 28 04:57:50 2003
+++ edited/include/asm-mips/resource.h Thu Apr 29 12:18:13 2004
@@ -23,8 +23,10 @@
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
#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 /* Number of limit flavors. */
+#define RLIM_NLIMITS 13 /* Number of limit flavors. */

#ifdef __KERNEL__

@@ -54,6 +56,8 @@
{ 0, 0 }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-parisc/resource.h 1.1 vs edited =====
--- 1.1/include/asm-parisc/resource.h Tue Feb 5 09:39:57 2002
+++ edited/include/asm-parisc/resource.h Thu Apr 29 12:18:13 2004
@@ -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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-ppc/resource.h 1.3 vs edited =====
--- 1.3/include/asm-ppc/resource.h Sun Sep 15 21:52:06 2002
+++ edited/include/asm-ppc/resource.h Thu Apr 29 12:18:13 2004
@@ -12,8 +12,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

#ifdef __KERNEL__

@@ -37,6 +39,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-ppc64/resource.h 1.1 vs edited =====
--- 1.1/include/asm-ppc64/resource.h Thu Feb 14 04:14:36 2002
+++ edited/include/asm-ppc64/resource.h Thu Apr 29 12:18:13 2004
@@ -21,8 +21,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

#ifdef __KERNEL__

@@ -46,6 +48,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-s390/resource.h 1.2 vs edited =====
--- 1.2/include/asm-s390/resource.h Mon Feb 4 23:37:28 2002
+++ edited/include/asm-s390/resource.h Thu Apr 29 12:18:13 2004
@@ -24,8 +24,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 RLIM_NLIMITS 11
+#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
+#define RLIMIT_MSGQUEUE 12 /* max number of POSIX msg queues */
+
+#define RLIM_NLIMITS 13

/*
* SuS says limits have to be unsigned.
@@ -48,6 +50,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-sh/resource.h 1.1 vs edited =====
--- 1.1/include/asm-sh/resource.h Tue Feb 5 09:39:53 2002
+++ edited/include/asm-sh/resource.h Thu Apr 29 12:18:13 2004
@@ -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

#ifdef __KERNEL__

@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-sparc/resource.h 1.1 vs edited =====
--- 1.1/include/asm-sparc/resource.h Tue Feb 5 09:39:47 2002
+++ edited/include/asm-sparc/resource.h Thu Apr 29 12:18:13 2004
@@ -22,8 +22,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.
@@ -44,7 +46,9 @@
{INR_OPEN, INR_OPEN}, {0, 0}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
- {RLIM_INFINITY, RLIM_INFINITY} \
+ {RLIM_INFINITY, RLIM_INFINITY}, \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
===== include/asm-sparc64/resource.h 1.1 vs edited =====
--- 1.1/include/asm-sparc64/resource.h Tue Feb 5 09:39:50 2002
+++ edited/include/asm-sparc64/resource.h Thu Apr 29 12:18:13 2004
@@ -22,8 +22,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.
@@ -43,7 +45,9 @@
{INR_OPEN, INR_OPEN}, {0, 0}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
{RLIM_INFINITY, RLIM_INFINITY}, \
- {RLIM_INFINITY, RLIM_INFINITY} \
+ {RLIM_INFINITY, RLIM_INFINITY}, \
+ {MAX_USER_SIGNALS, MAX_USER_SIGNALS}, \
+ {MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE},\
}

#endif /* __KERNEL__ */
===== include/asm-v850/resource.h 1.1 vs edited =====
--- 1.1/include/asm-v850/resource.h Fri Nov 1 08:38:12 2002
+++ edited/include/asm-v850/resource.h Thu Apr 29 12:18:13 2004
@@ -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.
@@ -40,6 +42,8 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/asm-x86_64/resource.h 1.1 vs edited =====
--- 1.1/include/asm-x86_64/resource.h Thu Feb 7 02:55:27 2002
+++ edited/include/asm-x86_64/resource.h Thu Apr 29 12:18:13 2004
@@ -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.
@@ -39,7 +41,9 @@
{ INR_OPEN, INR_OPEN }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
- { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { MAX_USER_SIGNALS, MAX_USER_SIGNALS }, \
+ { MAX_USER_MSGQUEUE, MAX_USER_MSGQUEUE }, \
}

#endif /* __KERNEL__ */
===== include/linux/mqueue.h 1.4 vs edited =====
--- 1.4/include/linux/mqueue.h Mon Apr 12 10:54:17 2004
+++ edited/include/linux/mqueue.h Thu Apr 29 12:18:13 2004
@@ -21,6 +21,10 @@
#include <linux/types.h>

#define MQ_PRIO_MAX 32768
+#define DFLT_QUEUESMAX 256
+
+/* per-uid limit of kernel memory used by mqueue, in bytes */
+#define MAX_USER_MSGQUEUE 819200

struct mq_attr {
long mq_flags; /* message queue flags */
===== include/linux/sched.h 1.197 vs edited =====
--- 1.197/include/linux/sched.h Mon Apr 26 22:07:44 2004
+++ edited/include/linux/sched.h Thu Apr 29 12:18:13 2004
@@ -282,6 +282,7 @@
int leader;

struct tty_struct *tty; /* NULL if no tty */
+ atomic_t sigpending;
};

/*
@@ -311,6 +312,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;
===== include/linux/signal.h 1.15 vs edited =====
--- 1.15/include/linux/signal.h Thu Jan 15 12:40:33 2004
+++ edited/include/linux/signal.h Thu Apr 29 12:21:37 2004
@@ -7,6 +7,9 @@
#include <asm/siginfo.h>

#ifdef __KERNEL__
+
+#define MAX_USER_SIGNALS 1024
+
/*
* Real Time signals may be queued.
*/
===== ipc/mqueue.c 1.9 vs edited =====
--- 1.9/ipc/mqueue.c Sat Apr 17 11:19:31 2004
+++ edited/ipc/mqueue.c Thu Apr 29 12:18:13 2004
@@ -43,10 +43,9 @@
#define CTL_MSGSIZEMAX 4

/* default values */
-#define DFLT_QUEUESMAX 64 /* max number of message queues */
-#define DFLT_MSGMAX 40 /* max number of messages in each queue */
+#define DFLT_MSGMAX 10 /* max number of messages in each queue */
#define HARD_MSGMAX (131072/sizeof(void*))
-#define DFLT_MSGSIZEMAX 16384 /* max message size */
+#define DFLT_MSGSIZEMAX 8192 /* max message size */

#define NOTIFY_COOKIE_LEN 32

@@ -67,6 +66,7 @@

struct sigevent notify;
pid_t notify_owner;
+ uid_t creator_id; /* UID of creator, for resource accouting */
struct sock *notify_sock;
struct sk_buff *notify_cookie;

@@ -113,6 +113,7 @@

if (S_ISREG(mode)) {
struct mqueue_inode_info *info;
+ struct task_struct *p = current;

inode->i_fop = &mqueue_file_operations;
inode->i_size = FILENT_SIZE;
@@ -127,7 +128,20 @@
memset(&info->attr, 0, sizeof(info->attr));
info->attr.mq_maxmsg = DFLT_MSGMAX;
info->attr.mq_msgsize = DFLT_MSGSIZEMAX;
+
+ if (p->user->msg_queues +
+ (DFLT_MSGMAX * sizeof(struct msg_msg *) +
+ (DFLT_MSGMAX * DFLT_MSGSIZEMAX)) >=
+ p->rlim[RLIMIT_MSGQUEUE].rlim_cur)
+ return NULL;
+
info->messages = kmalloc(DFLT_MSGMAX * sizeof(struct msg_msg *), GFP_KERNEL);
+ info->creator_id = current->uid;
+
+ spin_lock(&mq_lock);
+ p->user->msg_queues += (DFLT_MSGMAX * sizeof(struct msg_msg *) + (DFLT_MSGMAX * DFLT_MSGSIZEMAX));
+ spin_unlock(&mq_lock);
+
if (!info->messages) {
make_bad_inode(inode);
iput(inode);
@@ -200,22 +214,32 @@
static void mqueue_delete_inode(struct inode *inode)
{
struct mqueue_inode_info *info;
+ struct user_struct *user;
int i;

if (S_ISDIR(inode->i_mode)) {
clear_inode(inode);
return;
}
+
info = MQUEUE_I(inode);
+
+ user = find_user(info->creator_id);
+ if (!user)
+ BUG();
spin_lock(&info->lock);
for (i = 0; i < info->attr.mq_curmsgs; i++)
free_msg(info->messages[i]);
+
kfree(info->messages);
spin_unlock(&info->lock);

clear_inode(inode);

spin_lock(&mq_lock);
+ user->msg_queues -= (info->attr.mq_maxmsg *
+ sizeof(struct msg_msg *) +
+ (info->attr.mq_maxmsg * info->attr.mq_msgsize));
queues_count--;
spin_unlock(&mq_lock);
}
@@ -535,6 +559,7 @@
struct file *filp;
struct inode *inode;
struct mqueue_inode_info *info;
+ struct task_struct *p = current;
struct msg_msg **msgs = NULL;
struct mq_attr attr;
int ret;
@@ -553,15 +578,26 @@
attr.mq_msgsize > msgsize_max)
return ERR_PTR(-EINVAL);
}
+ if(p->user->msg_queues+ ((attr.mq_maxmsg * sizeof(struct msg_msg *)
+ + (attr.mq_maxmsg * attr.mq_msgsize)))
+ >= p->rlim[RLIMIT_MSGQUEUE].rlim_cur)
+ return ERR_PTR(-ENOMEM);
+
msgs = kmalloc(attr.mq_maxmsg * sizeof(*msgs), GFP_KERNEL);
if (!msgs)
return ERR_PTR(-ENOMEM);
+
+ spin_lock(&mq_lock);
+ current->user->msg_queues += (attr.mq_maxmsg * sizeof(*msgs) +
+ (attr.mq_maxmsg * attr.mq_msgsize));
+ spin_unlock(&mq_lock);
} else {
msgs = NULL;
}

ret = vfs_create(dir->d_inode, dentry, mode, NULL);
if (ret) {
+ /* kfree(msgs): msgs can be NULL -mt */
kfree(msgs);
return ERR_PTR(ret);
}
@@ -572,8 +608,17 @@
if (msgs) {
info->attr.mq_maxmsg = attr.mq_maxmsg;
info->attr.mq_msgsize = attr.mq_msgsize;
+ spin_lock(&mq_lock);
+ current->user->msg_queues -= (info->attr.mq_maxmsg
+ * sizeof (struct msg_msg *) +
+ (info->attr.mq_maxmsg *
+ info->attr.mq_msgsize));
+ if (current->user->msg_queues < 0)
+ current->user->msg_queues = 0;
+ spin_unlock(&mq_lock);
kfree(info->messages);
info->messages = msgs;
+ info->creator_id = current->uid;
}

filp = dentry_open(dentry, mqueue_mnt, oflag);
===== kernel/signal.c 1.114 vs edited =====
--- 1.114/kernel/signal.c Mon Apr 19 16:49:52 2004
+++ edited/kernel/signal.c Thu Apr 29 12:52:30 2004
@@ -31,9 +31,6 @@

static kmem_cache_t *sigqueue_cachep;

-atomic_t nr_queued_signals;
-int max_queued_signals = 1024;
-
/*
* In POSIX a signal is sent either to a specific thread (Linux task)
* or to the process as a whole (Linux thread group). How the signal
@@ -264,14 +261,15 @@
return sig;
}

-struct sigqueue *__sigqueue_alloc(void)
+static struct sigqueue *__sigqueue_alloc(void)
{
struct sigqueue *q = 0;

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&current->user->signal_pending) <
+ current->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
if (q) {
- atomic_inc(&nr_queued_signals);
+ atomic_inc(&current->user->signal_pending);
INIT_LIST_HEAD(&q->list);
q->flags = 0;
q->lock = 0;
@@ -279,15 +277,22 @@
return(q);
}

-static inline void __sigqueue_free(struct sigqueue *q)
+static inline void __sigqueue_free(struct task_struct *t, struct sigqueue *q)
{
if (q->flags & SIGQUEUE_PREALLOC)
return;
kmem_cache_free(sigqueue_cachep, q);
- atomic_dec(&nr_queued_signals);
+
+ /*
+ * Decrease per-user sigpending count. Check
+ * for negative value, we might have done setuid()
+ * with pending signals.
+ */
+ if (atomic_read(&t->user->signal_pending) > 0)
+ atomic_dec(&t->user->signal_pending);
}

-static void flush_sigqueue(struct sigpending *queue)
+static void flush_sigqueue(struct task_struct *t, struct sigpending *queue)
{
struct sigqueue *q;

@@ -295,7 +300,7 @@
while (!list_empty(&queue->list)) {
q = list_entry(queue->list.next, struct sigqueue , list);
list_del_init(&q->list);
- __sigqueue_free(q);
+ __sigqueue_free(t, q);
}
}

@@ -310,8 +315,8 @@

spin_lock_irqsave(&t->sighand->siglock, flags);
clear_tsk_thread_flag(t,TIF_SIGPENDING);
- flush_sigqueue(&t->pending);
- flush_sigqueue(&t->signal->shared_pending);
+ flush_sigqueue(t, &t->pending);
+ flush_sigqueue(t, &t->signal->shared_pending);
spin_unlock_irqrestore(&t->sighand->siglock, flags);
}

@@ -353,7 +358,7 @@
sig->curr_target = next_thread(tsk);
tsk->signal = NULL;
spin_unlock(&sighand->siglock);
- flush_sigqueue(&sig->shared_pending);
+ flush_sigqueue(tsk, &sig->shared_pending);
} else {
/*
* If there is any task waiting for the group exit
@@ -370,7 +375,7 @@
sig = NULL; /* Marker for below. */
}
clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
- flush_sigqueue(&tsk->pending);
+ flush_sigqueue(tsk, &tsk->pending);
if (sig) {
/*
* We are cleaning up the signal_struct here. We delayed
@@ -451,7 +456,8 @@
spin_unlock_irqrestore(&current->sighand->siglock, flags);
}

-static inline int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+static inline int collect_signal(int sig, struct task_struct *tsk,
+ struct sigpending *list, siginfo_t *info)
{
struct sigqueue *q, *first = 0;
int still_pending = 0;
@@ -475,7 +481,7 @@
if (first) {
list_del_init(&first->list);
copy_siginfo(info, &first->info);
- __sigqueue_free(first);
+ __sigqueue_free(tsk, first);
if (!still_pending)
sigdelset(&list->signal, sig);
} else {
@@ -494,8 +500,8 @@
return 1;
}

-static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
- siginfo_t *info)
+static int __dequeue_signal(struct task_struct *tsk, struct sigpending *pending,
+ sigset_t *mask, siginfo_t *info)
{
int sig = 0;

@@ -510,7 +516,7 @@
}
}

- if (!collect_signal(sig, pending, info))
+ if (!collect_signal(sig, tsk, pending, info))
sig = 0;

}
@@ -527,9 +533,9 @@
*/
int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
{
- int signr = __dequeue_signal(&tsk->pending, mask, info);
+ int signr = __dequeue_signal(tsk, &tsk->pending, mask, info);
if (!signr)
- signr = __dequeue_signal(&tsk->signal->shared_pending,
+ signr = __dequeue_signal(tsk, &tsk->signal->shared_pending,
mask, info);
if ( signr &&
((info->si_code & __SI_MASK) == __SI_TIMER) &&
@@ -576,7 +582,8 @@
*
* All callers must be holding the siglock.
*/
-static int rm_from_queue(unsigned long mask, struct sigpending *s)
+static int rm_from_queue(unsigned long mask, struct task_struct *t,
+ struct sigpending *s)
{
struct sigqueue *q, *n;

@@ -588,7 +595,7 @@
if (q->info.si_signo < SIGRTMIN &&
(mask & sigmask(q->info.si_signo))) {
list_del_init(&q->list);
- __sigqueue_free(q);
+ __sigqueue_free(t, q);
}
}
return 1;
@@ -634,10 +641,10 @@
/*
* This is a stop signal. Remove SIGCONT from all queues.
*/
- rm_from_queue(sigmask(SIGCONT), &p->signal->shared_pending);
+ rm_from_queue(sigmask(SIGCONT), p, &p->signal->shared_pending);
t = p;
do {
- rm_from_queue(sigmask(SIGCONT), &t->pending);
+ rm_from_queue(sigmask(SIGCONT), t, &t->pending);
t = next_thread(t);
} while (t != p);
} else if (sig == SIGCONT) {
@@ -666,11 +673,11 @@
p->group_leader,
p->group_leader->real_parent);
}
- rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
+ rm_from_queue(SIG_KERNEL_STOP_MASK, p, &p->signal->shared_pending);
t = p;
do {
unsigned int state;
- rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
+ rm_from_queue(SIG_KERNEL_STOP_MASK, t, &t->pending);

/*
* If there is a handler for SIGCONT, we must make
@@ -698,7 +705,8 @@
}
}

-static int send_signal(int sig, struct siginfo *info, struct sigpending *signals)
+static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+ struct sigpending *signals)
{
struct sigqueue * q = NULL;
int ret = 0;
@@ -718,11 +726,13 @@
make sure at least one signal gets delivered and don't
pass on the info struct. */

- if (atomic_read(&nr_queued_signals) < max_queued_signals)
+ if (atomic_read(&t->user->signal_pending) <
+ t->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);

if (q) {
- atomic_inc(&nr_queued_signals);
+ atomic_inc(&t->user->signal_pending);
+
q->flags = 0;
list_add_tail(&q->list, &signals->list);
switch ((unsigned long) info) {
@@ -797,7 +807,7 @@
if (LEGACY_QUEUE(&t->pending, sig))
goto out;

- ret = send_signal(sig, info, &t->pending);
+ ret = send_signal(sig, info, t, &t->pending);
if (!ret && !sigismember(&t->blocked, sig))
signal_wake_up(t, sig == SIGKILL);
out:
@@ -937,8 +947,8 @@
* unchanged from the death state, e.g. which thread had
* the core-dump signal unblocked.
*/
- rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
- rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
+ rm_from_queue(SIG_KERNEL_STOP_MASK, t, &t->pending);
+ rm_from_queue(SIG_KERNEL_STOP_MASK, p, &p->signal->shared_pending);
p->signal->group_stop_count = 0;
p->signal->group_exit_task = t;
t = p;
@@ -998,7 +1008,7 @@
* We always use the shared queue for process-wide signals,
* to avoid several races.
*/
- ret = send_signal(sig, info, &p->signal->shared_pending);
+ ret = send_signal(sig, info, p, &p->signal->shared_pending);
if (unlikely(ret))
return ret;

@@ -1037,7 +1047,7 @@
t->exit_signal = -1;

sigaddset(&t->pending.signal, SIGKILL);
- rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
+ rm_from_queue(SIG_KERNEL_STOP_MASK, t, &t->pending);
signal_wake_up(t, 1);
}
}
@@ -1290,7 +1300,7 @@
read_unlock(&tasklist_lock);
}
q->flags &= ~SIGQUEUE_PREALLOC;
- __sigqueue_free(q);
+ __sigqueue_free(current, q);
}

int
@@ -2328,9 +2338,9 @@
*k = *act;
sigdelsetmask(&k->sa.sa_mask,
sigmask(SIGKILL) | sigmask(SIGSTOP));
- rm_from_queue(sigmask(sig), &t->signal->shared_pending);
+ rm_from_queue(sigmask(sig), t, &t->signal->shared_pending);
do {
- rm_from_queue(sigmask(sig), &t->pending);
+ rm_from_queue(sigmask(sig), t, &t->pending);
recalc_sigpending_tsk(t);
t = next_thread(t);
} while (t != current);
===== kernel/sysctl.c 1.71 vs edited =====
--- 1.71/kernel/sysctl.c Mon Apr 26 22:07:43 2004
+++ edited/kernel/sysctl.c Thu Apr 29 12:22:25 2004
@@ -53,8 +53,6 @@
extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
extern int max_threads;
-extern atomic_t nr_queued_signals;
-extern int max_queued_signals;
extern int sysrq_enabled;
extern int core_uses_pid;
extern char core_pattern[];
@@ -429,22 +427,6 @@
.proc_handler = &proc_dointvec,
},
#endif
- {
- .ctl_name = KERN_RTSIGNR,
- .procname = "rtsig-nr",
- .data = &nr_queued_signals,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = KERN_RTSIGMAX,
- .procname = "rtsig-max",
- .data = &max_queued_signals,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
#ifdef CONFIG_SYSVIPC
{
.ctl_name = KERN_SHMMAX,
===== kernel/user.c 1.8 vs edited =====
--- 1.8/kernel/user.c Fri Aug 1 03:02:22 2003
+++ edited/kernel/user.c Thu Apr 29 12:18:13 2004
@@ -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
};

/*
@@ -97,6 +99,9 @@
atomic_set(&new->__count, 1);
atomic_set(&new->processes, 0);
atomic_set(&new->files, 0);
+ atomic_set(&new->signal_pending, 0);
+
+ new->msg_queues = 0;

/*
* Before adding this, check whether we raced