summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2011-11-01 13:07:41 -0700
committerBrian Behlendorf <[email protected]>2011-11-03 10:15:39 -0700
commit6a95d0b74c2951f0dc82361ea279f64a7349f060 (patch)
tree1401df8a79823003f52821d83ac274c5365864e9
parenta7b125e9a577cbf66ddbd7cf9701028ff150ee8e (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 zpl_putpage() 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]> Issue #287
-rw-r--r--module/zfs/zpl_file.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c
index af46afddf..298c0b62d 100644
--- a/module/zfs/zpl_file.c
+++ b/module/zfs/zpl_file.c
@@ -324,9 +324,13 @@ zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data)
* the VM might try to write out additional pages by calling
* zpl_putpage() again resulting in a deadlock.
*/
- current->flags |= PF_MEMALLOC;
- (void) zfs_putpage(mapping->host, pp, wbc);
- current->flags &= ~PF_MEMALLOC;
+ if (current->flags & PF_MEMALLOC) {
+ (void) zfs_putpage(mapping->host, pp, wbc);
+ } else {
+ current->flags |= PF_MEMALLOC;
+ (void) zfs_putpage(mapping->host, pp, wbc);
+ current->flags &= ~PF_MEMALLOC;
+ }
return (0);
}