]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.0.18/svcrpc-fix-double-free-on-shutdown-of-nfsd-after-changing-pool-mode.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.0.18 / svcrpc-fix-double-free-on-shutdown-of-nfsd-after-changing-pool-mode.patch
CommitLineData
5e3c2993
GKH
1From 61c8504c428edcebf23b97775a129c5b393a302b Mon Sep 17 00:00:00 2001
2From: "J. Bruce Fields" <bfields@redhat.com>
3Date: Thu, 22 Dec 2011 18:22:49 -0700
4Subject: svcrpc: fix double-free on shutdown of nfsd after changing pool mode
5
6From: "J. Bruce Fields" <bfields@redhat.com>
7
8commit 61c8504c428edcebf23b97775a129c5b393a302b upstream.
9
10The pool_to and to_pool fields of the global svc_pool_map are freed on
11shutdown, but are initialized in nfsd startup only in the
12SVC_POOL_PERCPU and SVC_POOL_PERNODE cases.
13
14They *are* initialized to zero on kernel startup. So as long as you use
15only SVC_POOL_GLOBAL (the default), this will never be a problem.
16
17You're also OK if you only ever use SVC_POOL_PERCPU or SVC_POOL_PERNODE.
18
19However, the following sequence events leads to a double-free:
20
21 1. set SVC_POOL_PERCPU or SVC_POOL_PERNODE
22 2. start nfsd: both fields are initialized.
23 3. shutdown nfsd: both fields are freed.
24 4. set SVC_POOL_GLOBAL
25 5. start nfsd: the fields are left untouched.
26 6. shutdown nfsd: now we try to free them again.
27
28Step 4 is actually unnecessary, since (for some bizarre reason), nfsd
29automatically resets the pool mode to SVC_POOL_GLOBAL on shutdown.
30
31Signed-off-by: J. Bruce Fields <bfields@redhat.com>
32Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
33
34---
35 net/sunrpc/svc.c | 3 +++
36 1 file changed, 3 insertions(+)
37
38--- a/net/sunrpc/svc.c
39+++ b/net/sunrpc/svc.c
40@@ -167,6 +167,7 @@ svc_pool_map_alloc_arrays(struct svc_poo
41
42 fail_free:
43 kfree(m->to_pool);
44+ m->to_pool = NULL;
45 fail:
46 return -ENOMEM;
47 }
48@@ -287,7 +288,9 @@ svc_pool_map_put(void)
49 if (!--m->count) {
50 m->mode = SVC_POOL_DEFAULT;
51 kfree(m->to_pool);
52+ m->to_pool = NULL;
53 kfree(m->pool_to);
54+ m->pool_to = NULL;
55 m->npools = 0;
56 }
57