[1/2] kerndat: Detect if we have guard page mangle in procfs output

Submitted by Cyrill Gorcunov on June 20, 2017, 2:22 p.m.

Details

Message ID 1497968567-9213-2-git-send-email-gorcunov@openvz.org
State New
Series "mem: Address dropped guard pages from procfs report"
Headers show

Commit Message

Cyrill Gorcunov June 20, 2017, 2:22 p.m.
In vanilla kernel commit 1be7107fbe18eed3e319a6c3e83c78254b693acb
show_map_vma() no longer report PAGE_SIZE. Detec it with
simple test and remember in kdat settings.

Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 criu/include/kerndat.h |  1 +
 criu/kerndat.c         | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
index a6dac92f97a7..76add98f94f2 100644
--- a/criu/include/kerndat.h
+++ b/criu/include/kerndat.h
@@ -39,6 +39,7 @@  struct kerndat_s {
 	bool has_memfd;
 	bool has_fdinfo_lock;
 	unsigned long task_size;
+	bool mm_guard_page_maps;
 	bool ipv6;
 	enum loginuid_func luid;
 	bool compat_cr;
diff --git a/criu/kerndat.c b/criu/kerndat.c
index 5bca4bfc92ad..48c6857436cb 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -464,6 +464,56 @@  static int get_task_size(void)
 	return 0;
 }
 
+static int kerndat_mm_guard_page_maps(void)
+{
+	int num, ret = -1, detected = 0;
+	unsigned long start, end;
+	char r, w, x, s;
+	char buf[1024];
+	FILE *maps;
+
+	void *mem = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN,
+			 -1, 0);
+	if (mem == MAP_FAILED) {
+		pr_perror("Can't mmap stack area");
+		return -1;
+	}
+
+	maps = fopen("/proc/self/maps", "r");
+	if (maps == NULL) {
+		munmap(mem, 4096);
+		return -1;
+	}
+
+	while (fgets(buf, sizeof(buf), maps)) {
+		num = sscanf(buf, "%lx-%lx %c%c%c%c",
+			     &start, &end, &r, &w, &x, &s);
+		if (num < 6) {
+			pr_err("Can't parse: %s\n", buf);
+			goto err;
+		}
+
+		if (start == (unsigned long)mem) {
+			kdat.mm_guard_page_maps = false;
+			detected = 1;
+			break;
+		} else if (start == ((unsigned long)mem + PAGE_SIZE)) {
+			kdat.mm_guard_page_maps = true;
+			detected = 1;
+			break;
+		}
+	}
+
+	if (detected)
+		ret = 0;
+
+err:
+	munmap(mem, 4096);
+	fclose(maps);
+	return ret;
+}
+
 int kerndat_fdinfo_has_lock()
 {
 	int fd, pfd = -1, exit_code = -1, len;
@@ -904,6 +954,8 @@  int kerndat_init(void)
 		ret = kerndat_has_ns_get_parent();
 	if (!ret)
 		ret = kerndat_has_pid_for_children_ns();
+	if (!ret)
+		ret = kerndat_mm_guard_page_maps();
 
 	kerndat_lsm();
 	kerndat_mmap_min_addr();