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