Roger Pau Monne
2012-Dec-04 14:21 UTC
[PATCH 1/2] xen-blkback: implement safe iterator for the list of persistent grants
Change foreach_grant iterator to a safe version, that allows freeing the element while iterating. Also move the free code in free_persistent_gnts to prevent freeing the element before the rb_next call. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> Cc: xen-devel@lists.xen.org --- drivers/block/xen-blkback/blkback.c | 18 +++++++++++------- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 74374fb..5ac841f 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -161,10 +161,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, static void make_response(struct xen_blkif *blkif, u64 id, unsigned short op, int st); -#define foreach_grant(pos, rbtree, node) \ - for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node); \ +#define foreach_grant_safe(pos, n, rbtree, node) \ + for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \ + (n) = rb_next(&(pos)->node); \ &(pos)->node != NULL; \ - (pos) = container_of(rb_next(&(pos)->node), typeof(*(pos)), node)) + (pos) = container_of(n, typeof(*(pos)), node), \ + (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL) static void add_persistent_gnt(struct rb_root *root, @@ -217,10 +219,11 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num) struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; struct persistent_gnt *persistent_gnt; + struct rb_node *n; int ret = 0; int segs_to_unmap = 0; - foreach_grant(persistent_gnt, root, node) { + foreach_grant_safe(persistent_gnt, n, root, node) { BUG_ON(persistent_gnt->handle = BLKBACK_INVALID_HANDLE); gnttab_set_unmap_op(&unmap[segs_to_unmap], @@ -230,9 +233,6 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num) persistent_gnt->handle); pages[segs_to_unmap] = persistent_gnt->page; - rb_erase(&persistent_gnt->node, root); - kfree(persistent_gnt); - num--; if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || !rb_next(&persistent_gnt->node)) { @@ -241,6 +241,10 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num) BUG_ON(ret); segs_to_unmap = 0; } + + rb_erase(&persistent_gnt->node, root); + kfree(persistent_gnt); + num--; } BUG_ON(num != 0); } -- 1.7.7.5 (Apple Git-26) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Roger Pau Monne
2012-Dec-04 14:21 UTC
[PATCH 2/2] 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> Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> Cc: xen-devel@lists.xen.org --- drivers/block/xen-blkfront.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 96e9b00..df21b05 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -143,6 +143,13 @@ static DEFINE_SPINLOCK(minor_lock); #define DEV_NAME "xvd" /* name in /dev */ +#define llist_for_each_entry_safe(pos, n, node, member) \ + for ((pos) = llist_entry((node), typeof(*(pos)), member), \ + (n) = (pos)->member.next; \ + &(pos)->member != NULL; \ + (pos) = llist_entry(n, typeof(*(pos)), member), \ + (n) = (&(pos)->member != NULL) ? (pos)->member.next : NULL) + static int get_id_from_freelist(struct blkfront_info *info) { unsigned long free = info->shadow_free; @@ -792,6 +799,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) { struct llist_node *all_gnts; struct grant *persistent_gnt; + struct llist_node *n; /* Prevent new requests being issued until we fix things up. */ spin_lock_irq(&info->io_lock); @@ -804,7 +812,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) /* Remove all persistent grants */ if (info->persistent_gnts_c) { all_gnts = llist_del_all(&info->persistent_gnts); - llist_for_each_entry(persistent_gnt, all_gnts, node) { + llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) { gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); __free_page(pfn_to_page(persistent_gnt->pfn)); kfree(persistent_gnt); -- 1.7.7.5 (Apple Git-26) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Konrad Rzeszutek Wilk
2012-Dec-07 20:20 UTC
Re: [PATCH 2/2] xen-blkfront: implement safe version of llist_for_each_entry
On Tue, Dec 04, 2012 at 03:21:53PM +0100, Roger Pau Monne wrote:> 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.Looks like xen-blkfront is the only user of this llist_for_each_entry. Would it be more prudent to put the macro in the llist.h file?> > Reported-by: Dan Carpenter <dan.carpenter@oracle.com> > Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> > Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> > Cc: xen-devel@lists.xen.org > --- > drivers/block/xen-blkfront.c | 10 +++++++++- > 1 files changed, 9 insertions(+), 1 deletions(-) > > diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c > index 96e9b00..df21b05 100644 > --- a/drivers/block/xen-blkfront.c > +++ b/drivers/block/xen-blkfront.c > @@ -143,6 +143,13 @@ static DEFINE_SPINLOCK(minor_lock); > > #define DEV_NAME "xvd" /* name in /dev */ > > +#define llist_for_each_entry_safe(pos, n, node, member) \ > + for ((pos) = llist_entry((node), typeof(*(pos)), member), \ > + (n) = (pos)->member.next; \ > + &(pos)->member != NULL; \ > + (pos) = llist_entry(n, typeof(*(pos)), member), \ > + (n) = (&(pos)->member != NULL) ? (pos)->member.next : NULL) > + > static int get_id_from_freelist(struct blkfront_info *info) > { > unsigned long free = info->shadow_free; > @@ -792,6 +799,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) > { > struct llist_node *all_gnts; > struct grant *persistent_gnt; > + struct llist_node *n; > > /* Prevent new requests being issued until we fix things up. */ > spin_lock_irq(&info->io_lock); > @@ -804,7 +812,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) > /* Remove all persistent grants */ > if (info->persistent_gnts_c) { > all_gnts = llist_del_all(&info->persistent_gnts); > - llist_for_each_entry(persistent_gnt, all_gnts, node) { > + llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) { > gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); > __free_page(pfn_to_page(persistent_gnt->pfn)); > kfree(persistent_gnt); > -- > 1.7.7.5 (Apple Git-26) > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel >
Roger Pau Monné
2012-Dec-10 12:15 UTC
Re: [PATCH 2/2] xen-blkfront: implement safe version of llist_for_each_entry
On 07/12/12 21:20, Konrad Rzeszutek Wilk wrote:> On Tue, Dec 04, 2012 at 03:21:53PM +0100, Roger Pau Monne wrote: >> 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. > > Looks like xen-blkfront is the only user of this llist_for_each_entry. > > Would it be more prudent to put the macro in the llist.h file?I''m not able to find out who is the maintainer of llist, should I just CC it''s author?
Konrad Rzeszutek Wilk
2012-Dec-10 15:15 UTC
Re: [PATCH 2/2] xen-blkfront: implement safe version of llist_for_each_entry
On Mon, Dec 10, 2012 at 01:15:50PM +0100, Roger Pau Monné wrote:> On 07/12/12 21:20, Konrad Rzeszutek Wilk wrote: > > On Tue, Dec 04, 2012 at 03:21:53PM +0100, Roger Pau Monne wrote: > >> 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. > > > > Looks like xen-blkfront is the only user of this llist_for_each_entry. > > > > Would it be more prudent to put the macro in the llist.h file? > > I''m not able to find out who is the maintainer of llist, should I just > CC it''s author?Sure. I CC-ed akpm here to solicit his input as well. Either way I am OK wit this being in xen-blkfront but it just seems that it could be useful in the llist file since that is where the non-safe version resides.>
Roger Pau Monné
2012-Dec-10 17:05 UTC
Re: [PATCH 2/2] xen-blkfront: implement safe version of llist_for_each_entry
On 10/12/12 16:15, Konrad Rzeszutek Wilk wrote:> On Mon, Dec 10, 2012 at 01:15:50PM +0100, Roger Pau Monné wrote: >> On 07/12/12 21:20, Konrad Rzeszutek Wilk wrote: >>> On Tue, Dec 04, 2012 at 03:21:53PM +0100, Roger Pau Monne wrote: >>>> 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. >>> >>> Looks like xen-blkfront is the only user of this llist_for_each_entry. >>> >>> Would it be more prudent to put the macro in the llist.h file? >> >> I''m not able to find out who is the maintainer of llist, should I just >> CC it''s author? > > Sure. I CC-ed akpm here to solicit his input as well. Either way I am > OK wit this being in xen-blkfront but it just seems that it could > be useful in the llist file since that is where the non-safe version > resides.I''m going to resend this series with llist_for_each_entry_safe added to llist.h in a separated patch. I wouldn''t like to delay this series because we cannot get llist_for_each_entry_safe added to llist.h, that''s why I''ve added it to blkfront in the first place.
Andrew Morton
2012-Dec-12 21:01 UTC
Re: [PATCH 2/2] xen-blkfront: implement safe version of llist_for_each_entry
On Mon, 10 Dec 2012 18:05:23 +0100 Roger Pau Monné <roger.pau@citrix.com> wrote:> On 10/12/12 16:15, Konrad Rzeszutek Wilk wrote: > > On Mon, Dec 10, 2012 at 01:15:50PM +0100, Roger Pau Monné wrote: > >> On 07/12/12 21:20, Konrad Rzeszutek Wilk wrote: > >>> On Tue, Dec 04, 2012 at 03:21:53PM +0100, Roger Pau Monne wrote: > >>>> 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. > >>> > >>> Looks like xen-blkfront is the only user of this llist_for_each_entry. > >>> > >>> Would it be more prudent to put the macro in the llist.h file? > >> > >> I''m not able to find out who is the maintainer of llist, should I just > >> CC it''s author? > > > > Sure. I CC-ed akpm here to solicit his input as well. Either way I am > > OK wit this being in xen-blkfront but it just seems that it could > > be useful in the llist file since that is where the non-safe version > > resides. > > I''m going to resend this series with llist_for_each_entry_safe added to > llist.h in a separated patch. I wouldn''t like to delay this series > because we cannot get llist_for_each_entry_safe added to llist.h, that''s > why I''ve added it to blkfront in the first place.Please include that llist.h patch within the xen merge. It''s just a single hunk and won''t cause any disruption.