diff options
author | David Howells <dhowells@redhat.com> | 2019-08-22 13:28:43 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-08-22 13:33:26 +0100 |
commit | a5fb8e6c02d6a518fb2b1a2b8c2471fa77b69436 (patch) | |
tree | 789dd4ce9ffac3d52183dcd1df3b1dc8260549a0 /fs/afs | |
parent | d1abaeb3be7b5fa6d7a1fbbd2e14e3310005c4c1 (diff) | |
download | linux-stable-a5fb8e6c02d6a518fb2b1a2b8c2471fa77b69436.tar.gz linux-stable-a5fb8e6c02d6a518fb2b1a2b8c2471fa77b69436.tar.bz2 linux-stable-a5fb8e6c02d6a518fb2b1a2b8c2471fa77b69436.zip |
afs: Fix leak in afs_lookup_cell_rcu()
Fix a leak on the cell refcount in afs_lookup_cell_rcu() due to
non-clearance of the default error in the case a NULL cell name is passed
and the workstation default cell is used.
Also put a bit at the end to make sure we don't leak a cell ref if we're
going to be returning an error.
This leak results in an assertion like the following when the kafs module is
unloaded:
AFS: Assertion failed
2 == 1 is false
0x2 == 0x1 is false
------------[ cut here ]------------
kernel BUG at fs/afs/cell.c:770!
...
RIP: 0010:afs_manage_cells+0x220/0x42f [kafs]
...
process_one_work+0x4c2/0x82c
? pool_mayday_timeout+0x1e1/0x1e1
? do_raw_spin_lock+0x134/0x175
worker_thread+0x336/0x4a6
? rescuer_thread+0x4af/0x4af
kthread+0x1de/0x1ee
? kthread_park+0xd4/0xd4
ret_from_fork+0x24/0x30
Fixes: 989782dcdc91 ("afs: Overhaul cell database management")
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs')
-rw-r--r-- | fs/afs/cell.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index a2a87117d262..fd5133e26a38 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c @@ -74,6 +74,7 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net, cell = rcu_dereference_raw(net->ws_cell); if (cell) { afs_get_cell(cell); + ret = 0; break; } ret = -EDESTADDRREQ; @@ -108,6 +109,9 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net, done_seqretry(&net->cells_lock, seq); + if (ret != 0 && cell) + afs_put_cell(net, cell); + return ret == 0 ? cell : ERR_PTR(ret); } |