[CRIU] [PATCHv3 11/30] parasite: add parasite-compat.h & convert parasite.h types
Dmitry Safonov
dsafonov at virtuozzo.com
Tue Jun 28 12:24:04 PDT 2016
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 at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at 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
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);
--
2.9.0
More information about the CRIU
mailing list