scoutfs: remove lock idr in free, not put

The idr entry that identifies a lock's position in the debugfs locks
file is allocated early in the process of building up a lock.  Today the
idr entry is only destroyed in put_(), which is called later once
reference counts are established.  Errors before then just call free_()
and can leave idrs around that reference freed memory.

This always destroys the idr entry in free_().  We no longer leave idr
entries around that reference freed memory.

This fixes use after free while walking the debugfs file which can hit
in scoutfs/006 which uses the locks file.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-01-29 12:48:02 -08:00
committed by Mark Fasheh
parent ac09f03327
commit 9cc750c4ec

View File

@@ -259,6 +259,13 @@ static void free_scoutfs_lock(struct scoutfs_lock *lock)
if (lock) {
linfo = SCOUTFS_SB(lock->sb)->lock_info;
if (lock->debug_locks_id) {
spin_lock(&linfo->lock);
idr_remove(&linfo->debug_locks_idr,
lock->debug_locks_id);
spin_unlock(&linfo->lock);
}
scoutfs_inc_counter(lock->sb, lock_free);
ocfs2_lock_res_free(&lock->lockres);
scoutfs_key_free(lock->sb, lock->start);
@@ -288,9 +295,6 @@ static void put_scoutfs_lock(struct super_block *sb, struct scoutfs_lock *lock)
RB_CLEAR_NODE(&lock->range_node);
}
list_del(&lock->lru_entry);
if (lock->debug_locks_id)
idr_remove(&linfo->debug_locks_idr,
lock->debug_locks_id);
spin_unlock(&linfo->lock);
ocfs2_simple_drop_lockres(&linfo->dlmglue,
&lock->lockres);