[PATCH] cpuset exit NULL dereference fix
authorPaul Jackson <pj@sgi.com>
Fri, 27 May 2005 09:02:43 +0000 (02:02 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 27 May 2005 15:07:26 +0000 (08:07 -0700)
commit2efe86b809d97debaaf9fcc13b041aedf15bd3d2
tree87e039397918f4c5b0a21d798589a8ce517bfa2d
parent88c1834633341bbb94e315433067496338bff4ad
[PATCH] cpuset exit NULL dereference fix

There is a race in the kernel cpuset code, between the code
to handle notify_on_release, and the code to remove a cpuset.
The notify_on_release code can end up trying to access a
cpuset that has been removed.  In the most common case, this
causes a NULL pointer dereference from the routine cpuset_path.
However all manner of bad things are possible, in theory at least.

The existing code decrements the cpuset use count, and if the
count goes to zero, processes the notify_on_release request,
if appropriate.  However, once the count goes to zero, unless we
are holding the global cpuset_sem semaphore, there is nothing to
stop another task from immediately removing the cpuset entirely,
and recycling its memory.

The obvious fix would be to always hold the cpuset_sem
semaphore while decrementing the use count and dealing with
notify_on_release.  However we don't want to force a global
semaphore into the mainline task exit path, as that might create
a scaling problem.

The actual fix is almost as easy - since this is only an issue
for cpusets using notify_on_release, which the top level big
cpusets don't normally need to use, only take the cpuset_sem
for cpusets using notify_on_release.

This code has been run for hours without a hiccup, while running
a cpuset create/destroy stress test that could crash the existing
kernel in seconds.  This patch applies to the current -linus
git kernel.

Signed-off-by: Paul Jackson <pj@sgi.com>
Acked-by: Simon Derr <simon.derr@bull.net>
Acked-by: Dinakar Guniguntala <dino@in.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
kernel/cpuset.c