Skip to content

Commit

Permalink
dma-debug: fix locking bug in check_unmap()
Browse files Browse the repository at this point in the history
In check_unmap() it is possible to get into a dead-locked state if
dma_mapping_error is called.  The problem is that the bucket is locked in
check_unmap, and locked again by debug_dma_mapping_error which is called
by dma_mapping_error.  To resolve that we must release the lock on the
bucket before making the call to dma_mapping_error.

[[email protected]: restore 80-col trickery to be consistent with the rest of the file]
Signed-off-by: Alexander Duyck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Reviewed-by: Shuah Khan <[email protected]>
Tested-by: Shuah Khan <[email protected]>
Cc: Jakub Kicinski <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Alexander Duyck authored and torvalds committed Mar 22, 2013
1 parent 0ef1594 commit 8d640a5
Showing 1 changed file with 12 additions and 9 deletions.
21 changes: 12 additions & 9 deletions lib/dma-debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -862,17 +862,21 @@ static void check_unmap(struct dma_debug_entry *ref)
entry = bucket_find_exact(bucket, ref);

if (!entry) {
/* must drop lock before calling dma_mapping_error */
put_hash_bucket(bucket, &flags);

if (dma_mapping_error(ref->dev, ref->dev_addr)) {
err_printk(ref->dev, NULL,
"DMA-API: device driver tries "
"to free an invalid DMA memory address\n");
return;
"DMA-API: device driver tries to free an "
"invalid DMA memory address\n");
} else {
err_printk(ref->dev, NULL,
"DMA-API: device driver tries to free DMA "
"memory it has not allocated [device "
"address=0x%016llx] [size=%llu bytes]\n",
ref->dev_addr, ref->size);
}
err_printk(ref->dev, NULL, "DMA-API: device driver tries "
"to free DMA memory it has not allocated "
"[device address=0x%016llx] [size=%llu bytes]\n",
ref->dev_addr, ref->size);
goto out;
return;
}

if (ref->size != entry->size) {
Expand Down Expand Up @@ -936,7 +940,6 @@ static void check_unmap(struct dma_debug_entry *ref)
hash_bucket_del(entry);
dma_entry_free(entry);

out:
put_hash_bucket(bucket, &flags);
}

Expand Down

0 comments on commit 8d640a5

Please sign in to comment.