diff options
author | Roger Pau Monne <roger.pau@citrix.com> | 2012-12-04 09:21:53 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-12-17 21:55:56 -0500 |
commit | ebb351cf78ee6bf3262e6b4b6906f456c05e6d5e (patch) | |
tree | 103c6133d51f266b16c8b6f71fddf4992c57dc8f /drivers/block/xen-blkfront.c | |
parent | 7dc341175af5e7361af81499ea192c7b274b6357 (diff) |
llist/xen-blkfront: implement safe version of llist_for_each_entry
Implement a safe version of llist_for_each_entry, and use it in
blkif_free. Previously grants where freed while iterating the list,
which lead to dereferences when trying to fetch the next item.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Andrew Morton <akpm@linux-foundation.org>
[v2: Move the llist_for_each_entry_safe in llist.h]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/block/xen-blkfront.c')
-rw-r--r-- | drivers/block/xen-blkfront.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 96e9b00db081..cfdb033c7107 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -792,6 +792,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
792 | { | 792 | { |
793 | struct llist_node *all_gnts; | 793 | struct llist_node *all_gnts; |
794 | struct grant *persistent_gnt; | 794 | struct grant *persistent_gnt; |
795 | struct llist_node *n; | ||
795 | 796 | ||
796 | /* Prevent new requests being issued until we fix things up. */ | 797 | /* Prevent new requests being issued until we fix things up. */ |
797 | spin_lock_irq(&info->io_lock); | 798 | spin_lock_irq(&info->io_lock); |
@@ -804,7 +805,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
804 | /* Remove all persistent grants */ | 805 | /* Remove all persistent grants */ |
805 | if (info->persistent_gnts_c) { | 806 | if (info->persistent_gnts_c) { |
806 | all_gnts = llist_del_all(&info->persistent_gnts); | 807 | all_gnts = llist_del_all(&info->persistent_gnts); |
807 | llist_for_each_entry(persistent_gnt, all_gnts, node) { | 808 | llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) { |
808 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); | 809 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); |
809 | __free_page(pfn_to_page(persistent_gnt->pfn)); | 810 | __free_page(pfn_to_page(persistent_gnt->pfn)); |
810 | kfree(persistent_gnt); | 811 | kfree(persistent_gnt); |