[CRIU] [PATCH 3/4] ia32/futex: add dumping compat_robust_list

Dmitry Safonov dsafonov at virtuozzo.com
Wed May 3 12:40:14 PDT 2017


The kernel keeps two different pointers for 32-bit and 64-bit futex
lists: robust_list and compat_robust_list in task_struct.
So, dump compat_robust_list for ia32 tasks.

Note: this means that one can set *both* compat_robust_list and
robust_list pointers by using as we're here 32-bit and 64-bit syscalls.
That's one of mixed-bitness application questions.
For simplification (and omitting more syscalls), we dump here only
one of the pointers.

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/arch/aarch64/include/asm/dump.h |  2 +
 criu/arch/arm/include/asm/dump.h     |  2 +
 criu/arch/ppc64/include/asm/dump.h   |  2 +
 criu/arch/x86/crtools.c              | 72 ++++++++++++++++++++++++++++++++++++
 criu/arch/x86/include/asm/dump.h     |  1 +
 criu/cr-dump.c                       | 14 ++++++-
 6 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/criu/arch/aarch64/include/asm/dump.h b/criu/arch/aarch64/include/asm/dump.h
index 8a966628900b..bc3dbcf3ac2d 100644
--- a/criu/arch/aarch64/include/asm/dump.h
+++ b/criu/arch/aarch64/include/asm/dump.h
@@ -11,4 +11,6 @@ static inline void core_put_tls(CoreEntry *core, tls_t tls)
 	core->ti_aarch64->tls = tls;
 }
 
+#define get_task_futex_robust_list_compat(pid, info) -1
+
 #endif
diff --git a/criu/arch/arm/include/asm/dump.h b/criu/arch/arm/include/asm/dump.h
index f08e53843614..2382ba42c05d 100644
--- a/criu/arch/arm/include/asm/dump.h
+++ b/criu/arch/arm/include/asm/dump.h
@@ -11,4 +11,6 @@ static inline void core_put_tls(CoreEntry *core, tls_t tls)
 	core->ti_arm->tls = tls;
 }
 
+#define get_task_futex_robust_list_compat(pid, info) -1
+
 #endif
diff --git a/criu/arch/ppc64/include/asm/dump.h b/criu/arch/ppc64/include/asm/dump.h
index 6439adafd8ca..a81ee02bd387 100644
--- a/criu/arch/ppc64/include/asm/dump.h
+++ b/criu/arch/ppc64/include/asm/dump.h
@@ -8,4 +8,6 @@ extern void arch_free_thread_info(CoreEntry *core);
 
 #define core_put_tls(core, tls)
 
+#define get_task_futex_robust_list_compat(pid, info) -1
+
 #endif
diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c
index d0121b48e308..756a36e3726e 100644
--- a/criu/arch/x86/crtools.c
+++ b/criu/arch/x86/crtools.c
@@ -7,6 +7,7 @@
 
 #include "types.h"
 #include "log.h"
+#include "asm/compat.h"
 #include "asm/parasite-syscall.h"
 #include "asm/restorer.h"
 #include <compel/asm/fpu.h>
@@ -436,3 +437,74 @@ int restore_gpregs(struct rt_sigframe *f, UserX86RegsEntry *r)
 	}
 	return 0;
 }
+
+struct syscall_args32 {
+	uint32_t nr, arg0, arg1, arg2, arg3, arg4, arg5;
+};
+
+static void do_full_int80(struct syscall_args32 *args)
+{
+	register unsigned long bp asm("bp") = args->arg5;
+	asm volatile ("int $0x80"
+		      : "+a" (args->nr),
+			"+b" (args->arg0), "+c" (args->arg1), "+d" (args->arg2),
+			"+S" (args->arg3), "+D" (args->arg4), "+r" (bp)
+			: : "r8", "r9", "r10", "r11");
+	args->arg5 = bp;
+}
+
+static int get_robust_list32(pid_t pid, uintptr_t head, uintptr_t len)
+{
+	struct syscall_args32 s = {
+		.nr	= __NR32_get_robust_list,
+		.arg0	= pid,
+		.arg1	= (uint32_t)head,
+		.arg2	= (uint32_t)len,
+	};
+
+	do_full_int80(&s);
+	return (int)s.nr;
+}
+
+static int set_robust_list32(uint32_t head, uint32_t len)
+{
+	struct syscall_args32 s = {
+		.nr	= __NR32_set_robust_list,
+		.arg0	= head,
+		.arg1	= len,
+	};
+
+	do_full_int80(&s);
+	return (int)s.nr;
+}
+
+int get_task_futex_robust_list_compat(pid_t pid, ThreadCoreEntry *info)
+{
+	void *mmap32;
+	int ret = -1;
+
+	mmap32 = alloc_compat_syscall_stack();
+	if (!mmap32)
+		return -1;
+
+	ret = get_robust_list32(pid, (uintptr_t)mmap32, (uintptr_t)mmap32 + 4);
+
+	if (ret == -ENOSYS) {
+		/* Check native get_task_futex_robust_list() for details. */
+		if (set_robust_list32(0, 0) == (uint32_t)-ENOSYS) {
+			info->futex_rla		= 0;
+			info->futex_rla_len	= 0;
+			ret = 0;
+		}
+	} else if (ret == 0) {
+		uint32_t *arg1		= (uint32_t*)mmap32;
+
+		info->futex_rla		= *arg1;
+		info->futex_rla_len	= *(arg1 + 1);
+		ret = 0;
+	}
+
+
+	free_compat_syscall_stack(mmap32);
+	return ret;
+}
diff --git a/criu/arch/x86/include/asm/dump.h b/criu/arch/x86/include/asm/dump.h
index ca7cd675f21c..c79e0dfa9713 100644
--- a/criu/arch/x86/include/asm/dump.h
+++ b/criu/arch/x86/include/asm/dump.h
@@ -4,6 +4,7 @@
 extern int save_task_regs(void *, user_regs_struct_t *, user_fpregs_struct_t *);
 extern int arch_alloc_thread_info(CoreEntry *core);
 extern void arch_free_thread_info(CoreEntry *core);
+extern int get_task_futex_robust_list_compat(pid_t pid, ThreadCoreEntry *info);
 
 static inline void core_put_tls(CoreEntry *core, tls_t tls)
 {
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 4562eeeaa129..e0bebec7f209 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -679,8 +679,18 @@ int dump_thread_core(int pid, CoreEntry *core, const struct parasite_dump_thread
 	ThreadCoreEntry *tc = core->thread_core;
 
 	ret = collect_lsm_profile(pid, tc->creds);
-	if (!ret)
-		ret = get_task_futex_robust_list(pid, tc);
+	if (!ret) {
+		/*
+		 * XXX: It's possible to set two: 32-bit and 64-bit
+		 * futex list's heads. That makes about no sense, but
+		 * it's possible. Until we meet such application, dump
+		 * only one: native or compat futex's list pointer.
+		 */
+		if (!core_is_compat(core))
+			ret = get_task_futex_robust_list(pid, tc);
+		else
+			ret = get_task_futex_robust_list_compat(pid, tc);
+	}
 	if (!ret)
 		ret = dump_sched_info(pid, tc);
 	if (!ret) {
-- 
2.12.2



More information about the CRIU mailing list