[CRIU] [PATCHv2 14/17] x86: add user_regs_native macro (optional)

Dmitry Safonov dsafonov at virtuozzo.com
Tue Apr 12 09:10:52 PDT 2016


This will document that {get,set}_user_reg should be used
only on initialized register set. Otherwise, after some code
changes we may find ourself in situation when setting not
inited user regs will set them for compatible register set:
(is_native == false).

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/arch/aarch64/include/asm/types.h |  2 ++
 criu/arch/arm/include/asm/types.h     |  2 ++
 criu/arch/ppc64/include/asm/types.h   |  1 +
 criu/arch/x86/crtools.c               | 14 +++++++-------
 criu/arch/x86/include/asm/types.h     | 34 +++++++++++++++++++++++++---------
 5 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/criu/arch/aarch64/include/asm/types.h b/criu/arch/aarch64/include/asm/types.h
index 970fde7412cc..203b44ab363f 100644
--- a/criu/arch/aarch64/include/asm/types.h
+++ b/criu/arch/aarch64/include/asm/types.h
@@ -61,6 +61,8 @@ typedef struct user_pt_regs user_regs_struct_t;
 #define REG_IP(regs)		((u64)(regs).pc)
 #define REG_SYSCALL_NR(regs)	((u64)(regs).regs[8])
 
+#define user_regs_native(pregs)			true
+
 /*
  * Range for task size calculated from the following Linux kernel files:
  *   arch/arm64/include/asm/memory.h
diff --git a/criu/arch/arm/include/asm/types.h b/criu/arch/arm/include/asm/types.h
index b186aafde52d..87f4c3c817d1 100644
--- a/criu/arch/arm/include/asm/types.h
+++ b/criu/arch/arm/include/asm/types.h
@@ -96,6 +96,8 @@ struct user_vfp_exc {
 #define REG_IP(regs)  ((regs).ARM_pc)
 #define REG_SYSCALL_NR(regs) ((regs).ARM_r7)
 
+#define user_regs_native(pregs)			true
+
 /*
  * Range for task size calculated from the following Linux kernel files:
  *   arch/arm/include/asm/memory.h
diff --git a/criu/arch/ppc64/include/asm/types.h b/criu/arch/ppc64/include/asm/types.h
index be29dbb37a9a..fed09c465888 100644
--- a/criu/arch/ppc64/include/asm/types.h
+++ b/criu/arch/ppc64/include/asm/types.h
@@ -79,6 +79,7 @@ typedef UserPpc64RegsEntry UserRegsEntry;
 #define REG_IP(regs)            ((u64)(regs).nip)
 #define REG_SYSCALL_NR(regs)    ((u64)(regs).gpr[0])
 
+#define user_regs_native(pregs)			true
 
 #define CORE_THREAD_ARCH_INFO(core) core->ti_ppc64
 
diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c
index 172c534306a3..ad957cdf4a2d 100644
--- a/criu/arch/x86/crtools.c
+++ b/criu/arch/x86/crtools.c
@@ -67,7 +67,7 @@ int arch_task_compatible(pid_t pid)
 	if (ret)
 		return -1;
 
-	return !r.is_native;
+	return !user_regs_native(&r);
 }
 
 #define USER32_CS	0x23
@@ -118,7 +118,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 	user_regs_struct_t regs = ctl->orig.regs;
 	int err;
 
-	if (regs.is_native) {
+	if (user_regs_native(&regs)) {
 		user_regs_struct64 *r = &regs.native;
 
 		r->ax  = (uint64_t)nr;
@@ -147,7 +147,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 }
 
 #define get_signed_user_reg(pregs, name)				\
-	(((pregs)->is_native) ? (int64_t)((pregs)->native.name) :	\
+	((user_regs_native(pregs)) ? (int64_t)((pregs)->native.name) :	\
 				(int32_t)((pregs)->compat.name))
 
 int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
@@ -180,7 +180,7 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
 #define assign_reg(dst, src, e)		do { dst->e = (__typeof__(dst->e))src.e; } while (0)
 #define assign_array(dst, src, e)	memcpy(dst->e, &src.e, sizeof(src.e))
 
-	if (regs.is_native) {
+	if (user_regs_native(&regs)) {
 		assign_reg(gpregs, regs.native, r15);
 		assign_reg(gpregs, regs.native, r14);
 		assign_reg(gpregs, regs.native, r13);
@@ -300,11 +300,11 @@ int ptrace_get_regs(pid_t pid, user_regs_struct_t *regs)
 
 	ret = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov);
 	if (iov.iov_len == sizeof(regs->native)) {
-		regs->is_native = true;
+		regs->__is_native = NATIVE_MAGIC;
 		return ret;
 	}
 	if (iov.iov_len == sizeof(regs->compat)) {
-		regs->is_native = false;
+		regs->__is_native = COMPAT_MAGIC;
 		return ret;
 	}
 
@@ -318,7 +318,7 @@ int ptrace_set_regs(pid_t pid, user_regs_struct_t *regs)
 {
 	struct iovec iov;
 
-	if (regs->is_native) {
+	if (user_regs_native(regs)) {
 		iov.iov_base = &regs->native;
 		iov.iov_len = sizeof(user_regs_struct64);
 	} else {
diff --git a/criu/arch/x86/include/asm/types.h b/criu/arch/x86/include/asm/types.h
index 32b1c014afa1..75621a7d046e 100644
--- a/criu/arch/x86/include/asm/types.h
+++ b/criu/arch/x86/include/asm/types.h
@@ -8,6 +8,7 @@
 #include "asm/bitops.h"
 #include "asm/int.h"
 
+#include "bug.h"
 #include "images/core.pb-c.h"
 
 #define SIGMAX			64
@@ -111,27 +112,42 @@ typedef struct {
 } user_regs_struct32;
 
 #ifdef CONFIG_X86_64
+/*
+ * To be sure that we rely on inited reg->__is_native, this member
+ * is (short int) instead of initial (bool). The right way to
+ * check if regs are native or compat is to use user_regs_native() macro.
+ * This should cost nothing, as *usually* sizeof(bool) == sizeof(short)
+ */
 typedef struct {
 	union {
 		user_regs_struct64 native;
 		user_regs_struct32 compat;
 	};
-	bool is_native;
+	short __is_native; /* use user_regs_native macro to check it */
 } user_regs_struct_t;
