[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