irda: Fix lockdep annotations in hashbin_delete().
A nested lock depth was added to the hasbin_delete() code but it doesn't actually work some well and results in tons of lockdep splats. Fix the code instead to properly drop the lock around the operation and just keep peeking the head of the hashbin queue. Change-Id: I0cb630739aa44b9e7c4a5b775e906713775f13ef Reported-by: Dmitry Vyukov <dvyukov@google.com> Tested-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> CVE-2017-6348 Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
parent
c846c56881
commit
dde420dc39
|
@ -385,9 +385,6 @@ EXPORT_SYMBOL(hashbin_new);
|
|||
* for deallocating this structure if it's complex. If not the user can
|
||||
* just supply kfree, which should take care of the job.
|
||||
*/
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
static int hashbin_lock_depth = 0;
|
||||
#endif
|
||||
int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
|
||||
{
|
||||
irda_queue_t* queue;
|
||||
|
@ -398,22 +395,27 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
|
|||
IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);
|
||||
|
||||
/* Synchronize */
|
||||
if ( hashbin->hb_type & HB_LOCK ) {
|
||||
spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags,
|
||||
hashbin_lock_depth++);
|
||||
}
|
||||
if (hashbin->hb_type & HB_LOCK)
|
||||
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
|
||||
|
||||
/*
|
||||
* Free the entries in the hashbin, TODO: use hashbin_clear when
|
||||
* it has been shown to work
|
||||
*/
|
||||
for (i = 0; i < HASHBIN_SIZE; i ++ ) {
|
||||
queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
|
||||
while (queue ) {
|
||||
if (free_func)
|
||||
(*free_func)(queue);
|
||||
queue = dequeue_first(
|
||||
(irda_queue_t**) &hashbin->hb_queue[i]);
|
||||
while (1) {
|
||||
queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
|
||||
|
||||
if (!queue)
|
||||
break;
|
||||
|
||||
if (free_func) {
|
||||
if (hashbin->hb_type & HB_LOCK)
|
||||
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
|
||||
free_func(queue);
|
||||
if (hashbin->hb_type & HB_LOCK)
|
||||
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,12 +424,8 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
|
|||
hashbin->magic = ~HB_MAGIC;
|
||||
|
||||
/* Release lock */
|
||||
if ( hashbin->hb_type & HB_LOCK) {
|
||||
if (hashbin->hb_type & HB_LOCK)
|
||||
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
hashbin_lock_depth--;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the hashbin structure
|
||||
|
|
Loading…
Reference in New Issue