Commit 61c8504c428edcebf23b97775a129c5b393a302b
1 parent
b8548894bd
Exists in
master
and in
6 other branches
svcrpc: fix double-free on shutdown of nfsd after changing pool mode
The pool_to and to_pool fields of the global svc_pool_map are freed on shutdown, but are initialized in nfsd startup only in the SVC_POOL_PERCPU and SVC_POOL_PERNODE cases. They *are* initialized to zero on kernel startup. So as long as you use only SVC_POOL_GLOBAL (the default), this will never be a problem. You're also OK if you only ever use SVC_POOL_PERCPU or SVC_POOL_PERNODE. However, the following sequence events leads to a double-free: 1. set SVC_POOL_PERCPU or SVC_POOL_PERNODE 2. start nfsd: both fields are initialized. 3. shutdown nfsd: both fields are freed. 4. set SVC_POOL_GLOBAL 5. start nfsd: the fields are left untouched. 6. shutdown nfsd: now we try to free them again. Step 4 is actually unnecessary, since (for some bizarre reason), nfsd automatically resets the pool mode to SVC_POOL_GLOBAL on shutdown. Cc: stable@kernel.org Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Showing 1 changed file with 3 additions and 0 deletions Side-by-side Diff
net/sunrpc/svc.c
... | ... | @@ -167,6 +167,7 @@ |
167 | 167 | |
168 | 168 | fail_free: |
169 | 169 | kfree(m->to_pool); |
170 | + m->to_pool = NULL; | |
170 | 171 | fail: |
171 | 172 | return -ENOMEM; |
172 | 173 | } |
173 | 174 | |
... | ... | @@ -287,7 +288,9 @@ |
287 | 288 | if (!--m->count) { |
288 | 289 | m->mode = SVC_POOL_DEFAULT; |
289 | 290 | kfree(m->to_pool); |
291 | + m->to_pool = NULL; | |
290 | 292 | kfree(m->pool_to); |
293 | + m->pool_to = NULL; | |
291 | 294 | m->npools = 0; |
292 | 295 | } |
293 | 296 |