diff options
author | attilio <attilio@FreeBSD.org> | 2012-12-05 15:11:01 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2012-12-05 15:11:01 +0000 |
commit | 97d8ae3890bf8dc9a8e2b6a9aab818d9a7778b07 (patch) | |
tree | b53607d9bcc3dda028b2903dec59dff2809ba59e /sys/kern/kern_lock.c | |
parent | 13826589d2f1a59c5ec6bc2edae8504eca4703c7 (diff) | |
download | FreeBSD-src-97d8ae3890bf8dc9a8e2b6a9aab818d9a7778b07.zip FreeBSD-src-97d8ae3890bf8dc9a8e2b6a9aab818d9a7778b07.tar.gz |
Check for lockmgr recursion in case of disown and downgrade and panic
also in !debugging kernel rather than having "undefined" behaviour.
Tested by: avg
MFC after: 1 week
Diffstat (limited to 'sys/kern/kern_lock.c')
-rw-r--r-- | sys/kern/kern_lock.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index 8b428bd..cc276db 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -934,9 +934,19 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, } break; case LK_DOWNGRADE: - _lockmgr_assert(lk, KA_XLOCKED | KA_NOTRECURSED, file, line); + _lockmgr_assert(lk, KA_XLOCKED, file, line); LOCK_LOG_LOCK("XDOWNGRADE", &lk->lock_object, 0, 0, file, line); WITNESS_DOWNGRADE(&lk->lock_object, 0, file, line); + + /* + * Panic if the lock is recursed. + */ + if (lockmgr_xlocked(lk) && lockmgr_recursed(lk)) { + if (flags & LK_INTERLOCK) + class->lc_unlock(ilk); + panic("%s: downgrade a recursed lockmgr %s @ %s:%d\n", + __func__, iwmesg, file, line); + } TD_SLOCKS_INC(curthread); /* @@ -1254,7 +1264,14 @@ _lockmgr_disown(struct lock *lk, const char *file, int line) return; tid = (uintptr_t)curthread; - _lockmgr_assert(lk, KA_XLOCKED | KA_NOTRECURSED, file, line); + _lockmgr_assert(lk, KA_XLOCKED, file, line); + + /* + * Panic if the lock is recursed. + */ + if (lockmgr_xlocked(lk) && lockmgr_recursed(lk)) + panic("%s: disown a recursed lockmgr @ %s:%d\n", + __func__, file, line); /* * If the owner is already LK_KERNPROC just skip the whole operation. |