-#define get_user_reg(pregs, name) (((pregs)->is_native) ?	\
-		((pregs)->native.name) :			\
-		((pregs)->compat.name))
-#define set_user_reg(pregs, name, val) (((pregs)->is_native) ?	\
-		((pregs)->native.name = val) :			\
-		((pregs)->compat.name = val))
+
+#define NATIVE_MAGIC	0x0A
+#define COMPAT_MAGIC	0x0C
+static inline bool user_regs_native(user_regs_struct_t *pregs)
+{
+	BUG_ON(pregs->__is_native != NATIVE_MAGIC &&
+		pregs->__is_native != COMPAT_MAGIC);
+	return pregs->__is_native == NATIVE_MAGIC;
+}
+
+#define get_user_reg(pregs, name) ((user_regs_native(pregs)) ?		\
+		((pregs)->native.name) : ((pregs)->compat.name))
+#define set_user_reg(pregs, name, val) ((user_regs_native(pregs)) ?	\
+		((pregs)->native.name = (val)) : ((pregs)->compat.name = (val)))
 #else
 typedef struct {
 	union {
 		user_regs_struct32 native;
 	};
 } user_regs_struct_t;
-#define get_user_reg(pregs, name) ((pregs)->native.name)
-#define set_user_reg(pregs, name, val) ((pregs)->native.name = val)
+#define user_regs_native(pregs)		true
+#define get_user_reg(pregs, name)	((pregs)->native.name)
+#define set_user_reg(pregs, name, val)	((pregs)->native.name = val)
 #endif
 
 typedef struct {
-- 
2.8.0



More information about the CRIU mailing list