summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2011-11-01 13:35:12 -0700
committerBrian Behlendorf <[email protected]>2011-11-03 09:50:22 -0700
commitb8b6e4c453929596b630fa1cca1ee26a532a2ab4 (patch)
tree8da18ee0bd93b259a3f0366826f2ee11962adaf9
parent16952a68f25d55da21578f562b3813559fd01c6b (diff)
Fix NULL deref in balance_pgdat()
Be careful not to unconditionally clear the PF_MEMALLOC bit in the task structure. It may have already been set when entering kv_alloc() in which case it must remain set on exit. In particular the kswapd thread will have PF_MEMALLOC set in order to prevent it from entering direct reclaim. By clearing it we allow the following NULL deref to potentially occur. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<ffffffff8109c7ab>] balance_pgdat+0x25b/0x4ff Signed-off-by: Brian Behlendorf <[email protected]> Closes ZFS issue #287
-rw-r--r--module/spl/spl-kmem.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c
index db009614f..b3c054a95 100644
--- a/module/spl/spl-kmem.c
+++ b/module/spl/spl-kmem.c
@@ -855,14 +855,17 @@ kv_alloc(spl_kmem_cache_t *skc, int size, int flags)
* been filed at kernel.org to track the issue.
*
* https://bugzilla.kernel.org/show_bug.cgi?id=30702
+ *
+ * NOTE: Only set PF_MEMALLOC if it's not already set, and
+ * then only clear it when we were the one who set it.
*/
- if (!(flags & __GFP_FS))
+ if (!(flags & __GFP_FS) && !(current->flags & PF_MEMALLOC)) {
current->flags |= PF_MEMALLOC;
-
- ptr = __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL);
-
- if (!(flags & __GFP_FS))
+ ptr = __vmalloc(size, flags|__GFP_HIGHMEM, PAGE_KERNEL);
current->flags &= ~PF_MEMALLOC;
+ } else {
+ ptr = __vmalloc(size, flags|__GFP_HIGHMEM, PAGE_KERNEL);
+ }
}
/* Resulting allocated memory will be page aligned */