diff options
author | J. Bruce Fields <bfields@redhat.com> | 2019-06-05 18:03:52 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2019-07-03 17:52:09 -0400 |
commit | 689d7ba4895b803244f596e56ffa3d9e4f24acdc (patch) | |
tree | bb66f63cdc792f2a297255fb86518d13d6a77e65 /fs/nfsd | |
parent | 30498dcc12e5fd0aa7395ef80da8466854ff6a41 (diff) |
nfsd: fix cleanup of nfsd_reply_cache_init on failure
The failure to unregister the shrinker results will result in corruption
when the nfsd_net is freed.
Also clean up the drc_slab while we're here.
Reported-by: syzbot+83a43746cebef3508b49@syzkaller.appspotmail.com
Fixes: db17b61765c2 ("nfsd4: drc containerization")
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfscache.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index b774306d1289..26ad75ae2be0 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -157,12 +157,12 @@ int nfsd_reply_cache_init(struct nfsd_net *nn) nn->nfsd_reply_cache_shrinker.seeks = 1; status = register_shrinker(&nn->nfsd_reply_cache_shrinker); if (status) - return status; + goto out_nomem; nn->drc_slab = kmem_cache_create("nfsd_drc", sizeof(struct svc_cacherep), 0, 0, NULL); if (!nn->drc_slab) - goto out_nomem; + goto out_shrinker; nn->drc_hashtbl = kcalloc(hashsize, sizeof(*nn->drc_hashtbl), GFP_KERNEL); @@ -170,7 +170,7 @@ int nfsd_reply_cache_init(struct nfsd_net *nn) nn->drc_hashtbl = vzalloc(array_size(hashsize, sizeof(*nn->drc_hashtbl))); if (!nn->drc_hashtbl) - goto out_nomem; + goto out_slab; } for (i = 0; i < hashsize; i++) { @@ -180,6 +180,10 @@ int nfsd_reply_cache_init(struct nfsd_net *nn) nn->drc_hashsize = hashsize; return 0; +out_slab: + kmem_cache_destroy(nn->drc_slab); +out_shrinker: + unregister_shrinker(&nn->nfsd_reply_cache_shrinker); out_nomem: printk(KERN_ERR "nfsd: failed to allocate reply cache\n"); return -ENOMEM; |