Message ID | 20190902124143.119478-1-Tianyu.Lan@microsoft.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [V2] x86/Hyper-V: Fix overflow issue in the fill_gva_list() | expand |
From: Tianyu Lan <Tianyu.Lan@microsoft.com> Sent: Monday, September 2, 2019 5:42 AM > > When the 'start' parameter is >= 0xFF000000 on 32-bit > systems, or >= 0xFFFFFFFF'FF000000 on 64-bit systems, > fill_gva_list gets into an infinite loop. With such inputs, > 'cur' overflows after adding HV_TLB_FLUSH_UNIT and always > compares as less than end. Memory is filled with guest virtual > addresses until the system crashes > > Fix this by never incrementing 'cur' to be larger than 'end'. > > Reported-by: Jong Hyun Park <park.jonghyun@yonsei.ac.kr> > Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com> > Fixes: 2ffd9e33ce4a ("x86/hyper-v: Use hypercall for remote TLB flush") > --- > Change since v1: > - Simply the commit message > > arch/x86/hyperv/mmu.c | 8 +++++--- > 1 file changed, 5 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c > index e65d7fe6489f..5208ba49c89a 100644 > --- a/arch/x86/hyperv/mmu.c > +++ b/arch/x86/hyperv/mmu.c > @@ -37,12 +37,14 @@ static inline int fill_gva_list(u64 gva_list[], int offset, > * Lower 12 bits encode the number of additional > * pages to flush (in addition to the 'cur' page). > */ > - if (diff >= HV_TLB_FLUSH_UNIT) > + if (diff >= HV_TLB_FLUSH_UNIT) { > gva_list[gva_n] |= ~PAGE_MASK; > - else if (diff) > + cur += HV_TLB_FLUSH_UNIT; > + } else if (diff) { > gva_list[gva_n] |= (diff - 1) >> PAGE_SHIFT; > + cur = end; > + } > > - cur += HV_TLB_FLUSH_UNIT; > gva_n++; > > } while (cur < end); > -- > 2.14.5 Reviewed-by: Michael Kelley <mikelley@microsoft.com>
diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index e65d7fe6489f..5208ba49c89a 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -37,12 +37,14 @@ static inline int fill_gva_list(u64 gva_list[], int offset, * Lower 12 bits encode the number of additional * pages to flush (in addition to the 'cur' page). */ - if (diff >= HV_TLB_FLUSH_UNIT) + if (diff >= HV_TLB_FLUSH_UNIT) { gva_list[gva_n] |= ~PAGE_MASK; - else if (diff) + cur += HV_TLB_FLUSH_UNIT; + } else if (diff) { gva_list[gva_n] |= (diff - 1) >> PAGE_SHIFT; + cur = end; + } - cur += HV_TLB_FLUSH_UNIT; gva_n++; } while (cur < end);