From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Liu Subject: [PATCH for 4.6 5/5] libxc: de-duplicate gpfns in populate_pfns Date: Fri, 4 Sep 2015 19:32:11 +0100 Message-ID: <1441391531-30004-6-git-send-email-wei.liu2@citrix.com> References: <1441391531-30004-1-git-send-email-wei.liu2@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1ZXvmg-0001Ge-Dm for xen-devel@lists.xenproject.org; Fri, 04 Sep 2015 18:32:22 +0000 In-Reply-To: <1441391531-30004-1-git-send-email-wei.liu2@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Xen-devel Cc: Andrew Cooper , Ian Jackson , Ian Campbell , Wei Liu List-Id: xen-devel@lists.xenproject.org The original implementation didn't consider there can be same gpfns present multiple times in the passed in array. The mechanism to prevent populating same gpfn multiple times only works if the same gpfn appear in different batch. This bug is discovered by save / restore Linux 4.1 32 bit kernel, which has several PTEs pointing to same gpfn. And gpfn pointed to by those PTEs are populated in one batch by libxc. When libxc calls x86_pv_localise_page, the original implementation failed to detect duplications in one batch. The fix is to de-duplicate gpfns in populate_pfns. Signed-off-by: Wei Liu --- tools/libxc/xc_sr_restore.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c index adb48da..09fe4c0 100644 --- a/tools/libxc/xc_sr_restore.c +++ b/tools/libxc/xc_sr_restore.c @@ -198,7 +198,7 @@ int populate_pfns(struct xc_sr_context *ctx, unsigned count, xc_interface *xch = ctx->xch; xen_pfn_t *mfns = malloc(count * sizeof(*mfns)), *pfns = malloc(count * sizeof(*pfns)); - unsigned i, nr_pfns = 0; + unsigned i, j, nr_pfns = 0; int rc = -1; if ( !mfns || !pfns ) @@ -209,14 +209,27 @@ int populate_pfns(struct xc_sr_context *ctx, unsigned count, } for ( i = 0; i < count; ++i ) + pfns[i] = mfns[i] = INVALID_MFN; + + for ( i = 0; i < count; ++i ) { if ( (!types || (types && (types[i] != XEN_DOMCTL_PFINFO_XTAB && types[i] != XEN_DOMCTL_PFINFO_BROKEN))) && !pfn_is_populated(ctx, original_pfns[i]) ) { - pfns[nr_pfns] = mfns[nr_pfns] = original_pfns[i]; - ++nr_pfns; + bool present = false; + + /* De-duplicate gpfns to avoid populating the same one twice */ + for ( j = 0; j < nr_pfns; ++j ) + if ( pfns[j] == original_pfns[i] ) + present = true; + + if ( !present ) + { + pfns[nr_pfns] = mfns[nr_pfns] = original_pfns[i]; + ++nr_pfns; + } } } -- 2.1.4