* [PATCH] per-user signal pending and message queue limits
@ 2004-04-19 21:28 Marcelo Tosatti
2004-04-19 22:49 ` Jakub Jelinek
2004-04-19 22:59 ` Andrew Morton
0 siblings, 2 replies; 21+ messages in thread
From: Marcelo Tosatti @ 2004-04-19 21:28 UTC (permalink / raw)
To: akpm; +Cc: drepper, manfred, linux-kernel
(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(¤t->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(¤t->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(¤t->user->signal_pending) > 0)
+ atomic_dec(¤t->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(¤t->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(¤t->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 -----
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH] per-user signal pending and message queue limits 2004-04-19 21:28 [PATCH] per-user signal pending and message queue limits Marcelo Tosatti @ 2004-04-19 22:49 ` Jakub Jelinek 2004-04-20 14:13 ` Marcelo Tosatti 2004-04-19 22:59 ` Andrew Morton 1 sibling, 1 reply; 21+ messages in thread From: Jakub Jelinek @ 2004-04-19 22:49 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: akpm, drepper, manfred, linux-kernel 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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-19 22:49 ` Jakub Jelinek @ 2004-04-20 14:13 ` Marcelo Tosatti 2004-04-20 18:05 ` Manfred Spraul 2004-04-20 20:04 ` Andrew Morton 0 siblings, 2 replies; 21+ messages in thread From: Marcelo Tosatti @ 2004-04-20 14:13 UTC (permalink / raw) To: Jakub Jelinek; +Cc: akpm, drepper, manfred, linux-kernel 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(¤t->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(¤t->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(¤t->user->signal_pending) > 0) + atomic_dec(¤t->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(¤t->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(¤t->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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-20 14:13 ` Marcelo Tosatti @ 2004-04-20 18:05 ` Manfred Spraul 2004-04-20 20:04 ` Andrew Morton 1 sibling, 0 replies; 21+ messages in thread From: Manfred Spraul @ 2004-04-20 18:05 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: Jakub Jelinek, akpm, drepper, linux-kernel 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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-20 14:13 ` Marcelo Tosatti 2004-04-20 18:05 ` Manfred Spraul @ 2004-04-20 20:04 ` Andrew Morton 2004-04-20 23:13 ` Marcelo Tosatti 1 sibling, 1 reply; 21+ messages in thread From: Andrew Morton @ 2004-04-20 20:04 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: jakub, drepper, manfred, linux-kernel Marcelo Tosatti <marcelo.tosatti@cyclades.com> 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 ;) ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-20 20:04 ` Andrew Morton @ 2004-04-20 23:13 ` Marcelo Tosatti 2004-04-20 23:34 ` Andrew Morton 0 siblings, 1 reply; 21+ messages in thread From: Marcelo Tosatti @ 2004-04-20 23:13 UTC (permalink / raw) To: Andrew Morton; +Cc: manfred, drepper, linux-kernel On Tue, Apr 20, 2004 at 01:04:39PM -0700, Andrew Morton wrote: > Marcelo Tosatti <marcelo.tosatti@cyclades.com> 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. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-20 23:13 ` Marcelo Tosatti @ 2004-04-20 23:34 ` Andrew Morton 2004-04-21 20:34 ` Marcelo Tosatti 0 siblings, 1 reply; 21+ messages in thread From: Andrew Morton @ 2004-04-20 23:34 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: manfred, drepper, linux-kernel Marcelo Tosatti <marcelo.tosatti@cyclades.com> 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. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-20 23:34 ` Andrew Morton @ 2004-04-21 20:34 ` Marcelo Tosatti 2004-04-22 5:33 ` Manfred Spraul 0 siblings, 1 reply; 21+ messages in thread From: Marcelo Tosatti @ 2004-04-21 20:34 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, manfred, Jakub Jelinek On Tue, Apr 20, 2004 at 04:34:43PM -0700, Andrew Morton wrote: > Marcelo Tosatti <marcelo.tosatti@cyclades.com> 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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-21 20:34 ` Marcelo Tosatti @ 2004-04-22 5:33 ` Manfred Spraul 2004-04-27 14:54 ` Marcelo Tosatti 0 siblings, 1 reply; 21+ messages in thread From: Manfred Spraul @ 2004-04-22 5:33 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: Andrew Morton, linux-kernel, Jakub Jelinek 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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-22 5:33 ` Manfred Spraul @ 2004-04-27 14:54 ` Marcelo Tosatti 2004-04-27 18:09 ` Manfred Spraul 0 siblings, 1 reply; 21+ messages in thread From: Marcelo Tosatti @ 2004-04-27 14:54 UTC (permalink / raw) To: Manfred Spraul; +Cc: Andrew Morton, linux-kernel, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 31148 bytes --] 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(¤t->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(¤t->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(¤t->user->signal_pending) > 0) + atomic_dec(¤t->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(¤t->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(¤t->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 [-- Attachment #2: mqsend.c --] [-- Type: text/plain, Size: 1712 bytes --] #include <sys/types.h> #include <sys/socket.h> #include <sys/syscall.h> #include <unistd.h> #include <stdio.h> #include <limits.h> #include <stdarg.h> #include <errno.h> #include <string.h> #include <poll.h> #include <asm/fcntl.h> #define __NR_mq_open 277 #define __NR_mq_unlink 278 #define __NR_mq_timedsend 279 #define __NR_mq_timedreceive 280 #define __NR_mq_notify 281 #define __NR_mq_getsetattr 282 typedef int mdq_t; struct mq_attr { long mq_flags; long mq_maxmsg; long mq_msgsize; long mq_curmsgs; long __reserved[4]; }; static inline int __mq_open (const char *name, int oflag, mode_t mode, struct mq_attr *attr) { return syscall(__NR_mq_open, name, oflag, mode, attr); } static inline int __mq_timedsend(mdq_t mqdes, const char *msg_ptr, size_t msglen, unsigned int msgprio, const struct timespec *abs_timeout) { return syscall( __NR_mq_timedsend, mqdes, msg_ptr, msglen, msgprio, abs_timeout); } static int mq_send(mdq_t des, const char *msgptr, size_t msglen, unsigned int msgprio) { return __mq_timedsend(des, msgptr, msglen, msgprio, NULL); } mdq_t mq_open(const char *name, int oflag, ...) { unsigned long mode; struct mq_attr *attr; va_list ap; va_start(ap, oflag); mode = va_arg(ap, unsigned long); attr = va_arg(ap, struct mq_attr *); va_end(ap); return __mq_open(name, oflag, mode, attr); } #define PRIO 1 #define QUEUE "/mnt/example_queue" void main() { mdq_t ds; char text[] = "Our message body!"; ds = open(QUEUE, O_WRONLY|O_CREAT); if (ds == -1) { perror("Opening queue error\n"); exit(1); } if (mq_send(ds, text, strlen(text), PRIO) == -1) perror("Sendong message error"); else puts("Message sent to queue"); return 0; } [-- Attachment #3: mqrec.c --] [-- Type: text/plain, Size: 2130 bytes --] #include <sys/types.h> #include <sys/socket.h> #include <sys/syscall.h> #include <unistd.h> #include <stdio.h> #include <limits.h> #include <stdarg.h> #include <errno.h> #include <string.h> #include <poll.h> #include <asm/fcntl.h> #define __NR_mq_open 277 #define __NR_mq_unlink 278 #define __NR_mq_timedsend 279 #define __NR_mq_timedreceive 280 #define __NR_mq_notify 281 #define __NR_mq_getsetattr 282 typedef int mdq_t; struct mq_attr { long mq_flags; long mq_maxmsg; long mq_msgsize; long mq_curmsgs; long __reserved[4]; }; static inline int __mq_open (const char *name, int oflag, mode_t mode, struct mq_attr *attr) { return syscall(__NR_mq_open, name, oflag, mode, attr); } static inline int __mq_timedreceive(mdq_t des, char *msgptr, size_t msglen, unsigned int *msgprio, const struct timespec *abs_timeout) { return syscall(__NR_mq_timedreceive, des, msgptr, msglen, msgprio, abs_timeout); } static inline int __mq_timedsend(mdq_t mqdes, const char *msg_ptr, size_t msglen, unsigned int msgprio, const struct timespec *abs_timeout) { return(syscall, __NR_mq_timedsend, mqdes, msg_ptr, msglen, msgprio, abs_timeout); } static int mq_send(mdq_t des, const char *msgptr, size_t msglen, unsigned int msgprio) { return __mq_timedsend(des, msgptr, msglen, msgprio, NULL); } ssize_t mq_receive(mdq_t des, char *msgptr, size_t msglen, unsigned int *msgprio) { return __mq_timedreceive(des, msgptr, msglen, msgprio, NULL); } mdq_t mq_open(const char *name, int oflag, ...) { unsigned long mode; struct mq_attr *attr; va_list ap; va_start(ap, oflag); mode = va_arg(ap, unsigned long); attr = va_arg(ap, struct mq_attr *); va_end(ap); return __mq_open(name, oflag, mode, attr); } #define PRIO 1 #define QUEUE "/mnt/example_queue" #define SIZE 17000 void main() { mdq_t ds; char text[SIZE]; unsigned int msg_prio = 1; ds = open(QUEUE, O_RDONLY|O_CREAT); if (ds == -1) { perror("Opening queue error\n"); exit(1); } if (mq_receive(ds, text, SIZE, &msg_prio) == -1) perror("Receiving message error"); else printf("Message received: %s\n", text); return 0; } ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-27 14:54 ` Marcelo Tosatti @ 2004-04-27 18:09 ` Manfred Spraul 2004-04-28 17:09 ` Marcelo Tosatti 0 siblings, 1 reply; 21+ messages in thread From: Manfred Spraul @ 2004-04-27 18:09 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: Andrew Morton, linux-kernel, Jakub Jelinek 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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-27 18:09 ` Manfred Spraul @ 2004-04-28 17:09 ` Marcelo Tosatti 2004-04-28 21:03 ` Andrew Morton 2004-04-29 1:33 ` Chris Wright 0 siblings, 2 replies; 21+ messages in thread From: Marcelo Tosatti @ 2004-04-28 17:09 UTC (permalink / raw) To: Manfred Spraul; +Cc: Andrew Morton, linux-kernel, Jakub Jelinek 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(¤t->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(¤t->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(¤t->user->signal_pending) > 0) + atomic_dec(¤t->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(¤t->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(¤t->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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-28 17:09 ` Marcelo Tosatti @ 2004-04-28 21:03 ` Andrew Morton 2004-04-29 1:33 ` Chris Wright 1 sibling, 0 replies; 21+ messages in thread From: Andrew Morton @ 2004-04-28 21:03 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: manfred, linux-kernel, jakub, Ingo Molnar Marcelo Tosatti <marcelo.tosatti@cyclades.com> 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: _ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-28 17:09 ` Marcelo Tosatti 2004-04-28 21:03 ` Andrew Morton @ 2004-04-29 1:33 ` Chris Wright 2004-04-29 12:17 ` Marcelo Tosatti 1 sibling, 1 reply; 21+ messages in thread From: Chris Wright @ 2004-04-29 1:33 UTC (permalink / raw) To: Marcelo Tosatti Cc: Manfred Spraul, Andrew Morton, linux-kernel, Jakub Jelinek * Marcelo Tosatti (marcelo.tosatti@cyclades.com) 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(¤t->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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-29 1:33 ` Chris Wright @ 2004-04-29 12:17 ` Marcelo Tosatti 2004-04-29 19:58 ` Chris Wright 0 siblings, 1 reply; 21+ messages in thread From: Marcelo Tosatti @ 2004-04-29 12:17 UTC (permalink / raw) To: Chris Wright; +Cc: Manfred Spraul, Andrew Morton, linux-kernel, Jakub Jelinek On Wed, Apr 28, 2004 at 06:33:15PM -0700, Chris Wright wrote: > * Marcelo Tosatti (marcelo.tosatti@cyclades.com) 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(¤t->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!! ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-29 12:17 ` Marcelo Tosatti @ 2004-04-29 19:58 ` Chris Wright 2004-05-06 0:08 ` Chris Wright 0 siblings, 1 reply; 21+ messages in thread From: Chris Wright @ 2004-04-29 19:58 UTC (permalink / raw) To: Marcelo Tosatti Cc: Chris Wright, Manfred Spraul, Andrew Morton, linux-kernel, Jakub Jelinek * Marcelo Tosatti (marcelo.tosatti@cyclades.com) wrote: > On Wed, Apr 28, 2004 at 06:33:15PM -0700, Chris Wright wrote: > > * Marcelo Tosatti (marcelo.tosatti@cyclades.com) 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(¤t->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(¤t->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(¤t->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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-29 19:58 ` Chris Wright @ 2004-05-06 0:08 ` Chris Wright 2004-05-06 12:09 ` Marcelo Tosatti 2004-05-06 12:32 ` Marcelo Tosatti 0 siblings, 2 replies; 21+ messages in thread From: Chris Wright @ 2004-05-06 0:08 UTC (permalink / raw) To: linux-kernel Cc: Marcelo Tosatti, Manfred Spraul, Andrew Morton, Jakub Jelinek, Chris Wright * Chris Wright (chrisw@osdl.org) wrote: > OK, here it is. That last patch left the mqueue rlimit bits alone (was only an update to the signal side). After looking more closely at the mqueue side I have the comments below: > --- 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 */ Just cache user directly. > 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; Below there's some inconsistent usage of p and current (just a cleanliness issue). > 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; This leaks the newly allocated inode. Also, it could fail even though the user was trying to allocate something smaller via mq_open() with an mq_attr which it had space for. > 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(); This BUG() is too easy to trigger, e.g. user creates mqueue, logs out, root comes by later and cleans up...BUG(). Simply caching user directly eliminates this altogether. > 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; Some inconsistent use of p and current below. > 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) Hrm, this thing can overflow. Seems like the hard maxes should be smaller. As it stands, looks like the hard max mq_msgsize that root could setup is INT_MAX. > + 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); This path means the user is penalized for the mq_attr sized accounting, plus the default sized accounting which happens later in mqueue_get_inode(). It is removed below, but as mentioned above, this could incorrectly cause mq_open() to fail. > } 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; Oops, I think the subtraction is slightly wrong here. Should be before the info->attr is updated, else you are actually carrying accounting for the default size (minus the actually allocated size). Should be subtracting off the recently added default size. New patch below (based on 2.6.6-rc3-bk). Couple known issues are the possible mq_bytes caluclation overflow (not yet fixed in this patch), and setuid issue on signal side. All other known issues have been addressed. 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 Tue May 4 23:15:08 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 Tue May 4 23:15:08 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 Tue May 4 23:15:09 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 Tue May 4 23:15:09 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 Tue May 4 23:15:09 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 Tue May 4 23:15:09 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 Tue May 4 23:15:09 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 Tue May 4 23:15:09 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 Tue May 4 23:15:10 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 Tue May 4 23:15:10 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 Tue May 4 23:15:10 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 Tue May 4 23:15:10 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 Tue May 4 23:15:11 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 Tue May 4 23:15:11 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 Tue May 4 23:15:11 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 Tue May 4 23:15:11 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 Tue May 4 23:15:11 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 Tue May 4 23:15:11 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 Tue May 4 23:15:11 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 Tue May 4 23:15:12 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 Tue May 4 23:15: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 Tue May 4 23:15:13 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.11 vs edited ===== --- 1.11/ipc/mqueue.c Tue May 4 15:16:34 2004 +++ edited/ipc/mqueue.c Wed May 5 16:39:56 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; + struct user_struct *user; /* user who created, for accouting */ struct sock *notify_sock; struct sk_buff *notify_cookie; @@ -97,7 +97,8 @@ return container_of(inode, struct mqueue_inode_info, vfs_inode); } -static struct inode *mqueue_get_inode(struct super_block *sb, int mode) +static struct inode *mqueue_get_inode(struct super_block *sb, int mode, + struct mq_attr *attr) { struct inode *inode; @@ -113,6 +114,9 @@ if (S_ISREG(mode)) { struct mqueue_inode_info *info; + struct task_struct *p = current; + struct user_struct *u = p->user; + unsigned long mq_bytes, mq_maxmsg_bytes; inode->i_fop = &mqueue_file_operations; inode->i_size = FILENT_SIZE; @@ -122,17 +126,40 @@ init_waitqueue_head(&info->wait_q); INIT_LIST_HEAD(&info->e_wait_q[0].list); INIT_LIST_HEAD(&info->e_wait_q[1].list); + info->messages = NULL; info->notify_owner = 0; info->qsize = 0; + info->user = NULL; /* set when all is ok */ memset(&info->attr, 0, sizeof(info->attr)); info->attr.mq_maxmsg = DFLT_MSGMAX; info->attr.mq_msgsize = DFLT_MSGSIZEMAX; - info->messages = kmalloc(DFLT_MSGMAX * sizeof(struct msg_msg *), GFP_KERNEL); + if (attr) { + info->attr.mq_maxmsg = attr->mq_maxmsg; + info->attr.mq_msgsize = attr->mq_msgsize; + } + mq_maxmsg_bytes = info->attr.mq_maxmsg * sizeof(struct msg_msg *); + mq_bytes = (mq_maxmsg_bytes + + (info->attr.mq_maxmsg * info->attr.mq_msgsize)); + + spin_lock(&mq_lock); + if (u->msg_queues + mq_bytes >= + p->rlim[RLIMIT_MSGQUEUE].rlim_cur) { + spin_unlock(&mq_lock); + goto out_inode; + } + u->msg_queues += mq_bytes; + spin_unlock(&mq_lock); + + info->messages = kmalloc(mq_maxmsg_bytes, GFP_KERNEL); if (!info->messages) { - make_bad_inode(inode); - iput(inode); - inode = NULL; + spin_lock(&mq_lock); + u->msg_queues -= mq_bytes; + spin_unlock(&mq_lock); + goto out_inode; } + /* all is ok */ + atomic_inc(&u->__count); + info->user = u; } else if (S_ISDIR(mode)) { inode->i_nlink++; /* Some things misbehave if size == 0 on a directory */ @@ -142,6 +169,10 @@ } } return inode; +out_inode: + make_bad_inode(inode); + iput(inode); + return NULL; } static int mqueue_fill_super(struct super_block *sb, void *data, int silent) @@ -153,7 +184,7 @@ sb->s_magic = MQUEUE_MAGIC; sb->s_op = &mqueue_super_ops; - inode = mqueue_get_inode(sb, S_IFDIR | S_ISVTX | S_IRWXUGO); + inode = mqueue_get_inode(sb, S_IFDIR | S_ISVTX | S_IRWXUGO, NULL); if (!inode) return -ENOMEM; @@ -200,6 +231,8 @@ static void mqueue_delete_inode(struct inode *inode) { struct mqueue_inode_info *info; + struct user_struct *user; + unsigned long mq_bytes; int i; if (S_ISDIR(inode->i_mode)) { @@ -215,10 +248,15 @@ clear_inode(inode); - if (info->messages) { + mq_bytes = (info->attr.mq_maxmsg * sizeof(struct msg_msg *) + + (info->attr.mq_maxmsg * info->attr.mq_msgsize)); + user = info->user; + if (user) { spin_lock(&mq_lock); + user->msg_queues -= mq_bytes; queues_count--; spin_unlock(&mq_lock); + free_uid(user); } } @@ -226,6 +264,7 @@ int mode, struct nameidata *nd) { struct inode *inode; + struct mq_attr *attr = dentry->d_fsdata; int error; spin_lock(&mq_lock); @@ -236,7 +275,7 @@ queues_count++; spin_unlock(&mq_lock); - inode = mqueue_get_inode(dir->i_sb, mode); + inode = mqueue_get_inode(dir->i_sb, mode, attr); if (!inode) { error = -ENOMEM; spin_lock(&mq_lock); @@ -535,9 +574,6 @@ int oflag, mode_t mode, struct mq_attr __user *u_attr) { struct file *filp; - struct inode *inode; - struct mqueue_inode_info *info; - struct msg_msg **msgs = NULL; struct mq_attr attr; int ret; @@ -555,28 +591,14 @@ attr.mq_msgsize > msgsize_max) return ERR_PTR(-EINVAL); } - msgs = kmalloc(attr.mq_maxmsg * sizeof(*msgs), GFP_KERNEL); - if (!msgs) - return ERR_PTR(-ENOMEM); - } else { - msgs = NULL; + /* store for use during create */ + dentry->d_fsdata = &attr; } ret = vfs_create(dir->d_inode, dentry, mode, NULL); - if (ret) { - kfree(msgs); + dentry->d_fsdata = NULL; + if (ret) return ERR_PTR(ret); - } - - inode = dentry->d_inode; - info = MQUEUE_I(inode); - - if (msgs) { - info->attr.mq_maxmsg = attr.mq_maxmsg; - info->attr.mq_msgsize = attr.mq_msgsize; - kfree(info->messages); - info->messages = msgs; - } filp = dentry_open(dentry, mqueue_mnt, oflag); if (!IS_ERR(filp)) ===== kernel/signal.c 1.114 vs edited ===== --- 1.114/kernel/signal.c Mon Apr 19 16:49:52 2004 +++ edited/kernel/signal.c Tue May 4 23:15:15 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(¤t->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(¤t->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(¤t->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 Tue May 4 23:15:16 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 Tue May 4 23:15:16 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 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-05-06 0:08 ` Chris Wright @ 2004-05-06 12:09 ` Marcelo Tosatti 2004-05-06 12:32 ` Marcelo Tosatti 1 sibling, 0 replies; 21+ messages in thread From: Marcelo Tosatti @ 2004-05-06 12:09 UTC (permalink / raw) To: Chris Wright; +Cc: linux-kernel, Manfred Spraul, Andrew Morton, Jakub Jelinek On Wed, May 05, 2004 at 05:08:11PM -0700, Chris Wright wrote: > * Chris Wright (chrisw@osdl.org) wrote: > > OK, here it is. > > That last patch left the mqueue rlimit bits alone (was only an update to > the signal side). After looking more closely at the mqueue side I have > the comments below: Great, you have gone deeper analysis. This looks much better. Thanks! ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-05-06 0:08 ` Chris Wright 2004-05-06 12:09 ` Marcelo Tosatti @ 2004-05-06 12:32 ` Marcelo Tosatti 2004-05-07 0:56 ` Chris Wright 1 sibling, 1 reply; 21+ messages in thread From: Marcelo Tosatti @ 2004-05-06 12:32 UTC (permalink / raw) To: Chris Wright; +Cc: linux-kernel, Manfred Spraul, Andrew Morton, Jakub Jelinek > This BUG() is too easy to trigger, e.g. user creates mqueue, logs out, > root comes by later and cleans up...BUG(). Simply caching user directly > eliminates this altogether. And with user_struct->__count you deal with that, yes? Caching the user_struct directly is indeed much nicer. > > Some inconsistent use of p and current below. > > > 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) > > Hrm, this thing can overflow. Seems like the hard maxes should be > smaller. As it stands, looks like the hard max mq_msgsize that root > could setup is INT_MAX. Eek. Just decreasing max mq_msgsize to something _much_ smaller is ok, isnt it? Like, say, 64MB. > > + 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); > > This path means the user is penalized for the mq_attr sized accounting, > plus the default sized accounting which happens later in mqueue_get_inode(). > It is removed below, but as mentioned above, this could incorrectly > cause mq_open() to fail. OK! > > } 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; > > Oops, I think the subtraction is slightly wrong here. Should be before > the info->attr is updated, else you are actually carrying accounting for > the default size (minus the actually allocated size). Should be > subtracting off the recently added default size. > > New patch below (based on 2.6.6-rc3-bk). Couple known issues are the > possible mq_bytes caluclation overflow (not yet fixed in this patch), > and setuid issue on signal side. All other known issues have been > addressed. The setuid issue on signal side is pretty harmless though. It only affects the users which are setuid() capable, and which do so with signal pending. I see no other way to fix it than cache the user struct in "struct sigqueue". Thats not good news for performance (not sure how bad it would matter). Again, thanks! ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-05-06 12:32 ` Marcelo Tosatti @ 2004-05-07 0:56 ` Chris Wright 0 siblings, 0 replies; 21+ messages in thread From: Chris Wright @ 2004-05-07 0:56 UTC (permalink / raw) To: Marcelo Tosatti Cc: Chris Wright, linux-kernel, Manfred Spraul, Andrew Morton, Jakub Jelinek * Marcelo Tosatti (marcelo.tosatti@cyclades.com) wrote: > > This BUG() is too easy to trigger, e.g. user creates mqueue, logs out, > > root comes by later and cleans up...BUG(). Simply caching user directly > > eliminates this altogether. > > And with user_struct->__count you deal with that, yes? Yes, exactly. > Caching the user_struct directly is indeed much nicer. > > > Some inconsistent use of p and current below. > > > > > 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) > > > > Hrm, this thing can overflow. Seems like the hard maxes should be > > smaller. As it stands, looks like the hard max mq_msgsize that root > > could setup is INT_MAX. > > Eek. Just decreasing max mq_msgsize to something _much_ smaller is ok, isnt it? > Like, say, 64MB. I think so. I've no idea what a good max is, but last night I simply added some overflow detection to handle this. > > > + 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); > > > > This path means the user is penalized for the mq_attr sized accounting, > > plus the default sized accounting which happens later in mqueue_get_inode(). > > It is removed below, but as mentioned above, this could incorrectly > > cause mq_open() to fail. > > OK! > > > > } 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; > > > > Oops, I think the subtraction is slightly wrong here. Should be before > > the info->attr is updated, else you are actually carrying accounting for > > the default size (minus the actually allocated size). Should be > > subtracting off the recently added default size. > > > > New patch below (based on 2.6.6-rc3-bk). Couple known issues are the > > possible mq_bytes caluclation overflow (not yet fixed in this patch), > > and setuid issue on signal side. All other known issues have been > > addressed. > > The setuid issue on signal side is pretty harmless though. It only affects the > users which are setuid() capable, and which do so with signal pending. Yes. It's part of why I left it for now. > I see no other way to fix it than cache the user struct in "struct sigqueue". > Thats not good news for performance (not sure how bad it would matter). My thoughts exactly. thanks, -chris -- Linux Security Modules http://lsm.immunix.org http://lsm.bkbits.net ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] per-user signal pending and message queue limits 2004-04-19 21:28 [PATCH] per-user signal pending and message queue limits Marcelo Tosatti 2004-04-19 22:49 ` Jakub Jelinek @ 2004-04-19 22:59 ` Andrew Morton 1 sibling, 0 replies; 21+ messages in thread From: Andrew Morton @ 2004-04-19 22:59 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: drepper, manfred, linux-kernel Marcelo Tosatti <marcelo.tosatti@cyclades.com> 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? ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2004-05-07 0:56 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-04-19 21:28 [PATCH] per-user signal pending and message queue limits Marcelo Tosatti 2004-04-19 22:49 ` Jakub Jelinek 2004-04-20 14:13 ` Marcelo Tosatti 2004-04-20 18:05 ` Manfred Spraul 2004-04-20 20:04 ` Andrew Morton 2004-04-20 23:13 ` Marcelo Tosatti 2004-04-20 23:34 ` Andrew Morton 2004-04-21 20:34 ` Marcelo Tosatti 2004-04-22 5:33 ` Manfred Spraul 2004-04-27 14:54 ` Marcelo Tosatti 2004-04-27 18:09 ` Manfred Spraul 2004-04-28 17:09 ` Marcelo Tosatti 2004-04-28 21:03 ` Andrew Morton 2004-04-29 1:33 ` Chris Wright 2004-04-29 12:17 ` Marcelo Tosatti 2004-04-29 19:58 ` Chris Wright 2004-05-06 0:08 ` Chris Wright 2004-05-06 12:09 ` Marcelo Tosatti 2004-05-06 12:32 ` Marcelo Tosatti 2004-05-07 0:56 ` Chris Wright 2004-04-19 22:59 ` Andrew Morton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox