[Devel,1/2] criu: proc_parse -- Add guard page the same way as kernel detects them

Submitted by Cyrill Gorcunov on Nov. 24, 2016, 3:48 p.m.

Details

Message ID 1480002497-21671-2-git-send-email-gorcunov@virtuozzo.com
State New
Series "criu: Make sure we don't hit guard page when looking for syscall-ip"
Headers show

Commit Message

Cyrill Gorcunov Nov. 24, 2016, 3:48 p.m.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 criu/include/vma.h | 12 ++++++++++++
 criu/proc_parse.c  | 20 ++++++++++++--------
 2 files changed, 24 insertions(+), 8 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/vma.h b/criu/include/vma.h
index 3930421..be591d5 100644
--- a/criu/include/vma.h
+++ b/criu/include/vma.h
@@ -1,6 +1,8 @@ 
 #ifndef __CR_VMA_H__
 #define __CR_VMA_H__
 
+#include <sys/mman.h>
+
 #include "asm/types.h"
 #include "image.h"
 #include "list.h"
@@ -110,4 +112,14 @@  static inline bool vma_area_is_private(struct vma_area *vma,
 	return vma_entry_is_private(vma->e, task_size);
 }
 
+static inline int vma_growsdown(struct vma_area *vma, unsigned long addr)
+{
+	return vma && (vma->e->end == addr) && (vma->e->flags & MAP_GROWSDOWN);
+}
+
+static inline int stack_guard_page_start(struct vma_area *vma, struct vma_area *vma_prev, unsigned long addr)
+{
+	return (vma->e->flags & MAP_GROWSDOWN) && (vma->e->start == addr) && !vma_growsdown(vma_prev, addr);
+}
+
 #endif /* __CR_VMA_H__ */
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index 8e6096d..0c457f2 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -612,7 +612,7 @@  err_bogus_mapfile:
 
 static int vma_list_add(struct vma_area *vma_area,
 			struct vm_area_list *vma_area_list,
-			unsigned long *prev_end,
+			struct vma_area **prev_vma,
 			struct vma_file_info *vfi, struct vma_file_info *prev_vfi)
 {
 	if (vma_area->e->status & VMA_UNSUPP) {
@@ -622,10 +622,14 @@  static int vma_list_add(struct vma_area *vma_area,
 	}
 
 	/* Add a guard page only if here is enough space for it */
-	if ((vma_area->e->flags & MAP_GROWSDOWN) &&
-	    *prev_end < vma_area->e->start)
-		vma_area->e->start -= PAGE_SIZE; /* Guard page */
-	*prev_end = vma_area->e->end;
+	if (stack_guard_page_start(vma_area, *prev_vma, vma_area->e->start) &&
+	    (*prev_vma && (*prev_vma)->e->end < vma_area->e->start)) {
+		pr_debug("adjusting VMA's start to cope with guard page (%lx -> %lx)-%lx\n",
+			 vma_area->e->start, (vma_area->e->start - PAGE_SIZE),
+			 vma_area->e->end);
+		vma_area->e->start -= PAGE_SIZE;
+	}
+	*prev_vma = vma_area;
 
 	list_add_tail(&vma_area->list, &vma_area_list->h);
 	vma_area_list->nr++;
@@ -646,8 +650,8 @@  static int vma_list_add(struct vma_area *vma_area,
 int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list,
 					dump_filemap_t dump_filemap)
 {
-	struct vma_area *vma_area = NULL;
-	unsigned long start, end, pgoff, prev_end = 0;
+	struct vma_area *vma_area = NULL, *prev_vma = NULL;
+	unsigned long start, end, pgoff;
 	char r, w, x, s;
 	int ret = -1, vm_file_fd = -1;
 	struct vma_file_info vfi;
@@ -704,7 +708,7 @@  int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list,
 		}
 
 		if (vma_area && vma_list_add(vma_area, vma_area_list,
-						&prev_end, &vfi, &prev_vfi))
+						&prev_vma, &vfi, &prev_vfi))
 			goto err;
 
 		if (eof)