Commit 7659c995 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

vm: don't overwrite vma->shmid for private mappings

shmid contains a file id for file mappings. It's required to determine,
which VMA-s are cowed. The parent maps a VMA and saves premmaped
address. Then  child trys to determing, which VMA-s must be inhereted
from parent, for that it compares addresses, flags and file id.

We don't want to transfer vma_area-s in restorer, so when a VMA entry is
copied in restorer memory, the premmaped address is save in shmid.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent b49d0960
...@@ -223,8 +223,6 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr, ...@@ -223,8 +223,6 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
return -1; return -1;
} }
vma->vma.fd = ret; vma->vma.fd = ret;
/* shmid will be used for a temporary address */
vma->vma.shmid = 0;
} }
nr_pages = vma_entry_len(&vma->vma) / PAGE_SIZE; nr_pages = vma_entry_len(&vma->vma) / PAGE_SIZE;
...@@ -240,7 +238,7 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr, ...@@ -240,7 +238,7 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
p->vma.start == vma->vma.start) { p->vma.start == vma->vma.start) {
pr_info("COW 0x%016"PRIx64"-0x%016"PRIx64" 0x%016"PRIx64" vma\n", pr_info("COW 0x%016"PRIx64"-0x%016"PRIx64" 0x%016"PRIx64" vma\n",
vma->vma.start, vma->vma.end, vma->vma.pgoff); vma->vma.start, vma->vma.end, vma->vma.pgoff);
paddr = decode_pointer(vma_premmaped_start(&p->vma)); paddr = decode_pointer(vma->premmaped_addr);
break; break;
} }
...@@ -292,13 +290,13 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr, ...@@ -292,13 +290,13 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
} }
vma_premmaped_start(&(vma->vma)) = (unsigned long) addr; vma->premmaped_addr = (unsigned long) addr;
pr_debug("\tpremap 0x%016"PRIx64"-0x%016"PRIx64" -> %016lx\n", pr_debug("\tpremap 0x%016"PRIx64"-0x%016"PRIx64" -> %016lx\n",
vma->vma.start, vma->vma.end, (unsigned long)addr); vma->vma.start, vma->vma.end, (unsigned long)addr);
if (vma->vma.flags & MAP_GROWSDOWN) { /* Skip gurad page */ if (vma->vma.flags & MAP_GROWSDOWN) { /* Skip gurad page */
vma->vma.start += PAGE_SIZE; vma->vma.start += PAGE_SIZE;
vma_premmaped_start(&vma->vma) += PAGE_SIZE; vma->premmaped_addr += PAGE_SIZE;
} }
if (vma_entry_is(&vma->vma, VMA_FILE_PRIVATE)) if (vma_entry_is(&vma->vma, VMA_FILE_PRIVATE))
...@@ -366,7 +364,7 @@ static int restore_priv_vma_content(pid_t pid) ...@@ -366,7 +364,7 @@ static int restore_priv_vma_content(pid_t pid)
off = (va - vma->vma.start) / PAGE_SIZE; off = (va - vma->vma.start) / PAGE_SIZE;
p = decode_pointer((off) * PAGE_SIZE + p = decode_pointer((off) * PAGE_SIZE +
vma_premmaped_start(&vma->vma)); vma->premmaped_addr);
set_bit(off, vma->page_bitmap); set_bit(off, vma->page_bitmap);
if (vma->ppage_bitmap) { /* inherited vma */ if (vma->ppage_bitmap) { /* inherited vma */
...@@ -404,7 +402,7 @@ static int restore_priv_vma_content(pid_t pid) ...@@ -404,7 +402,7 @@ static int restore_priv_vma_content(pid_t pid)
/* Remove pages, which were not shared with a child */ /* Remove pages, which were not shared with a child */
list_for_each_entry(vma, &rst_vmas.h, list) { list_for_each_entry(vma, &rst_vmas.h, list) {
unsigned long size, i = 0; unsigned long size, i = 0;
void *addr = decode_pointer(vma_premmaped_start(&vma->vma)); void *addr = decode_pointer(vma->premmaped_addr);
if (vma->ppage_bitmap == NULL) if (vma->ppage_bitmap == NULL)
continue; continue;
...@@ -574,7 +572,7 @@ static int unmap_guard_pages() ...@@ -574,7 +572,7 @@ static int unmap_guard_pages()
continue; continue;
if (vma->vma.flags & MAP_GROWSDOWN) { if (vma->vma.flags & MAP_GROWSDOWN) {
void *addr = decode_pointer(vma_premmaped_start(&vma->vma)); void *addr = decode_pointer(vma->premmaped_addr);
if (munmap(addr - PAGE_SIZE, PAGE_SIZE)) { if (munmap(addr - PAGE_SIZE, PAGE_SIZE)) {
pr_perror("Can't unmap guard page\n"); pr_perror("Can't unmap guard page\n");
...@@ -2220,6 +2218,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) ...@@ -2220,6 +2218,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
goto err_nv; goto err_nv;
*vme = vma->vma; *vme = vma->vma;
if (vma_priv(&vma->vma))
vma_premmaped_start(vme) = vma->premmaped_addr;
} }
/* /*
......
...@@ -23,6 +23,8 @@ struct vma_area { ...@@ -23,6 +23,8 @@ struct vma_area {
}; };
unsigned long *page_bitmap; /* existent pages */ unsigned long *page_bitmap; /* existent pages */
unsigned long *ppage_bitmap; /* parent's existent pages */ unsigned long *ppage_bitmap; /* parent's existent pages */
unsigned long premmaped_addr;
}; };
extern int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list); extern int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list);
...@@ -31,10 +33,17 @@ extern bool privately_dump_vma(struct vma_area *vma); ...@@ -31,10 +33,17 @@ extern bool privately_dump_vma(struct vma_area *vma);
#define vma_area_is(vma_area, s) vma_entry_is(&((vma_area)->vma), s) #define vma_area_is(vma_area, s) vma_entry_is(&((vma_area)->vma), s)
#define vma_area_len(vma_area) vma_entry_len(&((vma_area)->vma)) #define vma_area_len(vma_area) vma_entry_len(&((vma_area)->vma))
#define vma_premmaped_start(vma) ((vma)->shmid)
#define vma_entry_is(vma, s) (((vma)->status & (s)) == (s)) #define vma_entry_is(vma, s) (((vma)->status & (s)) == (s))
#define vma_entry_len(vma) ((vma)->end - (vma)->start) #define vma_entry_len(vma) ((vma)->end - (vma)->start)
/*
* vma_premmaped_start() can be used only in restorer.
* In other cases vma_area->premmaped_addr must be used.
* This hack is required, because vma_area isn't tranfered in restorer and
* shmid is used to determing which vma-s are cowed.
*/
#define vma_premmaped_start(vma) ((vma)->shmid)
static inline int in_vma_area(struct vma_area *vma, unsigned long addr) static inline int in_vma_area(struct vma_area *vma, unsigned long addr)
{ {
return addr >= (unsigned long)vma->vma.start && return addr >= (unsigned long)vma->vma.start &&
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment