2016-09-27 18:12:25 +03:00
|
|
|
#ifndef __COMPEL_INFECT_H__
|
|
|
|
#define __COMPEL_INFECT_H__
|
2016-09-28 13:55:21 +03:00
|
|
|
|
2016-10-31 15:06:48 +03:00
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
#include <compel/asm/sigframe.h>
|
|
|
|
#include <compel/asm/infect-types.h>
|
2016-10-27 19:01:21 +03:00
|
|
|
#include <compel/ksigset.h>
|
2017-02-08 06:36:12 -08:00
|
|
|
#include <compel/handle-elf.h>
|
Sanitize TASK_ values
First, TASK_* defines provided by compel should be prefixed
with COMPEL_. The complication is, same constants are also used
by CRIU, some are even writted into images (meaning we should
not change their values).
One way to solve this would be to untie compel values from CRIU ones,
using some mapping between the two sets when needed (i.e. in calls to
compel_wait_task() and compel_resume_task()).
Fortunately, we can avoid implementing this mapping by separating
the ranges used by compel and criu. With this patch, compel is using
values in range 0x01..0x7f, and criu is reusing those, plus adding
more values in range 0x80..0xff for its own purposes.
Note tha the values that are used inside images are not changed
(as, luckily, they were all used by compel).
travis-ci: success for compel uapi cleanups (rev2)
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-02-10 01:03:00 +03:00
|
|
|
#include <compel/task-state.h>
|
2016-09-28 13:55:21 +03:00
|
|
|
|
2016-10-31 15:06:48 +03:00
|
|
|
#include "common/compiler.h"
|
|
|
|
|
2016-10-27 11:22:42 +03:00
|
|
|
#define PARASITE_START_AREA_MIN (4096)
|
|
|
|
|
2016-11-21 21:26:19 +03:00
|
|
|
extern int compel_interrupt_task(int pid);
|
2016-09-27 20:16:07 +03:00
|
|
|
|
|
|
|
struct seize_task_status {
|
|
|
|
unsigned long long sigpnd;
|
|
|
|
unsigned long long shdpnd;
|
2017-05-03 15:48:14 +03:00
|
|
|
char state;
|
|
|
|
int ppid;
|
2016-09-27 20:16:07 +03:00
|
|
|
int seccomp_mode;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern int compel_wait_task(int pid, int ppid,
|
2017-05-03 15:48:25 +03:00
|
|
|
int (*get_status)(int pid, struct seize_task_status *, void *data),
|
|
|
|
void (*free_status)(int pid, struct seize_task_status *, void *data),
|
|
|
|
struct seize_task_status *st, void *data);
|
2016-11-25 16:20:31 +03:00
|
|
|
|
|
|
|
extern int compel_stop_task(int pid);
|
2016-11-25 16:20:45 +03:00
|
|
|
extern int compel_resume_task(pid_t pid, int orig_state, int state);
|
2016-09-27 20:16:07 +03:00
|
|
|
|
2016-09-28 11:29:01 +03:00
|
|
|
struct parasite_ctl;
|
2016-11-14 16:05:36 +03:00
|
|
|
struct parasite_thread_ctl;
|
2016-11-14 16:05:08 +03:00
|
|
|
|
2016-09-28 11:50:25 +03:00
|
|
|
extern struct parasite_ctl *compel_prepare(int pid);
|
2016-11-21 21:26:13 +03:00
|
|
|
extern struct parasite_ctl *compel_prepare_noctx(int pid);
|
2016-09-28 11:29:01 +03:00
|
|
|
extern int compel_infect(struct parasite_ctl *ctl, unsigned long nr_threads, unsigned long args_size);
|
2016-11-14 16:05:08 +03:00
|
|
|
extern struct parasite_thread_ctl *compel_prepare_thread(struct parasite_ctl *ctl, int pid);
|
|
|
|
extern void compel_release_thread(struct parasite_thread_ctl *);
|
2016-09-28 11:29:01 +03:00
|
|
|
|
2016-09-28 12:01:01 +03:00
|
|
|
extern int compel_stop_daemon(struct parasite_ctl *ctl);
|
|
|
|
extern int compel_cure_remote(struct parasite_ctl *ctl);
|
|
|
|
extern int compel_cure_local(struct parasite_ctl *ctl);
|
|
|
|
extern int compel_cure(struct parasite_ctl *ctl);
|
2016-09-28 12:12:09 +03:00
|
|
|
|
|
|
|
#define PARASITE_ARG_SIZE_MIN ( 1 << 12)
|
|
|
|
|
|
|
|
#define compel_parasite_args(ctl, type) \
|
|
|
|
({ \
|
|
|
|
void *___ret; \
|
|
|
|
BUILD_BUG_ON(sizeof(type) > PARASITE_ARG_SIZE_MIN); \
|
|
|
|
___ret = compel_parasite_args_p(ctl); \
|
|
|
|
___ret; \
|
|
|
|
})
|
|
|
|
|
|
|
|
extern void *compel_parasite_args_p(struct parasite_ctl *ctl);
|
|
|
|
extern void *compel_parasite_args_s(struct parasite_ctl *ctl, int args_size);
|
2016-09-28 13:55:21 +03:00
|
|
|
|
2016-12-17 03:21:56 -08:00
|
|
|
extern int compel_syscall(struct parasite_ctl *ctl, int nr, long *ret,
|
2016-11-25 16:45:31 +03:00
|
|
|
unsigned long arg1,
|
|
|
|
unsigned long arg2,
|
|
|
|
unsigned long arg3,
|
|
|
|
unsigned long arg4,
|
|
|
|
unsigned long arg5,
|
|
|
|
unsigned long arg6);
|
2016-11-14 16:05:49 +03:00
|
|
|
extern int compel_run_in_thread(struct parasite_thread_ctl *tctl, unsigned int cmd);
|
2016-12-06 00:15:00 +03:00
|
|
|
extern int compel_run_at(struct parasite_ctl *ctl, unsigned long ip, user_regs_struct_t *ret_regs);
|
2016-09-28 14:07:16 +03:00
|
|
|
|
2016-09-29 16:43:29 +03:00
|
|
|
/*
|
|
|
|
* The PTRACE_SYSCALL will trap task twice -- on
|
|
|
|
* enter into and on exit from syscall. If we trace
|
|
|
|
* a single task, we may skip half of all getregs
|
|
|
|
* calls -- on exit we don't need them.
|
|
|
|
*/
|
|
|
|
enum trace_flags {
|
|
|
|
TRACE_ALL,
|
|
|
|
TRACE_ENTER,
|
|
|
|
TRACE_EXIT,
|
|
|
|
};
|
|
|
|
|
|
|
|
extern int compel_stop_on_syscall(int tasks, int sys_nr,
|
|
|
|
int sys_nr_compat, enum trace_flags trace);
|
|
|
|
|
|
|
|
extern int compel_stop_pie(pid_t pid, void *addr, enum trace_flags *tf, bool no_bp);
|
|
|
|
|
2016-09-28 14:07:16 +03:00
|
|
|
extern int compel_unmap(struct parasite_ctl *ctl, unsigned long addr);
|
2016-09-30 14:56:28 +03:00
|
|
|
|
|
|
|
extern int compel_mode_native(struct parasite_ctl *ctl);
|
|
|
|
|
2016-09-30 14:58:29 +03:00
|
|
|
extern k_rtsigset_t *compel_task_sigmask(struct parasite_ctl *ctl);
|
2016-11-14 16:05:08 +03:00
|
|
|
extern k_rtsigset_t *compel_thread_sigmask(struct parasite_thread_ctl *tctl);
|
2016-09-30 14:58:29 +03:00
|
|
|
|
2016-09-30 14:53:49 +03:00
|
|
|
struct rt_sigframe;
|
|
|
|
|
2016-10-27 18:07:10 +03:00
|
|
|
typedef int (*open_proc_fn)(int pid, int mode, const char *fmt, ...)
|
|
|
|
__attribute__ ((__format__ (__printf__, 3, 4)));
|
2018-02-07 12:48:48 +00:00
|
|
|
typedef int (*save_regs_t)(void *, user_regs_struct_t *, user_fpregs_struct_t *);
|
|
|
|
typedef int (*make_sigframe_t)(void *, struct rt_sigframe *, struct rt_sigframe *, k_rtsigset_t *);
|
2016-10-27 18:07:10 +03:00
|
|
|
|
2016-09-30 14:53:49 +03:00
|
|
|
struct infect_ctx {
|
2016-11-18 04:23:00 +03:00
|
|
|
int sock;
|
2016-09-30 14:53:49 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Regs manipulation context.
|
|
|
|
*/
|
2018-02-07 12:48:48 +00:00
|
|
|
save_regs_t save_regs;
|
|
|
|
make_sigframe_t make_sigframe;
|
2016-09-30 14:53:49 +03:00
|
|
|
void *regs_arg;
|
|
|
|
|
2016-10-30 22:56:39 +03:00
|
|
|
unsigned long task_size;
|
2016-09-30 14:53:49 +03:00
|
|
|
unsigned long syscall_ip; /* entry point of infection */
|
|
|
|
unsigned long flags; /* fine-tune (e.g. faults) */
|
|
|
|
|
|
|
|
void (*child_handler)(int, siginfo_t *, void *); /* hander for SIGCHLD deaths */
|
2016-11-21 21:26:17 +03:00
|
|
|
struct sigaction orig_handler;
|
2016-10-27 18:07:10 +03:00
|
|
|
|
|
|
|
open_proc_fn open_proc;
|
2016-11-03 02:08:14 +03:00
|
|
|
|
|
|
|
int log_fd; /* fd for parasite code to send messages to */
|
2016-09-30 14:53:49 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
extern struct infect_ctx *compel_infect_ctx(struct parasite_ctl *);
|
|
|
|
|
2018-02-07 12:48:52 +00:00
|
|
|
/* Don't use memfd() */
|
|
|
|
#define INFECT_NO_MEMFD (1UL << 0)
|
|
|
|
/* Make parasite connect() fail */
|
|
|
|
#define INFECT_FAIL_CONNECT (1UL << 1)
|
|
|
|
/* No breakpoints in pie tracking */
|
|
|
|
#define INFECT_NO_BREAKPOINTS (1UL << 2)
|
|
|
|
/* Can run parasite inside compat tasks */
|
|
|
|
#define INFECT_COMPATIBLE (1UL << 3)
|
2018-02-07 12:48:51 +00:00
|
|
|
/* Workaround for ptrace bug on Skylake CPUs with kernels older than v4.14 */
|
2018-02-07 12:48:52 +00:00
|
|
|
#define INFECT_X86_PTRACE_MXCSR_BUG (1UL << 4)
|
2016-09-30 14:53:49 +03:00
|
|
|
|
2016-11-24 15:21:00 +03:00
|
|
|
/*
|
|
|
|
* There are several ways to describe a blob to compel
|
|
|
|
* library. The simplest one derived from criu is to
|
|
|
|
* provide it from .h files.
|
|
|
|
*/
|
|
|
|
#define COMPEL_BLOB_CHEADER 0x1
|
|
|
|
|
2016-11-04 00:30:00 +03:00
|
|
|
struct parasite_blob_desc {
|
2016-11-24 15:21:00 +03:00
|
|
|
unsigned parasite_type;
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
const void *mem;
|
2016-11-25 16:21:12 +03:00
|
|
|
size_t bsize;
|
|
|
|
size_t nr_gotpcrel;
|
2016-11-24 15:21:00 +03:00
|
|
|
unsigned long parasite_ip_off;
|
|
|
|
unsigned long addr_cmd_off;
|
|
|
|
unsigned long addr_arg_off;
|
|
|
|
compel_reloc_t *relocs;
|
|
|
|
unsigned int nr_relocs;
|
|
|
|
} hdr;
|
|
|
|
};
|
2016-11-04 00:30:00 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
extern struct parasite_blob_desc *compel_parasite_blob_desc(struct parasite_ctl *);
|
|
|
|
|
2016-11-14 16:05:49 +03:00
|
|
|
extern int compel_get_thread_regs(struct parasite_thread_ctl *, save_regs_t, void *);
|
2016-10-19 12:32:44 +03:00
|
|
|
|
2016-11-07 01:20:46 +03:00
|
|
|
extern void compel_relocs_apply(void *mem, void *vbase, size_t size, compel_reloc_t *elf_relocs, size_t nr_relocs);
|
|
|
|
|
2016-11-18 19:44:52 +03:00
|
|
|
extern unsigned long compel_task_size(void);
|
|
|
|
|
2016-09-27 18:12:25 +03:00
|
|
|
#endif
|