* [PATCH v2] xen-blkback: fix compatibility bug with single page rings
@ 2021-01-28 13:04 Paul Durrant
2021-01-29 6:20 ` Dongli Zhang
2021-02-02 16:28 ` Roger Pau Monné
0 siblings, 2 replies; 7+ messages in thread
From: Paul Durrant @ 2021-01-28 13:04 UTC (permalink / raw)
To: xen-devel, linux-block, linux-kernel
Cc: Paul Durrant, Konrad Rzeszutek Wilk, Roger Pau Monné,
Jens Axboe, Dongli Zhang
From: Paul Durrant <pdurrant@amazon.com>
Prior to commit 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid
inconsistent xenstore 'ring-page-order' set by malicious blkfront"), the
behaviour of xen-blkback when connecting to a frontend was:
- read 'ring-page-order'
- if not present then expect a single page ring specified by 'ring-ref'
- else expect a ring specified by 'ring-refX' where X is between 0 and
1 << ring-page-order
This was correct behaviour, but was broken by the afforementioned commit to
become:
- read 'ring-page-order'
- if not present then expect a single page ring (i.e. ring-page-order = 0)
- expect a ring specified by 'ring-refX' where X is between 0 and
1 << ring-page-order
- if that didn't work then see if there's a single page ring specified by
'ring-ref'
This incorrect behaviour works most of the time but fails when a frontend
that sets 'ring-page-order' is unloaded and replaced by one that does not
because, instead of reading 'ring-ref', xen-blkback will read the stale
'ring-ref0' left around by the previous frontend will try to map the wrong
grant reference.
This patch restores the original behaviour.
Fixes: 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid inconsistent xenstore 'ring-page-order' set by malicious blkfront")
Signed-off-by: Paul Durrant <pdurrant@amazon.com>
---
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: "Roger Pau Monné" <roger.pau@citrix.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Dongli Zhang <dongli.zhang@oracle.com>
v2:
- Remove now-spurious error path special-case when nr_grefs == 1
---
drivers/block/xen-blkback/common.h | 1 +
drivers/block/xen-blkback/xenbus.c | 38 +++++++++++++-----------------
2 files changed, 17 insertions(+), 22 deletions(-)
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index b0c71d3a81a0..524a79f10de6 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -313,6 +313,7 @@ struct xen_blkif {
struct work_struct free_work;
unsigned int nr_ring_pages;
+ bool multi_ref;
/* All rings for this device. */
struct xen_blkif_ring *rings;
unsigned int nr_rings;
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 9860d4842f36..6c5e9373e91c 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -998,14 +998,17 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
for (i = 0; i < nr_grefs; i++) {
char ring_ref_name[RINGREF_NAME_LEN];
- snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
+ if (blkif->multi_ref)
+ snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
+ else {
+ WARN_ON(i != 0);
+ snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref");
+ }
+
err = xenbus_scanf(XBT_NIL, dir, ring_ref_name,
"%u", &ring_ref[i]);
if (err != 1) {
- if (nr_grefs == 1)
- break;
-
err = -EINVAL;
xenbus_dev_fatal(dev, err, "reading %s/%s",
dir, ring_ref_name);
@@ -1013,18 +1016,6 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
}
}
- if (err != 1) {
- WARN_ON(nr_grefs != 1);
-
- err = xenbus_scanf(XBT_NIL, dir, "ring-ref", "%u",
- &ring_ref[0]);
- if (err != 1) {
- err = -EINVAL;
- xenbus_dev_fatal(dev, err, "reading %s/ring-ref", dir);
- return err;
- }
- }
-
err = -ENOMEM;
for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) {
req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -1129,10 +1120,15 @@ static int connect_ring(struct backend_info *be)
blkif->nr_rings, blkif->blk_protocol, protocol,
blkif->vbd.feature_gnt_persistent ? "persistent grants" : "");
- ring_page_order = xenbus_read_unsigned(dev->otherend,
- "ring-page-order", 0);
-
- if (ring_page_order > xen_blkif_max_ring_order) {
+ err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-page-order", "%u",
+ &ring_page_order);
+ if (err != 1) {
+ blkif->nr_ring_pages = 1;
+ blkif->multi_ref = false;
+ } else if (ring_page_order <= xen_blkif_max_ring_order) {
+ blkif->nr_ring_pages = 1 << ring_page_order;
+ blkif->multi_ref = true;
+ } else {
err = -EINVAL;
xenbus_dev_fatal(dev, err,
"requested ring page order %d exceed max:%d",
@@ -1141,8 +1137,6 @@ static int connect_ring(struct backend_info *be)
return err;
}
- blkif->nr_ring_pages = 1 << ring_page_order;
-
if (blkif->nr_rings == 1)
return read_per_ring_refs(&blkif->rings[0], dev->otherend);
else {
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
2021-01-28 13:04 [PATCH v2] xen-blkback: fix compatibility bug with single page rings Paul Durrant
@ 2021-01-29 6:20 ` Dongli Zhang
2021-01-29 7:35 ` Jürgen Groß
2021-02-02 16:28 ` Roger Pau Monné
1 sibling, 1 reply; 7+ messages in thread
From: Dongli Zhang @ 2021-01-29 6:20 UTC (permalink / raw)
To: Paul Durrant, xen-devel, linux-block, linux-kernel
Cc: Paul Durrant, Konrad Rzeszutek Wilk, Roger Pau Monné, Jens Axboe
On 1/28/21 5:04 AM, Paul Durrant wrote:
> From: Paul Durrant <pdurrant@amazon.com>
>
> Prior to commit 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid
> inconsistent xenstore 'ring-page-order' set by malicious blkfront"), the
> behaviour of xen-blkback when connecting to a frontend was:
>
> - read 'ring-page-order'
> - if not present then expect a single page ring specified by 'ring-ref'
> - else expect a ring specified by 'ring-refX' where X is between 0 and
> 1 << ring-page-order
>
> This was correct behaviour, but was broken by the afforementioned commit to
> become:
>
> - read 'ring-page-order'
> - if not present then expect a single page ring (i.e. ring-page-order = 0)
> - expect a ring specified by 'ring-refX' where X is between 0 and
> 1 << ring-page-order
> - if that didn't work then see if there's a single page ring specified by
> 'ring-ref'
>
> This incorrect behaviour works most of the time but fails when a frontend
> that sets 'ring-page-order' is unloaded and replaced by one that does not
> because, instead of reading 'ring-ref', xen-blkback will read the stale
> 'ring-ref0' left around by the previous frontend will try to map the wrong
> grant reference.
>
> This patch restores the original behaviour.
>
> Fixes: 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid inconsistent xenstore 'ring-page-order' set by malicious blkfront")
> Signed-off-by: Paul Durrant <pdurrant@amazon.com>
> ---
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: "Roger Pau Monné" <roger.pau@citrix.com>
> Cc: Jens Axboe <axboe@kernel.dk>
> Cc: Dongli Zhang <dongli.zhang@oracle.com>
>
> v2:
> - Remove now-spurious error path special-case when nr_grefs == 1
> ---
> drivers/block/xen-blkback/common.h | 1 +
> drivers/block/xen-blkback/xenbus.c | 38 +++++++++++++-----------------
> 2 files changed, 17 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
> index b0c71d3a81a0..524a79f10de6 100644
> --- a/drivers/block/xen-blkback/common.h
> +++ b/drivers/block/xen-blkback/common.h
> @@ -313,6 +313,7 @@ struct xen_blkif {
>
> struct work_struct free_work;
> unsigned int nr_ring_pages;
> + bool multi_ref;
Is it really necessary to introduce 'multi_ref' here or we may just re-use
'nr_ring_pages'?
According to blkfront code, 'ring-page-order' is set only when it is not zero,
that is, only when (info->nr_ring_pages > 1).
1819 if (info->nr_ring_pages > 1) {
1820 err = xenbus_printf(xbt, dev->nodename, "ring-page-order",
"%u",
1821 ring_page_order);
1822 if (err) {
1823 message = "writing ring-page-order";
1824 goto abort_transaction;
1825 }
1826 }
Therefore, can we assume 'ring-page-order' can never be 0? Once we have
'ring-page-order' set, it should be >= 1 and we should read from "ring-ref%u"?
If the specification allows 'ring-page-order' to be zero with "ring-ref%u"
available, we should introduce 'multi_ref'.
Thank you very much!
Dongli Zhang
> /* All rings for this device. */
> struct xen_blkif_ring *rings;
> unsigned int nr_rings;
> diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
> index 9860d4842f36..6c5e9373e91c 100644
> --- a/drivers/block/xen-blkback/xenbus.c
> +++ b/drivers/block/xen-blkback/xenbus.c
> @@ -998,14 +998,17 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
> for (i = 0; i < nr_grefs; i++) {
> char ring_ref_name[RINGREF_NAME_LEN];
>
> - snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
> + if (blkif->multi_ref)
> + snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
> + else {
> + WARN_ON(i != 0);
> + snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref");
> + }
> +
> err = xenbus_scanf(XBT_NIL, dir, ring_ref_name,
> "%u", &ring_ref[i]);
>
> if (err != 1) {
> - if (nr_grefs == 1)
> - break;
> -
> err = -EINVAL;
> xenbus_dev_fatal(dev, err, "reading %s/%s",
> dir, ring_ref_name);
> @@ -1013,18 +1016,6 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
> }
> }
>
> - if (err != 1) {
> - WARN_ON(nr_grefs != 1);
> -
> - err = xenbus_scanf(XBT_NIL, dir, "ring-ref", "%u",
> - &ring_ref[0]);
> - if (err != 1) {
> - err = -EINVAL;
> - xenbus_dev_fatal(dev, err, "reading %s/ring-ref", dir);
> - return err;
> - }
> - }
> -
> err = -ENOMEM;
> for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) {
> req = kzalloc(sizeof(*req), GFP_KERNEL);
> @@ -1129,10 +1120,15 @@ static int connect_ring(struct backend_info *be)
> blkif->nr_rings, blkif->blk_protocol, protocol,
> blkif->vbd.feature_gnt_persistent ? "persistent grants" : "");
>
> - ring_page_order = xenbus_read_unsigned(dev->otherend,
> - "ring-page-order", 0);
> -
> - if (ring_page_order > xen_blkif_max_ring_order) {
> + err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-page-order", "%u",
> + &ring_page_order);
> + if (err != 1) {
> + blkif->nr_ring_pages = 1;
> + blkif->multi_ref = false;
> + } else if (ring_page_order <= xen_blkif_max_ring_order) {
> + blkif->nr_ring_pages = 1 << ring_page_order;
> + blkif->multi_ref = true;
> + } else {
> err = -EINVAL;
> xenbus_dev_fatal(dev, err,
> "requested ring page order %d exceed max:%d",
> @@ -1141,8 +1137,6 @@ static int connect_ring(struct backend_info *be)
> return err;
> }
>
> - blkif->nr_ring_pages = 1 << ring_page_order;
> -
> if (blkif->nr_rings == 1)
> return read_per_ring_refs(&blkif->rings[0], dev->otherend);
> else {
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
2021-01-29 6:20 ` Dongli Zhang
@ 2021-01-29 7:35 ` Jürgen Groß
[not found] ` <02d901d6f616$b0004750$1000d5f0$@xen.org>
0 siblings, 1 reply; 7+ messages in thread
From: Jürgen Groß @ 2021-01-29 7:35 UTC (permalink / raw)
To: Dongli Zhang, Paul Durrant, xen-devel, linux-block, linux-kernel
Cc: Paul Durrant, Konrad Rzeszutek Wilk, Roger Pau Monné, Jens Axboe
[-- Attachment #1.1.1: Type: text/plain, Size: 2875 bytes --]
On 29.01.21 07:20, Dongli Zhang wrote:
>
>
> On 1/28/21 5:04 AM, Paul Durrant wrote:
>> From: Paul Durrant <pdurrant@amazon.com>
>>
>> Prior to commit 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid
>> inconsistent xenstore 'ring-page-order' set by malicious blkfront"), the
>> behaviour of xen-blkback when connecting to a frontend was:
>>
>> - read 'ring-page-order'
>> - if not present then expect a single page ring specified by 'ring-ref'
>> - else expect a ring specified by 'ring-refX' where X is between 0 and
>> 1 << ring-page-order
>>
>> This was correct behaviour, but was broken by the afforementioned commit to
>> become:
>>
>> - read 'ring-page-order'
>> - if not present then expect a single page ring (i.e. ring-page-order = 0)
>> - expect a ring specified by 'ring-refX' where X is between 0 and
>> 1 << ring-page-order
>> - if that didn't work then see if there's a single page ring specified by
>> 'ring-ref'
>>
>> This incorrect behaviour works most of the time but fails when a frontend
>> that sets 'ring-page-order' is unloaded and replaced by one that does not
>> because, instead of reading 'ring-ref', xen-blkback will read the stale
>> 'ring-ref0' left around by the previous frontend will try to map the wrong
>> grant reference.
>>
>> This patch restores the original behaviour.
>>
>> Fixes: 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid inconsistent xenstore 'ring-page-order' set by malicious blkfront")
>> Signed-off-by: Paul Durrant <pdurrant@amazon.com>
>> ---
>> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>> Cc: "Roger Pau Monné" <roger.pau@citrix.com>
>> Cc: Jens Axboe <axboe@kernel.dk>
>> Cc: Dongli Zhang <dongli.zhang@oracle.com>
>>
>> v2:
>> - Remove now-spurious error path special-case when nr_grefs == 1
>> ---
>> drivers/block/xen-blkback/common.h | 1 +
>> drivers/block/xen-blkback/xenbus.c | 38 +++++++++++++-----------------
>> 2 files changed, 17 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
>> index b0c71d3a81a0..524a79f10de6 100644
>> --- a/drivers/block/xen-blkback/common.h
>> +++ b/drivers/block/xen-blkback/common.h
>> @@ -313,6 +313,7 @@ struct xen_blkif {
>>
>> struct work_struct free_work;
>> unsigned int nr_ring_pages;
>> + bool multi_ref;
>
> Is it really necessary to introduce 'multi_ref' here or we may just re-use
> 'nr_ring_pages'?
>
> According to blkfront code, 'ring-page-order' is set only when it is not zero,
> that is, only when (info->nr_ring_pages > 1).
Did you look into all other OS's (Windows, OpenBSD, FreebSD, NetBSD,
Solaris, Netware, other proprietary systems) implementations to verify
that claim?
I don't think so. So better safe than sorry.
Juergen
[-- Attachment #1.1.2: OpenPGP_0xB0DE9DD628BF132F.asc --]
[-- Type: application/pgp-keys, Size: 3135 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
[not found] ` <02d901d6f616$b0004750$1000d5f0$@xen.org>
@ 2021-01-30 5:09 ` Dongli Zhang
2021-02-02 9:36 ` Paul Durrant
0 siblings, 1 reply; 7+ messages in thread
From: Dongli Zhang @ 2021-01-30 5:09 UTC (permalink / raw)
To: paul, 'Jürgen Groß',
xen-devel, linux-block, linux-kernel
Cc: 'Paul Durrant', 'Konrad Rzeszutek Wilk',
'Roger Pau Monné', 'Jens Axboe'
On 1/29/21 12:13 AM, Paul Durrant wrote:
>> -----Original Message-----
>> From: Jürgen Groß <jgross@suse.com>
>> Sent: 29 January 2021 07:35
>> To: Dongli Zhang <dongli.zhang@oracle.com>; Paul Durrant <paul@xen.org>; xen-
>> devel@lists.xenproject.org; linux-block@vger.kernel.org; linux-kernel@vger.kernel.org
>> Cc: Paul Durrant <pdurrant@amazon.com>; Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>; Roger Pau
>> Monné <roger.pau@citrix.com>; Jens Axboe <axboe@kernel.dk>
>> Subject: Re: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
>>
>> On 29.01.21 07:20, Dongli Zhang wrote:
>>>
>>>
>>> On 1/28/21 5:04 AM, Paul Durrant wrote:
>>>> From: Paul Durrant <pdurrant@amazon.com>
>>>>
>>>> Prior to commit 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid
>>>> inconsistent xenstore 'ring-page-order' set by malicious blkfront"), the
>>>> behaviour of xen-blkback when connecting to a frontend was:
>>>>
>>>> - read 'ring-page-order'
>>>> - if not present then expect a single page ring specified by 'ring-ref'
>>>> - else expect a ring specified by 'ring-refX' where X is between 0 and
>>>> 1 << ring-page-order
>>>>
>>>> This was correct behaviour, but was broken by the afforementioned commit to
>>>> become:
>>>>
>>>> - read 'ring-page-order'
>>>> - if not present then expect a single page ring (i.e. ring-page-order = 0)
>>>> - expect a ring specified by 'ring-refX' where X is between 0 and
>>>> 1 << ring-page-order
>>>> - if that didn't work then see if there's a single page ring specified by
>>>> 'ring-ref'
>>>>
>>>> This incorrect behaviour works most of the time but fails when a frontend
>>>> that sets 'ring-page-order' is unloaded and replaced by one that does not
>>>> because, instead of reading 'ring-ref', xen-blkback will read the stale
>>>> 'ring-ref0' left around by the previous frontend will try to map the wrong
>>>> grant reference.
>>>>
>>>> This patch restores the original behaviour.
>>>>
>>>> Fixes: 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid inconsistent xenstore 'ring-page-
>> order' set by malicious blkfront")
>>>> Signed-off-by: Paul Durrant <pdurrant@amazon.com>
>>>> ---
>>>> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>>>> Cc: "Roger Pau Monné" <roger.pau@citrix.com>
>>>> Cc: Jens Axboe <axboe@kernel.dk>
>>>> Cc: Dongli Zhang <dongli.zhang@oracle.com>
>>>>
>>>> v2:
>>>> - Remove now-spurious error path special-case when nr_grefs == 1
>>>> ---
>>>> drivers/block/xen-blkback/common.h | 1 +
>>>> drivers/block/xen-blkback/xenbus.c | 38 +++++++++++++-----------------
>>>> 2 files changed, 17 insertions(+), 22 deletions(-)
>>>>
>>>> diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
>>>> index b0c71d3a81a0..524a79f10de6 100644
>>>> --- a/drivers/block/xen-blkback/common.h
>>>> +++ b/drivers/block/xen-blkback/common.h
>>>> @@ -313,6 +313,7 @@ struct xen_blkif {
>>>>
>>>> struct work_struct free_work;
>>>> unsigned int nr_ring_pages;
>>>> + bool multi_ref;
>>>
>>> Is it really necessary to introduce 'multi_ref' here or we may just re-use
>>> 'nr_ring_pages'?
>>>
>>> According to blkfront code, 'ring-page-order' is set only when it is not zero,
>>> that is, only when (info->nr_ring_pages > 1).
>>
>
> That's how it is *supposed* to be. Windows certainly behaves that way too.
>
>> Did you look into all other OS's (Windows, OpenBSD, FreebSD, NetBSD,
>> Solaris, Netware, other proprietary systems) implementations to verify
>> that claim?
>>
>> I don't think so. So better safe than sorry.
>>
>
> Indeed. It was unfortunate that the commit to blkif.h documenting multi-page (829f2a9c6dfae) was not crystal clear and (possibly as a consequence) blkback was implemented to read ring-ref0 rather than ring-ref if ring-page-order was present and 0. Hence the only safe thing to do is to restore that behaviour.
>
Thank you very much for the explanation!
Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
Dongli ZHang
^ permalink raw reply [flat|nested] 7+ messages in thread
* RE: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
2021-01-30 5:09 ` Dongli Zhang
@ 2021-02-02 9:36 ` Paul Durrant
0 siblings, 0 replies; 7+ messages in thread
From: Paul Durrant @ 2021-02-02 9:36 UTC (permalink / raw)
To: 'Dongli Zhang', 'Jürgen Groß',
'Roger Pau Monné'
Cc: 'Paul Durrant', 'Konrad Rzeszutek Wilk',
'Jens Axboe',
linux-block, xen-devel, linux-kernel
> -----Original Message-----
> From: Xen-devel <xen-devel-bounces@lists.xenproject.org> On Behalf Of Dongli Zhang
> Sent: 30 January 2021 05:09
> To: paul@xen.org; 'Jürgen Groß' <jgross@suse.com>; xen-devel@lists.xenproject.org; linux-
> block@vger.kernel.org; linux-kernel@vger.kernel.org
> Cc: 'Paul Durrant' <pdurrant@amazon.com>; 'Konrad Rzeszutek Wilk' <konrad.wilk@oracle.com>; 'Roger Pau
> Monné' <roger.pau@citrix.com>; 'Jens Axboe' <axboe@kernel.dk>
> Subject: Re: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
>
>
>
> On 1/29/21 12:13 AM, Paul Durrant wrote:
> >> -----Original Message-----
> >> From: Jürgen Groß <jgross@suse.com>
> >> Sent: 29 January 2021 07:35
> >> To: Dongli Zhang <dongli.zhang@oracle.com>; Paul Durrant <paul@xen.org>; xen-
> >> devel@lists.xenproject.org; linux-block@vger.kernel.org; linux-kernel@vger.kernel.org
> >> Cc: Paul Durrant <pdurrant@amazon.com>; Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>; Roger Pau
> >> Monné <roger.pau@citrix.com>; Jens Axboe <axboe@kernel.dk>
> >> Subject: Re: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
> >>
> >> On 29.01.21 07:20, Dongli Zhang wrote:
> >>>
> >>>
> >>> On 1/28/21 5:04 AM, Paul Durrant wrote:
> >>>> From: Paul Durrant <pdurrant@amazon.com>
> >>>>
> >>>> Prior to commit 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid
> >>>> inconsistent xenstore 'ring-page-order' set by malicious blkfront"), the
> >>>> behaviour of xen-blkback when connecting to a frontend was:
> >>>>
> >>>> - read 'ring-page-order'
> >>>> - if not present then expect a single page ring specified by 'ring-ref'
> >>>> - else expect a ring specified by 'ring-refX' where X is between 0 and
> >>>> 1 << ring-page-order
> >>>>
> >>>> This was correct behaviour, but was broken by the afforementioned commit to
> >>>> become:
> >>>>
> >>>> - read 'ring-page-order'
> >>>> - if not present then expect a single page ring (i.e. ring-page-order = 0)
> >>>> - expect a ring specified by 'ring-refX' where X is between 0 and
> >>>> 1 << ring-page-order
> >>>> - if that didn't work then see if there's a single page ring specified by
> >>>> 'ring-ref'
> >>>>
> >>>> This incorrect behaviour works most of the time but fails when a frontend
> >>>> that sets 'ring-page-order' is unloaded and replaced by one that does not
> >>>> because, instead of reading 'ring-ref', xen-blkback will read the stale
> >>>> 'ring-ref0' left around by the previous frontend will try to map the wrong
> >>>> grant reference.
> >>>>
> >>>> This patch restores the original behaviour.
> >>>>
> >>>> Fixes: 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid inconsistent xenstore 'ring-
> page-
> >> order' set by malicious blkfront")
> >>>> Signed-off-by: Paul Durrant <pdurrant@amazon.com>
> >>>> ---
> >>>> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> >>>> Cc: "Roger Pau Monné" <roger.pau@citrix.com>
> >>>> Cc: Jens Axboe <axboe@kernel.dk>
> >>>> Cc: Dongli Zhang <dongli.zhang@oracle.com>
> >>>>
> >>>> v2:
> >>>> - Remove now-spurious error path special-case when nr_grefs == 1
> >>>> ---
> >>>> drivers/block/xen-blkback/common.h | 1 +
> >>>> drivers/block/xen-blkback/xenbus.c | 38 +++++++++++++-----------------
> >>>> 2 files changed, 17 insertions(+), 22 deletions(-)
> >>>>
> >>>> diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
> >>>> index b0c71d3a81a0..524a79f10de6 100644
> >>>> --- a/drivers/block/xen-blkback/common.h
> >>>> +++ b/drivers/block/xen-blkback/common.h
> >>>> @@ -313,6 +313,7 @@ struct xen_blkif {
> >>>>
> >>>> struct work_struct free_work;
> >>>> unsigned int nr_ring_pages;
> >>>> + bool multi_ref;
> >>>
> >>> Is it really necessary to introduce 'multi_ref' here or we may just re-use
> >>> 'nr_ring_pages'?
> >>>
> >>> According to blkfront code, 'ring-page-order' is set only when it is not zero,
> >>> that is, only when (info->nr_ring_pages > 1).
> >>
> >
> > That's how it is *supposed* to be. Windows certainly behaves that way too.
> >
> >> Did you look into all other OS's (Windows, OpenBSD, FreebSD, NetBSD,
> >> Solaris, Netware, other proprietary systems) implementations to verify
> >> that claim?
> >>
> >> I don't think so. So better safe than sorry.
> >>
> >
> > Indeed. It was unfortunate that the commit to blkif.h documenting multi-page (829f2a9c6dfae) was not
> crystal clear and (possibly as a consequence) blkback was implemented to read ring-ref0 rather than
> ring-ref if ring-page-order was present and 0. Hence the only safe thing to do is to restore that
> behaviour.
> >
>
> Thank you very much for the explanation!
>
> Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
>
Thanks.
Roger, Konrad, can I get a maintainer ack or otherwise, please?
Paul
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
2021-01-28 13:04 [PATCH v2] xen-blkback: fix compatibility bug with single page rings Paul Durrant
2021-01-29 6:20 ` Dongli Zhang
@ 2021-02-02 16:28 ` Roger Pau Monné
2021-02-02 16:42 ` Paul Durrant
1 sibling, 1 reply; 7+ messages in thread
From: Roger Pau Monné @ 2021-02-02 16:28 UTC (permalink / raw)
To: Paul Durrant
Cc: xen-devel, linux-block, linux-kernel, Paul Durrant,
Konrad Rzeszutek Wilk, Jens Axboe, Dongli Zhang
On Thu, Jan 28, 2021 at 01:04:41PM +0000, Paul Durrant wrote:
> From: Paul Durrant <pdurrant@amazon.com>
>
> Prior to commit 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid
> inconsistent xenstore 'ring-page-order' set by malicious blkfront"), the
> behaviour of xen-blkback when connecting to a frontend was:
>
> - read 'ring-page-order'
> - if not present then expect a single page ring specified by 'ring-ref'
> - else expect a ring specified by 'ring-refX' where X is between 0 and
> 1 << ring-page-order
>
> This was correct behaviour, but was broken by the afforementioned commit to
> become:
>
> - read 'ring-page-order'
> - if not present then expect a single page ring (i.e. ring-page-order = 0)
> - expect a ring specified by 'ring-refX' where X is between 0 and
> 1 << ring-page-order
> - if that didn't work then see if there's a single page ring specified by
> 'ring-ref'
>
> This incorrect behaviour works most of the time but fails when a frontend
> that sets 'ring-page-order' is unloaded and replaced by one that does not
> because, instead of reading 'ring-ref', xen-blkback will read the stale
> 'ring-ref0' left around by the previous frontend will try to map the wrong
> grant reference.
>
> This patch restores the original behaviour.
>
> Fixes: 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid inconsistent xenstore 'ring-page-order' set by malicious blkfront")
> Signed-off-by: Paul Durrant <pdurrant@amazon.com>
> ---
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: "Roger Pau Monné" <roger.pau@citrix.com>
> Cc: Jens Axboe <axboe@kernel.dk>
> Cc: Dongli Zhang <dongli.zhang@oracle.com>
>
> v2:
> - Remove now-spurious error path special-case when nr_grefs == 1
> ---
> drivers/block/xen-blkback/common.h | 1 +
> drivers/block/xen-blkback/xenbus.c | 38 +++++++++++++-----------------
> 2 files changed, 17 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
> index b0c71d3a81a0..524a79f10de6 100644
> --- a/drivers/block/xen-blkback/common.h
> +++ b/drivers/block/xen-blkback/common.h
> @@ -313,6 +313,7 @@ struct xen_blkif {
>
> struct work_struct free_work;
> unsigned int nr_ring_pages;
> + bool multi_ref;
You seem to have used spaces between the type and the variable name
here, while neighbors also use hard tabs.
The rest LGTM:
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
We should have forbidden the usage of ring-page-order = 0 and we could
have avoided having to add the multi_ref variable, but that's too late
now.
Thanks, Roger.
^ permalink raw reply [flat|nested] 7+ messages in thread
* RE: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
2021-02-02 16:28 ` Roger Pau Monné
@ 2021-02-02 16:42 ` Paul Durrant
0 siblings, 0 replies; 7+ messages in thread
From: Paul Durrant @ 2021-02-02 16:42 UTC (permalink / raw)
To: 'Roger Pau Monné'
Cc: xen-devel, linux-block, linux-kernel, 'Paul Durrant',
'Konrad Rzeszutek Wilk', 'Jens Axboe',
'Dongli Zhang'
> -----Original Message-----
> From: Roger Pau Monné <roger.pau@citrix.com>
> Sent: 02 February 2021 16:29
> To: Paul Durrant <paul@xen.org>
> Cc: xen-devel@lists.xenproject.org; linux-block@vger.kernel.org; linux-kernel@vger.kernel.org; Paul
> Durrant <pdurrant@amazon.com>; Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>; Jens Axboe
> <axboe@kernel.dk>; Dongli Zhang <dongli.zhang@oracle.com>
> Subject: Re: [PATCH v2] xen-blkback: fix compatibility bug with single page rings
>
> On Thu, Jan 28, 2021 at 01:04:41PM +0000, Paul Durrant wrote:
> > From: Paul Durrant <pdurrant@amazon.com>
> >
> > Prior to commit 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid
> > inconsistent xenstore 'ring-page-order' set by malicious blkfront"), the
> > behaviour of xen-blkback when connecting to a frontend was:
> >
> > - read 'ring-page-order'
> > - if not present then expect a single page ring specified by 'ring-ref'
> > - else expect a ring specified by 'ring-refX' where X is between 0 and
> > 1 << ring-page-order
> >
> > This was correct behaviour, but was broken by the afforementioned commit to
> > become:
> >
> > - read 'ring-page-order'
> > - if not present then expect a single page ring (i.e. ring-page-order = 0)
> > - expect a ring specified by 'ring-refX' where X is between 0 and
> > 1 << ring-page-order
> > - if that didn't work then see if there's a single page ring specified by
> > 'ring-ref'
> >
> > This incorrect behaviour works most of the time but fails when a frontend
> > that sets 'ring-page-order' is unloaded and replaced by one that does not
> > because, instead of reading 'ring-ref', xen-blkback will read the stale
> > 'ring-ref0' left around by the previous frontend will try to map the wrong
> > grant reference.
> >
> > This patch restores the original behaviour.
> >
> > Fixes: 4a8c31a1c6f5 ("xen/blkback: rework connect_ring() to avoid inconsistent xenstore 'ring-page-
> order' set by malicious blkfront")
> > Signed-off-by: Paul Durrant <pdurrant@amazon.com>
> > ---
> > Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Cc: "Roger Pau Monné" <roger.pau@citrix.com>
> > Cc: Jens Axboe <axboe@kernel.dk>
> > Cc: Dongli Zhang <dongli.zhang@oracle.com>
> >
> > v2:
> > - Remove now-spurious error path special-case when nr_grefs == 1
> > ---
> > drivers/block/xen-blkback/common.h | 1 +
> > drivers/block/xen-blkback/xenbus.c | 38 +++++++++++++-----------------
> > 2 files changed, 17 insertions(+), 22 deletions(-)
> >
> > diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
> > index b0c71d3a81a0..524a79f10de6 100644
> > --- a/drivers/block/xen-blkback/common.h
> > +++ b/drivers/block/xen-blkback/common.h
> > @@ -313,6 +313,7 @@ struct xen_blkif {
> >
> > struct work_struct free_work;
> > unsigned int nr_ring_pages;
> > + bool multi_ref;
>
> You seem to have used spaces between the type and the variable name
> here, while neighbors also use hard tabs.
>
Oops. Xen vs. Linux coding style :-( I'll send a v3 with the whitespace fixed.
> The rest LGTM:
>
> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
>
> We should have forbidden the usage of ring-page-order = 0 and we could
> have avoided having to add the multi_ref variable, but that's too late
> now.
Thanks. Yes, that cat is out of the bag and has been for a while unfortunately.
Paul
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-02-02 16:45 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-28 13:04 [PATCH v2] xen-blkback: fix compatibility bug with single page rings Paul Durrant
2021-01-29 6:20 ` Dongli Zhang
2021-01-29 7:35 ` Jürgen Groß
[not found] ` <02d901d6f616$b0004750$1000d5f0$@xen.org>
2021-01-30 5:09 ` Dongli Zhang
2021-02-02 9:36 ` Paul Durrant
2021-02-02 16:28 ` Roger Pau Monné
2021-02-02 16:42 ` Paul Durrant
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).