[CRIU] [RFC 3/3] Probe for task size in restorer

Christopher Covington cov at codeaurora.org
Thu Jul 23 04:59:50 PDT 2015


If we want one CRIU binary to work across all AArch64 kernel
configurations, the task size cannot be hard coded. Introduce a
simple munmap based probing mechanism to detect the task size at
run time, searching between hard coded minimum, TASK_SIZE_MIN,
and maximum, TASK_SIZE_MAX, values. This fixes the following error
for CRIU on AArch64 kernels with CONFIG_ARM64_64K_PAGES=y.

  pie: Error (pie/restorer.c:778): Unable to unmap (-): -1210712064

This change is implemented in generic code but done in a way that
shouldn't affect the functionality or performance of other platforms.
For 32-bit ARM, where TASK_SIZE_MIN and TASK_SIZE_MAX are equal, the
number of calls of the munmap wrapper from pie/restorer.o does not
increase with this change, while it increases by one for AArch64. (I
also tried checking x86_64, but found 0 occurrences of munmap in that
objdump output.)

Signed-off-by: Christopher Covington <cov at codeaurora.org>
---
 arch/aarch64/include/asm/types.h |  3 ++-
 arch/arm/include/asm/types.h     |  2 ++
 arch/ppc64/include/asm/types.h   |  2 ++
 arch/x86/include/asm/types.h     |  3 +++
 pie/restorer.c                   | 14 +++++++++++---
 5 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/arch/aarch64/include/asm/types.h b/arch/aarch64/include/asm/types.h
index 6512f67..24fb27b 100644
--- a/arch/aarch64/include/asm/types.h
+++ b/arch/aarch64/include/asm/types.h
@@ -62,9 +62,10 @@ typedef struct user_pt_regs user_regs_struct_t;
 #define REG_SYSCALL_NR(regs)	((u64)(regs).regs[8])
 
 // Copied from the Linux kernel arch/arm64/include/asm/memory.h
-// FIXME: what about a 32bit task?
 
 #define TASK_SIZE (1ULL << 39)
+#define TASK_SIZE_MIN (1ULL << 32)
+#define TASK_SIZE_MAX (1ULL << 48)
 
 #define AT_VECTOR_SIZE 40
 
diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h
index 4efebdd..153f03f 100644
--- a/arch/arm/include/asm/types.h
+++ b/arch/arm/include/asm/types.h
@@ -97,6 +97,8 @@ struct user_vfp_exc {
 #define REG_SYSCALL_NR(regs) ((regs).ARM_r7)
 
 #define TASK_SIZE 0xbf000000
+#define TASK_SIZE_MIN TASK_SIZE
+#define TASK_SIZE_MAX TASK_SIZE
 
 #define AT_VECTOR_SIZE 40
 
diff --git a/arch/ppc64/include/asm/types.h b/arch/ppc64/include/asm/types.h
index 934a4fb..ea0f4fc 100644
--- a/arch/ppc64/include/asm/types.h
+++ b/arch/ppc64/include/asm/types.h
@@ -104,6 +104,8 @@ typedef uint64_t tls_t;
  */
 #define TASK_SIZE_USER64 (0x0000400000000000UL)
 #define TASK_SIZE TASK_SIZE_USER64
+#define TASK_SIZE_MIN TASK_SIZE
+#define TASK_SIZE_MAX TASK_SIZE
 
 static inline void *decode_pointer(uint64_t v) { return (void*)v; }
 static inline uint64_t encode_pointer(void *p) { return (uint64_t)p; }
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
index db41b75..c54478a 100644
--- a/arch/x86/include/asm/types.h
+++ b/arch/x86/include/asm/types.h
@@ -119,6 +119,9 @@ typedef struct {
 # define TASK_SIZE	(0xffffe000)
 #endif
 
+# define TASK_SIZE_MIN	TASK_SIZE
+# define TASK_SIZE_MAX	TASK_SIZE
+
 typedef u64 auxv_t;
 typedef u32 tls_t;
 
diff --git a/pie/restorer.c b/pie/restorer.c
index fa336fc..30f0323 100644
--- a/pie/restorer.c
+++ b/pie/restorer.c
@@ -744,7 +744,7 @@ void __export_unmap(void)
 static int unmap_old_vmas(void *premmapped_addr, unsigned long premmapped_len,
 		      void *bootstrap_start, unsigned long bootstrap_len)
 {
-	unsigned long s1, s2;
+	unsigned long s1, s2, task_size;
 	void *p1, *p2;
 	int ret;
 
@@ -772,10 +772,18 @@ static int unmap_old_vmas(void *premmapped_addr, unsigned long premmapped_len,
 		return -1;
 	}
 
-	ret = sys_munmap(p2 + s2, (void *) TASK_SIZE - (p2 + s2));
+	/* TODO: Use args->mm_saved_aux to get page size */
+	for (task_size = TASK_SIZE_MIN; task_size < TASK_SIZE_MAX; task_size <<= 1)
+		if (sys_munmap((void *)task_size, 65536))
+			break;
+
+	if (TASK_SIZE_MIN != TASK_SIZE_MAX)
+		pr_info("Found task size of %lx\n", task_size);
+
+	ret = sys_munmap(p2 + s2, (void *) task_size - (p2 + s2));
 	if (ret) {
 		pr_err("Unable to unmap (%p-%p): %d\n",
-				p2 + s2, (void *)TASK_SIZE, ret);
+				p2 + s2, (void *)task_size, ret);
 		return -1;
 	}
 
-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



More information about the CRIU mailing list