Jiri Slaby 87e5f9
From: Roger Pau Monne <roger.pau@citrix.com>
Jiri Slaby 87e5f9
Date: Tue, 18 Jul 2017 15:01:00 +0100
Jiri Slaby 87e5f9
Subject: [PATCH] xen: fix bio vec merging
Jiri Slaby 87e5f9
MIME-Version: 1.0
Jiri Slaby 87e5f9
Content-Type: text/plain; charset=UTF-8
Jiri Slaby 87e5f9
Content-Transfer-Encoding: 8bit
Jiri Slaby 87e5f9
References: bnc#1060662
Thomas Zimmermann 1d81d2
Patch-mainline: v4.12.9
Jiri Slaby 87e5f9
Git-commit: 462cdace790ac2ed6aad1b19c9c0af0143b6aab0
Jiri Slaby 87e5f9
Jiri Slaby 87e5f9
commit 462cdace790ac2ed6aad1b19c9c0af0143b6aab0 upstream.
Jiri Slaby 87e5f9
Jiri Slaby 87e5f9
The current test for bio vec merging is not fully accurate and can be
Jiri Slaby 87e5f9
tricked into merging bios when certain grant combinations are used.
Jiri Slaby 87e5f9
The result of these malicious bio merges is a bio that extends past
Jiri Slaby 87e5f9
the memory page used by any of the originating bios.
Jiri Slaby 87e5f9
Jiri Slaby 87e5f9
Take into account the following scenario, where a guest creates two
Jiri Slaby 87e5f9
grant references that point to the same mfn, ie: grant 1 -> mfn A,
Jiri Slaby 87e5f9
grant 2 -> mfn A.
Jiri Slaby 87e5f9
Jiri Slaby 87e5f9
These references are then used in a PV block request, and mapped by
Jiri Slaby 87e5f9
the backend domain, thus obtaining two different pfns that point to
Jiri Slaby 87e5f9
the same mfn, pfn B -> mfn A, pfn C -> mfn A.
Jiri Slaby 87e5f9
Jiri Slaby 87e5f9
If those grants happen to be used in two consecutive sectors of a disk
Jiri Slaby 87e5f9
IO operation becoming two different bios in the backend domain, the
Jiri Slaby 87e5f9
checks in xen_biovec_phys_mergeable will succeed, because bfn1 == bfn2
Jiri Slaby 87e5f9
(they both point to the same mfn). However due to the bio merging,
Jiri Slaby 87e5f9
the backend domain will end up with a bio that expands past mfn A into
Jiri Slaby 87e5f9
mfn A + 1.
Jiri Slaby 87e5f9
Jiri Slaby 87e5f9
Fix this by making sure the check in xen_biovec_phys_mergeable takes
Jiri Slaby 87e5f9
into account the offset and the length of the bio, this basically
Jiri Slaby 87e5f9
replicates whats done in __BIOVEC_PHYS_MERGEABLE using mfns (bus
Jiri Slaby 87e5f9
addresses). While there also remove the usage of
Jiri Slaby 87e5f9
__BIOVEC_PHYS_MERGEABLE, since that's already checked by the callers
Jiri Slaby 87e5f9
of xen_biovec_phys_mergeable.
Jiri Slaby 87e5f9
Jiri Slaby 87e5f9
Reported-by: "Jan H. Schönherr" <jschoenh@amazon.de>
Jiri Slaby 87e5f9
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Jiri Slaby 87e5f9
Reviewed-by: Juergen Gross <jgross@suse.com>
Jiri Slaby 87e5f9
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Jiri Slaby 87e5f9
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby 87e5f9
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 87e5f9
---
Jiri Slaby 87e5f9
 drivers/xen/biomerge.c | 3 +--
Jiri Slaby 87e5f9
 1 file changed, 1 insertion(+), 2 deletions(-)
Jiri Slaby 87e5f9
Jiri Slaby 87e5f9
diff --git a/drivers/xen/biomerge.c b/drivers/xen/biomerge.c
Jiri Slaby 87e5f9
index 4da69dbf7dca..1bdd02a6d6ac 100644
Jiri Slaby 87e5f9
--- a/drivers/xen/biomerge.c
Jiri Slaby 87e5f9
+++ b/drivers/xen/biomerge.c
Jiri Slaby 87e5f9
@@ -10,8 +10,7 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
Jiri Slaby 87e5f9
 	unsigned long bfn1 = pfn_to_bfn(page_to_pfn(vec1->bv_page));
Jiri Slaby 87e5f9
 	unsigned long bfn2 = pfn_to_bfn(page_to_pfn(vec2->bv_page));
Jiri Slaby 87e5f9
 
Jiri Slaby 87e5f9
-	return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) &&
Jiri Slaby 87e5f9
-		((bfn1 == bfn2) || ((bfn1+1) == bfn2));
Jiri Slaby 87e5f9
+	return bfn1 + PFN_DOWN(vec1->bv_offset + vec1->bv_len) == bfn2;
Jiri Slaby 87e5f9
 #else
Jiri Slaby 87e5f9
 	/*
Jiri Slaby 87e5f9
 	 * XXX: Add support for merging bio_vec when using different page
Jiri Slaby 87e5f9
-- 
Jiri Slaby 87e5f9
2.14.2
Jiri Slaby 87e5f9