From: Jan Beulich Date: Tue, 29 Jun 2021 09:02:35 +0000 (+0200) Subject: x86/paging: deal with log-dirty stats overflow X-Git-Tag: archive/raspbian/4.16.0+51-g0941d6cb-1+rpi1~2^2~42^2~381 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=17e91570c5a442d0500b05c157966ac212a1f12f;p=xen.git x86/paging: deal with log-dirty stats overflow While the precise values are unlikely of interest once they exceed 4 billion (allowing us to leave alone the domctl struct), we still shouldn't wrap or truncate the actual values. It is in particular problematic if the truncated values were zero (causing libxenguest to skip an iteration altogether) or a very small value (leading to premature exiting of the pre-copy phase). Change the internal fields to unsigned long, and suitably saturate for copying to guest context. Signed-off-by: Jan Beulich Acked-by: Andrew Cooper --- diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index c304c24526..dd6b2bdf6f 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -446,14 +446,16 @@ static int paging_log_dirty_op(struct domain *d, clean = (sc->op == XEN_DOMCTL_SHADOW_OP_CLEAN); - PAGING_DEBUG(LOGDIRTY, "log-dirty %s: dom %u faults=%u dirty=%u\n", + PAGING_DEBUG(LOGDIRTY, "log-dirty %s: dom %u faults=%lu dirty=%lu\n", (clean) ? "clean" : "peek", d->domain_id, d->arch.paging.log_dirty.fault_count, d->arch.paging.log_dirty.dirty_count); - sc->stats.fault_count = d->arch.paging.log_dirty.fault_count; - sc->stats.dirty_count = d->arch.paging.log_dirty.dirty_count; + sc->stats.fault_count = min(d->arch.paging.log_dirty.fault_count, + UINT32_MAX + 0UL); + sc->stats.dirty_count = min(d->arch.paging.log_dirty.dirty_count, + UINT32_MAX + 0UL); if ( guest_handle_is_null(sc->dirty_bitmap) ) /* caller may have wanted just to clean the state or access stats. */ diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 7213d184b0..92d54de0b9 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -190,8 +190,8 @@ struct log_dirty_domain { unsigned int failed_allocs; /* log-dirty mode stats */ - unsigned int fault_count; - unsigned int dirty_count; + unsigned long fault_count; + unsigned long dirty_count; /* functions which are paging mode specific */ const struct log_dirty_ops {