66 lines
2.3 KiB
Diff
66 lines
2.3 KiB
Diff
From d52f00960c1070c683809faddd35a2223e2b8a6e Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com>
|
|
Date: Tue, 3 Nov 2015 16:40:43 +0000
|
|
Subject: [PATCH 6/7] xen-blkback: read from indirect descriptors only once
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Since indirect descriptors are in memory shared with the frontend, the
|
|
frontend could alter the first_sect and last_sect values after they have
|
|
been validated but before they are recorded in the request. This may
|
|
result in I/O requests that overflow the foreign page, possibly
|
|
overwriting local pages when the I/O request is executed.
|
|
|
|
When parsing indirect descriptors, only read first_sect and last_sect
|
|
once.
|
|
|
|
This is part of XSA155.
|
|
|
|
CC: stable@vger.kernel.org
|
|
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
|
|
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
|
|
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
|
----
|
|
v2: This is against v4.3
|
|
---
|
|
drivers/block/xen-blkback/blkback.c | 12 +++++++-----
|
|
1 file changed, 7 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
|
|
index 6a685ae..f2e7a38 100644
|
|
--- a/drivers/block/xen-blkback/blkback.c
|
|
+++ b/drivers/block/xen-blkback/blkback.c
|
|
@@ -950,6 +950,8 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req,
|
|
goto unmap;
|
|
|
|
for (n = 0, i = 0; n < nseg; n++) {
|
|
+ uint8_t first_sect, last_sect;
|
|
+
|
|
if ((n % SEGS_PER_INDIRECT_FRAME) == 0) {
|
|
/* Map indirect segments */
|
|
if (segments)
|
|
@@ -958,14 +960,14 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req,
|
|
}
|
|
i = n % SEGS_PER_INDIRECT_FRAME;
|
|
pending_req->segments[n]->gref = segments[i].gref;
|
|
- seg[n].nsec = segments[i].last_sect -
|
|
- segments[i].first_sect + 1;
|
|
- seg[n].offset = (segments[i].first_sect << 9);
|
|
- if ((segments[i].last_sect >= (PAGE_SIZE >> 9)) ||
|
|
- (segments[i].last_sect < segments[i].first_sect)) {
|
|
+ first_sect = READ_ONCE(segments[i].first_sect);
|
|
+ last_sect = READ_ONCE(segments[i].last_sect);
|
|
+ if (last_sect >= (PAGE_SIZE >> 9) || last_sect < first_sect) {
|
|
rc = -EINVAL;
|
|
goto unmap;
|
|
}
|
|
+ seg[n].nsec = last_sect - first_sect + 1;
|
|
+ seg[n].offset = first_sect << 9;
|
|
preq->nr_sects += seg[n].nsec;
|
|
}
|
|
|
|
--
|
|
2.1.0
|
|
|