Skip to content

Commit

Permalink
xen/blkfront: Fix crash if backend doesn't follow the right states.
Browse files Browse the repository at this point in the history
We have split the setting up of all the resources in two steps:
1) talk_to_blkback  - which figures out the num_ring_pages (from
   the default value of zero), sets up shadow and so
2) blkfront_connect - does the real part of filling out the
   internal structures.

The problem is if we bypass the 1) step and go straight to 2)
and call blkfront_setup_indirect where we use the macro
BLK_RING_SIZE - which returns an negative value (because
sz is zero  - since num_ring_pages is zero - since it has never
been set).

We can fix this by making sure that we always have called
talk_to_blkback before going to blkfront_connect.

Or we could set in blkfront_probe info->nr_ring_pages = 1
to have a default value. But that looks odd - as we haven't
actually negotiated any ring size.

This patch changes XenbusStateConnected state to detect if
we haven't done the initial handshake - and if so continue
on as if were in XenbusStateInitWait state.

We also roll the error recovery (freeing the structure) into
talk_to_blkback error path - which is safe since that function
is only called from blkback_changed.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
  • Loading branch information
Konrad Rzeszutek Wilk committed Jan 4, 2016
1 parent 93bb277 commit c31ecf6
Showing 1 changed file with 8 additions and 4 deletions.
12 changes: 8 additions & 4 deletions drivers/block/xen-blkfront.c
Original file line number Diff line number Diff line change
Expand Up @@ -1867,6 +1867,9 @@ static int talk_to_blkback(struct xenbus_device *dev,
destroy_blkring:
blkif_free(info, 0);

kfree(info);
dev_set_drvdata(&dev->dev, NULL);

return err;
}

Expand Down Expand Up @@ -2453,11 +2456,8 @@ static void blkback_changed(struct xenbus_device *dev,
case XenbusStateInitWait:
if (dev->state != XenbusStateInitialising)
break;
if (talk_to_blkback(dev, info)) {
kfree(info);
dev_set_drvdata(&dev->dev, NULL);
if (talk_to_blkback(dev, info))
break;
}
case XenbusStateInitialising:
case XenbusStateInitialised:
case XenbusStateReconfiguring:
Expand All @@ -2466,6 +2466,10 @@ static void blkback_changed(struct xenbus_device *dev,
break;

case XenbusStateConnected:
if (dev->state != XenbusStateInitialised) {
if (talk_to_blkback(dev, info))
break;
}
blkfront_connect(info);
break;

Expand Down

0 comments on commit c31ecf6

Please sign in to comment.