Re: message queue limits

From: Marcelo Tosatti
Date: Thu Apr 15 2004 - 19:46:19 EST



Hi Andrew!

On Thu, Apr 15, 2004 at 03:54:08PM -0700, Andrew Morton wrote:
> Marcelo Tosatti <marcelo.tosatti@xxxxxxxxxxxx> wrote:
> >
> > This adds a new "RLIMIT_SIGPENDING" limit, which is used to limit
> > per-uid pending signals. Currently an unpriviledged user can queue
> > more than maximum of allowed signals and cause overall system
> > malfunction.
>
> So now it takes two users to gang up and do the same thing.

Decrease rlim_cur then. Usually people dont have several accounts
on the same box.

> We should either exempt root from the global check or simply remove the global > limit
> altogether.

Then allow for unlimited pending signals? Are you sure?

> Is it possible for a process to do setuid() with outstanding signals? If
> so, they may end up with a negative current->user->signal_pending?

Nice catch, root can do that and I think current->user->signal_pending can get
negative. Not completly sure though.

> You need to initialise ->signal_pending in alloc_uid().

--- signal.c.orig 2004-04-15 20:44:17.458438104 -0300
+++ signal.c 2004-04-15 20:45:36.850368696 -0300
@@ -288,7 +288,8 @@
return;
kmem_cache_free(sigqueue_cachep, q);
atomic_dec(&nr_queued_signals);
- atomic_dec(&current->user->signal_pending);
+ if (atomic_read(&current->user->signal_pending) > 0)
+ atomic_dec(&current->user->signal_pending);
}

static void flush_sigqueue(struct sigpending *queue)
--- user.c.orig 2004-04-15 20:44:20.395991528 -0300
+++ user.c 2004-04-15 20:44:37.069456776 -0300
@@ -98,6 +98,7 @@
atomic_set(&new->__count, 1);
atomic_set(&new->processes, 0);
atomic_set(&new->files, 0);
+ atomic_set(&new->signal_pending, 0);

/*
* Before adding this, check whether we raced

> What are you doing for testing of this?

Simple app posted by Nikita (attached) together with MySQL and
sql-bench for creating mysql threads.
The setuid() was added by me now.

#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
sigset_t set;
int i;
pid_t pid;

sigemptyset(&set);
sigaddset(&set, 40);
sigprocmask(SIG_BLOCK, &set, 0);

pid = getpid();
for (i = 0; i < 1024; i++)
kill(pid, 40);

setuid(500);

while (1)
sleep(1);
}