[CRIU] [PATCHv3 10/30] kdat: add compat_sigreturn feature
Dmitry Safonov
dsafonov at virtuozzo.com
Tue Jun 28 12:24:03 PDT 2016
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
criu/arch/aarch64/include/asm/restorer.h | 1 +
criu/arch/arm/include/asm/restorer.h | 1 +
criu/arch/ppc64/include/asm/restorer.h | 1 +
criu/arch/x86/crtools.c | 36 ++++++++++++++++++++++++++++++--
criu/arch/x86/include/asm/restorer.h | 7 +++++++
criu/include/kerndat.h | 1 +
criu/kerndat.c | 15 +++++++++++++
7 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/criu/arch/aarch64/include/asm/restorer.h b/criu/arch/aarch64/include/asm/restorer.h
index 9bf4268bb74e..19f459a0b08f 100644
--- a/criu/arch/aarch64/include/asm/restorer.h
+++ b/criu/arch/aarch64/include/asm/restorer.h
@@ -98,6 +98,7 @@ struct rt_sigframe {
#define RT_SIGFRAME_FPU(rt_sigframe) \
(&RT_SIGFRAME_AUX_CONTEXT(rt_sigframe)->fpsimd)
#define RT_SIGFRAME_OFFSET(rt_sigframe) 0
+#define kdat_compat_sigreturn_test() 0
int restore_gpregs(struct rt_sigframe *f, UserAarch64RegsEntry *r);
diff --git a/criu/arch/arm/include/asm/restorer.h b/criu/arch/arm/include/asm/restorer.h
index 34c2783323ef..e17a80e7a971 100644
--- a/criu/arch/arm/include/asm/restorer.h
+++ b/criu/arch/arm/include/asm/restorer.h
@@ -131,6 +131,7 @@ struct rt_sigframe {
#define RT_SIGFRAME_FPU(rt_sigframe) \
(&RT_SIGFRAME_AUX_SIGFRAME(rt_sigframe)->vfp)
#define RT_SIGFRAME_OFFSET(rt_sigframe) 0
+#define kdat_compat_sigreturn_test() 0
int restore_gpregs(struct rt_sigframe *f, UserArmRegsEntry *r);
diff --git a/criu/arch/ppc64/include/asm/restorer.h b/criu/arch/ppc64/include/asm/restorer.h
index 8c1473eb9b0a..e1c08ef17eeb 100644
--- a/criu/arch/ppc64/include/asm/restorer.h
+++ b/criu/arch/ppc64/include/asm/restorer.h
@@ -105,6 +105,7 @@ struct rt_sigframe {
#define RT_SIGFRAME_REGIP(rt_sigframe) ((long unsigned int)(rt_sigframe)->uc.uc_mcontext.gp_regs[PT_NIP])
#define RT_SIGFRAME_HAS_FPU(rt_sigframe) (1)
#define RT_SIGFRAME_FPU(rt_sigframe) (&(rt_sigframe)->uc.uc_mcontext)
+#define kdat_compat_sigreturn_test() 0
int restore_gpregs(struct rt_sigframe *f, UserPpc64RegsEntry *r);
int restore_nonsigframe_gpregs(UserPpc64RegsEntry *r);
diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c
index 2a768bcc4b27..58757b2830dc 100644
--- a/criu/arch/x86/crtools.c
+++ b/criu/arch/x86/crtools.c
@@ -3,6 +3,8 @@
#include <elf.h>
#include <sys/user.h>
#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/auxv.h>
#include "asm/processor-flags.h"
#include "asm/parasite-syscall.h"
@@ -20,6 +22,7 @@
#include "cpu.h"
#include "errno.h"
#include "syscall-codes.h"
+#include "kerndat.h"
#include "protobuf.h"
#include "images/core.pb-c.h"
@@ -67,6 +70,31 @@ void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *
~(X86_EFLAGS_TF | X86_EFLAGS_DF | X86_EFLAGS_IF));
}
+#ifdef CONFIG_X86_64
+/* Remaps 64-bit vDSO on the same addr, where it already is */
+int kdat_compat_sigreturn_test(void)
+{
+ unsigned long auxval;
+ int ret;
+
+ errno = 0;
+ auxval = getauxval(AT_SYSINFO_EHDR);
+ if (!auxval || errno == ENOENT) {
+ pr_err("Failed to get auxval, err: %lu\n", auxval);
+ return 0;
+ }
+ /*
+ * Mapping vDSO on very low unaligned address (1).
+ * We will get ENOMEM or EPERM if ARCH_MAP_VDSO_* exist,
+ * and ENOSYS if patches aren't in kernel.
+ */
+ ret = syscall(SYS_arch_prctl, ARCH_MAP_VDSO_32, 1);
+ if (ret == -1 && errno == ENOSYS)
+ return 0;
+ return 1;
+}
+#endif /* CONFIG_X86_64 */
+
int ptrace_get_regs(pid_t pid, user_regs_struct_t *regs);
int arch_task_compatible(pid_t pid)
{
@@ -102,8 +130,12 @@ static bool ldt_task_selectors(pid_t pid)
bool arch_can_dump_task(pid_t pid)
{
- /* FIXME: remove it */
- if (arch_task_compatible(pid)) {
+ int ret = arch_task_compatible(pid);
+
+ if (ret < 0)
+ return false;
+
+ if (ret && !kdat.has_compat_sigreturn) {
pr_err("Can't dump task %d running in 32-bit mode\n", pid);
return false;
}
diff --git a/criu/arch/x86/include/asm/restorer.h b/criu/arch/x86/include/asm/restorer.h
index 6ae4245bb800..66931e1d46fc 100644
--- a/criu/arch/x86/include/asm/restorer.h
+++ b/criu/arch/x86/include/asm/restorer.h
@@ -250,6 +250,12 @@ do { \
: \
: "r"(ret) \
: "memory")
+
+#ifndef ARCH_MAP_VDSO_32
+# define ARCH_MAP_VDSO_32 0x2002
+#endif
+
+extern int kdat_compat_sigreturn_test(void);
#else /* !CONFIG_X86_64 */
#define ARCH_RT_SIGRETURN(new_sp, rt_sigframe) \
@@ -286,6 +292,7 @@ do { \
(unsigned long)(rt_sigframe)->uc.uc_mcontext.ip
#define RT_SIGFRAME_FPU(rt_sigframe) (&(rt_sigframe)->fpu_state)
#define RT_SIGFRAME_HAS_FPU(rt_sigframe) (RT_SIGFRAME_FPU(rt_sigframe)->has_fpu)
+#define kdat_compat_sigreturn_test() 0
#endif /* !CONFIG_X86_64 */
static inline void
diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
index 015c3e0b756d..e1bf7ad043c6 100644
--- a/criu/include/kerndat.h
+++ b/criu/include/kerndat.h
@@ -33,6 +33,7 @@ struct kerndat_s {
unsigned long task_size;
bool ipv6;
bool has_loginuid;
+ bool has_compat_sigreturn;
enum pagemap_func pmap;
unsigned int has_xtlocks;
};
diff --git a/criu/kerndat.c b/criu/kerndat.c
index 5793de180960..0bd6961ff8aa 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -16,6 +16,7 @@
#include "compiler.h"
#include "sysctl.h"
#include "asm/types.h"
+#include "asm/restorer.h"
#include "cr_options.h"
#include "util.h"
#include "lsm.h"
@@ -457,6 +458,16 @@ static int kerndat_iptables_has_xtlocks(void)
return 0;
}
+static int kerndat_compat_restore(void)
+{
+ int ret = kdat_compat_sigreturn_test();
+
+ if (ret < 0) /* failure */
+ return ret;
+ kdat.has_compat_sigreturn = !!ret;
+ return 0;
+}
+
int kerndat_init(void)
{
int ret;
@@ -480,6 +491,8 @@ int kerndat_init(void)
ret = kerndat_loginuid(true);
if (!ret)
ret = kerndat_iptables_has_xtlocks();
+ if (!ret)
+ ret = kerndat_compat_restore();
kerndat_lsm();
@@ -509,6 +522,8 @@ int kerndat_init_rst(void)
ret = kerndat_loginuid(false);
if (!ret)
ret = kerndat_iptables_has_xtlocks();
+ if (!ret)
+ ret = kerndat_compat_restore();
kerndat_lsm();
--
2.9.0
More information about the CRIU
mailing list