[PATCHv3,11/30] parasite: add parasite-compat.h & convert parasite.h types

Submitted by Dmitry Safonov on June 28, 2016, 7:24 p.m.

Details

Message ID 20160628192423.14943-12-dsafonov@virtuozzo.com
State Rejected
Series "x86 Compatible C/R, part 2"
Headers show

Commit Message

Dmitry Safonov June 28, 2016, 7:24 p.m.
We need serialization between parasite and criu process in
case of compatible dump. For x86_64 (unsigned long) is 8 bytes,
but for parasite inside compatibe 32-bit application it's 4 bytes.
I changed type declarations for several parasite_args to be
size-specific.

But in some parasite arguments there are standard libc types
which also may differ from native to compatible application
(like timers/timespecs/timevals, etc).
I didn't redefine those structures as size-specific, case it
would need to serialize syscall returns in pie. And pie
should do as lesser as possible in my POV.
So, the serialization work will be done in parasite-syscall,
that should properly check if task compatible and convert
returned structures.
This is done in the very next patch.

All casts added in C files are for gcc to convert from
i.e. u64 to (void*) type which it thinks is incompatible
pointer (and it's right but not this time).

Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
---
 criu/include/parasite-compat.h |  89 ++++++++++++++++++++++++++++++++++++
 criu/include/parasite.h        | 100 ++++++++++++++++++++++-------------------
 criu/parasite-syscall.c        |   4 +-
 criu/pie/parasite.c            |  16 ++++---
 4 files changed, 154 insertions(+), 55 deletions(-)
 create mode 100644 criu/include/parasite-compat.h

Patch hide | download patch | download mbox

diff --git a/criu/include/parasite-compat.h b/criu/include/parasite-compat.h
new file mode 100644
index 000000000000..a0629a950558
--- /dev/null
+++ b/criu/include/parasite-compat.h
@@ -0,0 +1,89 @@ 
+#ifndef __CR_PARASITE_COMPAT_H__
+#define __CR_PARASITE_COMPAT_H__
+
+/* XXX: define _compat types per-arch */
+
+#ifndef __ASSEMBLY__
+
+#include "images/core.pb-c.h"
+
+typedef struct {
+	u32	rt_sa_handler;
+	u32	rt_sa_flags;
+	u32	rt_sa_restorer;
+	k_rtsigset_t	rt_sa_mask;
+} rt_sigaction_t_compat;
+
+struct parasite_dump_sa_args_compat {
+	rt_sigaction_t_compat sas[SIGMAX];
+};
+
+struct parasite_timeval_compat {
+	u32	tv_sec;
+	u32	tv_usec;
+};
+
+struct parasite_itimerval_compat {
+	struct parasite_timeval_compat it_interval;
+	struct parasite_timeval_compat it_value;
+};
+
+struct parasite_dump_itimers_args_compat {
+	struct parasite_itimerval_compat real;
+	struct parasite_itimerval_compat virt;
+	struct parasite_itimerval_compat prof;
+};
+
+struct parasite_timespec_compat {
+	u32	tv_sec;
+	u32	tv_nsec;
+};
+
+struct parasite_itimerspec_compat {
+	struct parasite_timespec_compat it_interval;
+	struct parasite_timespec_compat it_value;
+};
+
+struct posix_timer_compat {
+	s32 it_id;
+	struct parasite_itimerspec_compat val;
+	s32 overrun;
+};
+
+struct parasite_dump_posix_timers_args_compat {
+	s32 timer_n;
+	struct posix_timer_compat timer[0];
+};
+
+static inline int posix_timers_compat_dump_size(int timer_n)
+{
+	return sizeof(s32) + sizeof(struct posix_timer_compat) * timer_n;
+}
+
+typedef struct {
+	u32	ss_sp;
+	s32	ss_flags;
+	u32	ss_size;
+} stack_t_compat;
+
+struct parasite_dump_thread_compat {
+	u32				tid_addr;
+	s32				tid;
+	tls_t				tls;
+	stack_t_compat			sas;
+	s32				pdeath_sig;
+	struct parasite_dump_creds	creds[0];
+};
+
+static inline void copy_sas_compat(ThreadSasEntry *dst,
+		const stack_t_compat *src)
+{
+	dst->ss_sp = encode_pointer((void*)(uintptr_t)src->ss_sp);
+	dst->ss_size = (u64)src->ss_size;
+	dst->ss_flags = src->ss_flags;
+}
+
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __CR_PARASITE_COMPAT_H__ */
diff --git a/criu/include/parasite.h b/criu/include/parasite.h
index dd58ef041e81..77688100e58a 100644
--- a/criu/include/parasite.h
+++ b/criu/include/parasite.h
@@ -21,6 +21,11 @@ 
 
 #define __head __used __section(.head.text)
 
+/*
+ * NOTE: each command's args should be arch-independed sized.
+ * If you want to use one of the standard types, declare
+ * alternative type for compatible tasks in parasite-compat.h
+ */
 enum {
 	PARASITE_CMD_IDLE		= 0,
 	PARASITE_CMD_ACK,
@@ -52,9 +57,9 @@  enum {
 };
 
 struct ctl_msg {
-	unsigned int	cmd;			/* command itself */
-	unsigned int	ack;			/* ack on command */
-	int		err;			/* error code on reply */
+	u32	cmd;			/* command itself */
+	u32	ack;			/* ack on command */
+	s32	err;			/* error code on reply */
 };
 
 #define ctl_msg_cmd(_cmd)		\
@@ -64,44 +69,44 @@  struct ctl_msg {
 	(struct ctl_msg){.cmd = _cmd, .ack = _cmd, .err = _err, }
 
 struct parasite_init_args {
-	int			h_addr_len;
-	struct sockaddr_un	h_addr;
+	s32				h_addr_len;
+	struct sockaddr_un		h_addr;
 
-	int			log_level;
+	s32				log_level;
 
-	struct rt_sigframe	*sigframe;
+	struct rt_sigframe		*sigframe;
 
-	void			*sigreturn_addr;
+	u64				sigreturn_addr;
 };
 
 struct parasite_unmap_args {
-	void			*parasite_start;
-	unsigned long		parasite_len;
+	u64		parasite_start;
+	u64		parasite_len;
 };
 
 struct parasite_vma_entry
 {
-	unsigned long	start;
-	unsigned long	len;
-	int		prot;
+	u64		start;
+	u64		len;
+	s32		prot;
 };
 
 struct parasite_vdso_vma_entry {
-	unsigned long	start;
-	unsigned long	len;
-	unsigned long	proxy_vdso_addr;
-	unsigned long	proxy_vvar_addr;
-	int		is_marked;
-	bool		try_fill_symtable;
-	bool		is_vdso;
+	u64	start;
+	u64	len;
+	u64	proxy_vdso_addr;
+	u64	proxy_vvar_addr;
+	s32		is_marked;
+	u8		try_fill_symtable;
+	u8		is_vdso;
 };
 
 struct parasite_dump_pages_args {
-	unsigned int	nr_vmas;
-	unsigned int	add_prot;
-	unsigned int	off;
-	unsigned int	nr_segs;
-	unsigned int	nr_pages;
+	u32	nr_vmas;
+	u32	add_prot;
+	u32	off;
+	u32	nr_segs;
+	u32	nr_pages;
 };
 
 static inline struct parasite_vma_entry *pargs_vmas(struct parasite_dump_pages_args *a)
@@ -136,12 +141,12 @@  struct parasite_dump_posix_timers_args {
 };
 
 struct parasite_aio {
-	unsigned long ctx;
-	unsigned int size;
+	u64 ctx;
+	u64 size;
 };
 
 struct parasite_check_aios_args {
-	unsigned nr_rings;
+	u32 nr_rings;
 	struct parasite_aio ring[0];
 };
 
@@ -156,14 +161,14 @@  static inline int posix_timers_dump_size(int timer_n)
  */
 
 struct parasite_dump_misc {
-	unsigned long		brk;
+	u64 brk;
 
 	u32 pid;
 	u32 sid;
 	u32 pgid;
 	u32 umask;
 
-	int dumpable;
+	s32 dumpable;
 };
 
 /*
@@ -175,17 +180,17 @@  struct parasite_dump_misc {
 	 offsetof(struct parasite_dump_creds, groups)) / sizeof(unsigned int)) /* groups */
 
 struct parasite_dump_creds {
-	unsigned int		cap_last_cap;
+	u32			cap_last_cap;
 
 	u32			cap_inh[CR_CAP_SIZE];
 	u32			cap_prm[CR_CAP_SIZE];
 	u32			cap_eff[CR_CAP_SIZE];
 	u32			cap_bnd[CR_CAP_SIZE];
 
-	int			uids[4];
-	int			gids[4];
-	unsigned int		secbits;
-	unsigned int		ngroups;
+	s32			uids[4];
+	s32			gids[4];
+	u32			secbits;
+	u32			ngroups;
 	/*
 	 * FIXME -- this structure is passed to parasite code
 	 * through parasite args area so in parasite_dump_creds()
@@ -199,7 +204,7 @@  struct parasite_dump_creds {
 	 * of memory in use doesn't exceed the PAGE_SIZE and the
 	 * args area is at least one page (PARASITE_ARG_SIZE_MIN).
 	 */
-	unsigned int		groups[0];
+	u32			groups[0];
 };
 
 struct parasite_dump_thread {
@@ -229,8 +234,8 @@  static inline void copy_sas(ThreadSasEntry *dst, const stack_t *src)
 #define PARASITE_MAX_FDS	CR_SCM_MAX_FD * 3
 
 struct parasite_drain_fd {
-	int	nr_fds;
-	int	fds[0];
+	s32	nr_fds;
+	s32	fds[0];
 };
 
 static inline int drain_fds_size(struct parasite_drain_fd *dfds)
@@ -243,16 +248,17 @@  static inline int drain_fds_size(struct parasite_drain_fd *dfds)
 }
 
 struct parasite_tty_args {
-	int	fd;
-	int	type;
+	s32	fd;
+	s32	type;
 
-	int	sid;
-	int	pgrp;
-	bool	hangup;
+	s32	sid;
+	s32	pgrp;
 
-	int	st_pckt;
-	int	st_lock;
-	int	st_excl;
+	s32	st_pckt;
+	s32	st_lock;
+	s32	st_excl;
+
+	u8	hangup;
 };
 
 struct parasite_dump_cgroup_args {
@@ -272,4 +278,6 @@  struct parasite_dump_cgroup_args {
 
 #endif /* !__ASSEMBLY__ */
 
+#include "parasite-compat.h"
+
 #endif /* __CR_PARASITE_H__ */
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index bce494433541..72550a331b6b 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -536,7 +536,7 @@  static int parasite_init_daemon(struct parasite_ctl *ctl, struct ns_id *net)
 		goto err;
 	}
 
-	ctl->sigreturn_addr = args->sigreturn_addr;
+	ctl->sigreturn_addr = (void*)(uintptr_t)args->sigreturn_addr;
 	ctl->daemonized = true;
 	pr_info("Parasite %d has been switched to daemon mode\n", pid);
 	return 0;
@@ -1086,7 +1086,7 @@  int parasite_cure_remote(struct parasite_ctl *ctl)
 		*ctl->addr_cmd = PARASITE_CMD_UNMAP;
 
 		args = parasite_args(ctl, struct parasite_unmap_args);
-		args->parasite_start = ctl->remote_map;
+		args->parasite_start = (uintptr_t)ctl->remote_map;
 		args->parasite_len = ctl->map_length;
 		if (parasite_unmap(ctl, ctl->parasite_ip))
 			ret = -1;
diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
index b1856ea0c0e7..96ea2c8bcdd7 100644
--- a/criu/pie/parasite.c
+++ b/criu/pie/parasite.c
@@ -50,10 +50,12 @@  static int mprotect_vmas(struct parasite_dump_pages_args *args)
 	vmas = pargs_vmas(args);
 	for (i = 0; i < args->nr_vmas; i++) {
 		vma = vmas + i;
-		ret = sys_mprotect((void *)vma->start, vma->len, vma->prot | args->add_prot);
+		ret = sys_mprotect((void *)(uintptr_t)vma->start, vma->len,
+				vma->prot | args->add_prot);
 		if (ret) {
 			pr_err("mprotect(%08lx, %lu) failed with code %d\n",
-						vma->start, vma->len, ret);
+					(unsigned long)vma->start,
+					(unsigned long)vma->len, ret);
 			break;
 		}
 	}
@@ -387,7 +389,7 @@  static inline int tty_ioctl(int fd, int cmd, int *arg)
 
 static int sane_ring(struct parasite_aio *aio)
 {
-	struct aio_ring *ring = (struct aio_ring *)aio->ctx;
+	struct aio_ring *ring = (struct aio_ring *)(uintptr_t)aio->ctx;
 	unsigned nr;
 
 	nr = (aio->size - sizeof(struct aio_ring)) / sizeof(struct io_event);
@@ -406,7 +408,7 @@  static int parasite_check_aios(struct parasite_check_aios_args *args)
 	for (i = 0; i < args->nr_rings; i++) {
 		struct aio_ring *ring;
 
-		ring = (struct aio_ring *)args->ring[i].ctx;
+		ring = (struct aio_ring *)(uintptr_t)args->ring[i].ctx;
 		if (!sane_ring(&args->ring[i])) {
 			pr_err("Not valid ring #%d\n", i);
 			pr_info(" `- magic %x\n", ring->magic);
@@ -485,7 +487,7 @@  err_io:
 #ifdef CONFIG_VDSO
 static int parasite_check_vdso_mark(struct parasite_vdso_vma_entry *args)
 {
-	struct vdso_mark *m = (void *)args->start;
+	struct vdso_mark *m = (void *)(uintptr_t)args->start;
 
 	if (is_vdso_mark(m)) {
 		/*
@@ -717,7 +719,7 @@  static noinline int unmap_itself(void *data)
 {
 	struct parasite_unmap_args *args = data;
 
-	sys_munmap(args->parasite_start, args->parasite_len);
+	sys_munmap((void*)(uintptr_t)args->parasite_start, args->parasite_len);
 	/*
 	 * This call to sys_munmap must never return. Instead, the controlling
 	 * process must trap us on the exit from munmap.
@@ -732,7 +734,7 @@  static noinline __used int parasite_init_daemon(void *data)
 	struct parasite_init_args *args = data;
 	int ret;
 
-	args->sigreturn_addr = fini_sigreturn;
+	args->sigreturn_addr = (u64)(uintptr_t)fini_sigreturn;
 	sigframe = args->sigframe;
 
 	tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0);