|
|
72b139 |
From 8a4a164f3e33be9b2d28d54fe430e92f40626054 Mon Sep 17 00:00:00 2001
|
|
|
72b139 |
From: Cyrill Gorcunov <gorcunov@openvz.org>
|
|
|
72b139 |
Date: Mon, 26 Jun 2017 23:55:28 +0300
|
|
|
72b139 |
Subject: [PATCH 1/2] kerndat: Detect if we have guard page mangle in procfs
|
|
|
72b139 |
output
|
|
|
72b139 |
|
|
|
72b139 |
In vanilla kernel commit 1be7107fbe18eed3e319a6c3e83c78254b693acb
|
|
|
72b139 |
show_map_vma() no longer report PAGE_SIZE. Detect it with
|
|
|
72b139 |
simple test and remember in kdat settings.
|
|
|
72b139 |
|
|
|
72b139 |
Suggested-by: Oleg Nesterov <oleg@redhat.com>
|
|
|
72b139 |
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
|
|
|
72b139 |
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
|
|
|
72b139 |
---
|
|
|
72b139 |
criu/include/kerndat.h | 1 +
|
|
|
72b139 |
criu/kerndat.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
72b139 |
2 files changed, 77 insertions(+)
|
|
|
72b139 |
|
|
|
72b139 |
diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
|
|
|
72b139 |
index ba8c10da7..891cbdd41 100644
|
|
|
72b139 |
--- a/criu/include/kerndat.h
|
|
|
72b139 |
+++ b/criu/include/kerndat.h
|
|
|
72b139 |
@@ -44,6 +44,7 @@ struct kerndat_s {
|
|
|
72b139 |
unsigned int has_xtlocks;
|
|
|
72b139 |
unsigned long mmap_min_addr;
|
|
|
72b139 |
bool has_tcp_half_closed;
|
|
|
72b139 |
+ bool stack_guard_gap_hidden;
|
|
|
72b139 |
};
|
|
|
72b139 |
|
|
|
72b139 |
extern struct kerndat_s kdat;
|
|
|
72b139 |
diff --git a/criu/kerndat.c b/criu/kerndat.c
|
|
|
72b139 |
index 354fb672b..80ec58bcf 100644
|
|
|
72b139 |
--- a/criu/kerndat.c
|
|
|
72b139 |
+++ b/criu/kerndat.c
|
|
|
72b139 |
@@ -563,6 +563,80 @@ int kerndat_tcp_repair(void)
|
|
|
72b139 |
return exit_code;
|
|
|
72b139 |
}
|
|
|
72b139 |
|
|
|
72b139 |
+static int kerndat_detect_stack_guard_gap(void)
|
|
|
72b139 |
+{
|
|
|
72b139 |
+ int num, ret = -1, detected = 0;
|
|
|
72b139 |
+ unsigned long start, end;
|
|
|
72b139 |
+ char r, w, x, s;
|
|
|
72b139 |
+ char buf[1024];
|
|
|
72b139 |
+ FILE *maps;
|
|
|
72b139 |
+ void *mem;
|
|
|
72b139 |
+
|
|
|
72b139 |
+ mem = mmap(NULL, (3ul << 20), PROT_READ | PROT_WRITE,
|
|
|
72b139 |
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
|
|
|
72b139 |
+ if (mem == MAP_FAILED) {
|
|
|
72b139 |
+ pr_perror("Can't mmap stack area");
|
|
|
72b139 |
+ return -1;
|
|
|
72b139 |
+ }
|
|
|
72b139 |
+ munmap(mem, (3ul << 20));
|
|
|
72b139 |
+
|
|
|
72b139 |
+ mem = mmap(mem + (2ul << 20), (1ul << 20), PROT_READ | PROT_WRITE,
|
|
|
72b139 |
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, -1, 0);
|
|
|
72b139 |
+ if (mem == MAP_FAILED) {
|
|
|
72b139 |
+ pr_perror("Can't mmap stack area");
|
|
|
72b139 |
+ return -1;
|
|
|
72b139 |
+ }
|
|
|
72b139 |
+
|
|
|
72b139 |
+ maps = fopen("/proc/self/maps", "r");
|
|
|
72b139 |
+ if (maps == NULL) {
|
|
|
72b139 |
+ munmap(mem, 4096);
|
|
|
72b139 |
+ return -1;
|
|
|
72b139 |
+ }
|
|
|
72b139 |
+
|
|
|
72b139 |
+ while (fgets(buf, sizeof(buf), maps)) {
|
|
|
72b139 |
+ num = sscanf(buf, "%lx-%lx %c%c%c%c",
|
|
|
72b139 |
+ &start, &end, &r, &w, &x, &s);
|
|
|
72b139 |
+ if (num < 6) {
|
|
|
72b139 |
+ pr_err("Can't parse: %s\n", buf);
|
|
|
72b139 |
+ goto err;
|
|
|
72b139 |
+ }
|
|
|
72b139 |
+
|
|
|
72b139 |
+ /*
|
|
|
72b139 |
+ * When reading /proc/$pid/[s]maps the
|
|
|
72b139 |
+ * start/end addresses migh be cutted off
|
|
|
72b139 |
+ * with PAGE_SIZE on kernels prior 4.12
|
|
|
72b139 |
+ * (see kernel commit 1be7107fbe18ee).
|
|
|
72b139 |
+ *
|
|
|
72b139 |
+ * Same time there was semi-complete
|
|
|
72b139 |
+ * patch released which hitted a number
|
|
|
72b139 |
+ * of repos (Ubuntu, Fedora) where instead
|
|
|
72b139 |
+ * of PAGE_SIZE the 1M gap is cutted off.
|
|
|
72b139 |
+ */
|
|
|
72b139 |
+ if (start == (unsigned long)mem) {
|
|
|
72b139 |
+ kdat.stack_guard_gap_hidden = false;
|
|
|
72b139 |
+ detected = 1;
|
|
|
72b139 |
+ break;
|
|
|
72b139 |
+ } else if (start == ((unsigned long)mem + (1ul << 20))) {
|
|
|
72b139 |
+ pr_warn("Unsupported stack guard detected, confused but continue\n");
|
|
|
72b139 |
+ kdat.stack_guard_gap_hidden = true;
|
|
|
72b139 |
+ detected = 1;
|
|
|
72b139 |
+ break;
|
|
|
72b139 |
+ } else if (start == ((unsigned long)mem + PAGE_SIZE)) {
|
|
|
72b139 |
+ kdat.stack_guard_gap_hidden = true;
|
|
|
72b139 |
+ detected = 1;
|
|
|
72b139 |
+ break;
|
|
|
72b139 |
+ }
|
|
|
72b139 |
+ }
|
|
|
72b139 |
+
|
|
|
72b139 |
+ if (detected)
|
|
|
72b139 |
+ ret = 0;
|
|
|
72b139 |
+
|
|
|
72b139 |
+err:
|
|
|
72b139 |
+ munmap(mem, (1ul << 20));
|
|
|
72b139 |
+ fclose(maps);
|
|
|
72b139 |
+ return ret;
|
|
|
72b139 |
+}
|
|
|
72b139 |
+
|
|
|
72b139 |
int kerndat_init(void)
|
|
|
72b139 |
{
|
|
|
72b139 |
int ret;
|
|
|
72b139 |
@@ -676,6 +750,8 @@ int kerndat_init(void)
|
|
|
72b139 |
ret = kerndat_iptables_has_xtlocks();
|
|
|
72b139 |
if (!ret)
|
|
|
72b139 |
ret = kerndat_tcp_repair();
|
|
|
72b139 |
+ if (!ret)
|
|
|
72b139 |
+ ret = kerndat_detect_stack_guard_gap();
|
|
|
72b139 |
|
|
|
72b139 |
kerndat_lsm();
|
|
|
72b139 |
kerndat_mmap_min_addr();
|
|
|
72b139 |
--
|
|
|
72b139 |
2.13.0
|
|
|
72b139 |
|