Commit 61c8504c authored by J. Bruce Fields's avatar J. Bruce Fields

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: default avatarJ. Bruce Fields <bfields@redhat.com>
parent b8548894
...@@ -167,6 +167,7 @@ svc_pool_map_alloc_arrays(struct svc_pool_map *m, unsigned int maxpools) ...@@ -167,6 +167,7 @@ svc_pool_map_alloc_arrays(struct svc_pool_map *m, unsigned int maxpools)
fail_free: fail_free:
kfree(m->to_pool); kfree(m->to_pool);
m->to_pool = NULL;
fail: fail:
return -ENOMEM; return -ENOMEM;
} }
...@@ -287,7 +288,9 @@ svc_pool_map_put(void) ...@@ -287,7 +288,9 @@ svc_pool_map_put(void)
if (!--m->count) { if (!--m->count) {
m->mode = SVC_POOL_DEFAULT; m->mode = SVC_POOL_DEFAULT;
kfree(m->to_pool); kfree(m->to_pool);
m->to_pool = NULL;
kfree(m->pool_to); kfree(m->pool_to);
m->pool_to = NULL;
m->npools = 0; m->npools = 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment