From 57d25e7cea126cf83b81cc2ee2578bbd917ffff6 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Fri, 22 Nov 2013 18:19:23 +0400 Subject: [PATCH] mm: fix expression to determine which vma-s can be shared Currently only addresses are compared. It's obviously not enough. * First of all the parent vma must be private. * Both vma-s must have the identical set of MAP_GROWSDOWN and MAP_FILES flags. * Both vma-s must be linked to the same file. https://bugzilla.openvz.org/show_bug.cgi?id=2824 Signed-off-by: Andrey Vagin Signed-off-by: Pavel Emelyanov --- cr-restore.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/cr-restore.c b/cr-restore.c index 1c67a2026..6a0637eb2 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -234,14 +234,24 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr, if (p->vma.start > vma->vma.start) break; - if (p->vma.end == vma->vma.end && - p->vma.start == vma->vma.start) { - pr_info("COW 0x%016"PRIx64"-0x%016"PRIx64" 0x%016"PRIx64" vma\n", - vma->vma.start, vma->vma.end, vma->vma.pgoff); - paddr = decode_pointer(vma->premmaped_addr); - break; - } + if (!vma_priv(&p->vma)) + continue; + if (p->vma.end != vma->vma.end || + p->vma.start != vma->vma.start) + continue; + + /* Check flags, which must be identical for both vma-s */ + if ((vma->vma.flags ^ p->vma.flags) & (MAP_GROWSDOWN | MAP_ANONYMOUS)) + break; + + if (!(vma->vma.flags & MAP_ANONYMOUS) && + vma->vma.shmid != p->vma.shmid) + break; + + pr_info("COW 0x%016"PRIx64"-0x%016"PRIx64" 0x%016"PRIx64" vma\n", + vma->vma.start, vma->vma.end, vma->vma.pgoff); + paddr = decode_pointer(vma->premmaped_addr); } *pvma = p;