mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
compel: Simple infection test
And, at the same time, an example of how to work with compel. Based on titanic preliminary work of Cyrill :) Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
committed by
Andrei Vagin
parent
16080b7f6f
commit
dd4d5aedda
4
compel/test/infect/.gitignore
vendored
Normal file
4
compel/test/infect/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
parasite.h
|
||||
parasite.po
|
||||
spy
|
||||
victim
|
41
compel/test/infect/Makefile
Normal file
41
compel/test/infect/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
ifeq ($(ARCH),)
|
||||
ARCH := x86
|
||||
endif
|
||||
|
||||
# FIXME -- generate common symlink in compel/uapi
|
||||
COMMON_IDIR := ../../../include
|
||||
COMPEL := ../../../compel/compel-host
|
||||
COMPEL_IDIR := ../../../compel/include/uapi
|
||||
COMPEL_PACK_LDS := ../../../compel/arch/$(ARCH)/scripts/compel-pack.lds.S
|
||||
COMPEL_PLUGINS := ../../../compel/plugins
|
||||
COMPEL_LIBRARY := ../../../compel/libcompel.a
|
||||
|
||||
all: victim spy
|
||||
|
||||
clean:
|
||||
rm -f victim
|
||||
rm -f spy
|
||||
rm -f parasite.h
|
||||
rm -f parasite.po
|
||||
rm -f parasite.o
|
||||
|
||||
victim: victim.c
|
||||
gcc -o $@ $^
|
||||
|
||||
spy: spy.c parasite.h $(COMPEL_LIBRARY)
|
||||
gcc -Werror -I$(COMPEL_IDIR) -I$(COMMON_IDIR) -o $@ $^
|
||||
|
||||
parasite.h: parasite.po
|
||||
$(COMPEL) hgen -f $^ -l 4 \
|
||||
-v parasite_relocs \
|
||||
-p parasite_sym \
|
||||
-s parasite_blob \
|
||||
-r parasite_nr_gotpcrel \
|
||||
-u $(COMPEL_IDIR) \
|
||||
-o $@
|
||||
|
||||
parasite.po: parasite.o $(COMPEL_PLUGINS)/std.built-in.o
|
||||
ld -r -T $(COMPEL_PACK_LDS) -o $@ $^
|
||||
|
||||
parasite.o: parasite.c
|
||||
gcc -c $(shell $(COMPEL) --arch=$(ARCH) cflags) -I$(COMPEL_IDIR) -o $@ $^
|
37
compel/test/infect/parasite.c
Normal file
37
compel/test/infect/parasite.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include <compel/plugins/std/syscall.h>
|
||||
#include <compel/plugins/std/string.h>
|
||||
#include <compel/plugins/std/log.h>
|
||||
|
||||
#include <compel/infect-rpc.h>
|
||||
|
||||
/*
|
||||
* Stubs for std compel plugin.
|
||||
*/
|
||||
int compel_main(void *arg_p, unsigned int arg_s) { return 0; }
|
||||
int parasite_trap_cmd(int cmd, void *args) { return 0; }
|
||||
void parasite_cleanup(void) { }
|
||||
|
||||
#define PARASITE_CMD_INC PARASITE_USER_CMDS
|
||||
#define PARASITE_CMD_DEC PARASITE_USER_CMDS + 1
|
||||
|
||||
int parasite_daemon_cmd(int cmd, void *args)
|
||||
{
|
||||
int v;
|
||||
|
||||
switch (cmd) {
|
||||
case PARASITE_CMD_INC:
|
||||
v = (*(int *)args) + 1;
|
||||
break;
|
||||
case PARASITE_CMD_DEC:
|
||||
v = (*(int *)args) - 1;
|
||||
break;
|
||||
default:
|
||||
v = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
sys_write(1, &v, sizeof(int));
|
||||
return 0;
|
||||
}
|
183
compel/test/infect/spy.c
Normal file
183
compel/test/infect/spy.c
Normal file
@@ -0,0 +1,183 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <compel/compel.h>
|
||||
#include "parasite.h"
|
||||
|
||||
#define PARASITE_CMD_INC PARASITE_USER_CMDS
|
||||
#define PARASITE_CMD_DEC PARASITE_USER_CMDS + 1
|
||||
|
||||
static void print_vmsg(unsigned int lvl, const char *fmt, va_list parms)
|
||||
{
|
||||
printf("\tLC%u: ", lvl);
|
||||
vprintf(fmt, parms);
|
||||
}
|
||||
|
||||
static int do_infection(int pid)
|
||||
{
|
||||
#define err_and_ret(msg) do { fprintf(stderr, msg); return -1; } while (0)
|
||||
|
||||
int state;
|
||||
struct parasite_ctl *ctl;
|
||||
struct infect_ctx *ictx;
|
||||
struct parasite_blob_desc *pbd;
|
||||
int *arg;
|
||||
|
||||
compel_log_init(print_vmsg, LOG_DEBUG);
|
||||
|
||||
printf("Stopping task\n");
|
||||
state = compel_stop_task(pid);
|
||||
if (state < 0)
|
||||
err_and_ret("Can't stop task");
|
||||
|
||||
printf("Preparing parasite ctl\n");
|
||||
ctl = compel_prepare(pid);
|
||||
if (!ctl)
|
||||
err_and_ret("Can't prepare for infection");
|
||||
|
||||
printf("Configuring contexts\n");
|
||||
|
||||
/*
|
||||
* First -- the infection context. Most of the stuff
|
||||
* is already filled by compel_prepare(), just set the
|
||||
* log descriptor for parasite side, library cannot
|
||||
* live w/o it.
|
||||
*/
|
||||
ictx = compel_infect_ctx(ctl);
|
||||
ictx->log_fd = STDERR_FILENO;
|
||||
|
||||
/*
|
||||
* Next the blob descriptor. We've requested for hgen
|
||||
* in Makefile, so prepare this type of blob with the
|
||||
* values from parasite.h.
|
||||
*/
|
||||
pbd = compel_parasite_blob_desc(ctl);
|
||||
pbd->parasite_type = COMPEL_BLOB_CHEADER;
|
||||
pbd->hdr.mem = parasite_blob;
|
||||
pbd->hdr.bsize = sizeof(parasite_blob);
|
||||
pbd->hdr.nr_gotpcrel = parasite_nr_gotpcrel;
|
||||
pbd->hdr.parasite_ip_off = COMPEL_H_PARASITE_HEAD(parasite_sym);
|
||||
pbd->hdr.addr_cmd_off = COMPEL_H_PARASITE_CMD(parasite_sym);
|
||||
pbd->hdr.addr_arg_off = COMPEL_H_PARASITE_ARGS(parasite_sym);
|
||||
pbd->hdr.relocs = parasite_relocs;
|
||||
pbd->hdr.nr_relocs = sizeof(parasite_relocs) / sizeof(parasite_relocs[0]);
|
||||
|
||||
printf("Infecting\n");
|
||||
if (compel_infect(ctl, 1, sizeof(int)))
|
||||
err_and_ret("Can't infect victim");
|
||||
|
||||
/*
|
||||
* Now get the area with arguments and run two
|
||||
* commands one by one.
|
||||
*/
|
||||
arg = compel_parasite_args(ctl, int);
|
||||
|
||||
printf("Running cmd 1\n");
|
||||
*arg = 137;
|
||||
if (compel_rpc_call_sync(PARASITE_CMD_INC, ctl))
|
||||
err_and_ret("Can't run parasite command 1");
|
||||
|
||||
printf("Running cmd 2\n");
|
||||
*arg = 404;
|
||||
if (compel_rpc_call_sync(PARASITE_CMD_DEC, ctl))
|
||||
err_and_ret("Can't run parasite command 2");
|
||||
|
||||
/*
|
||||
* Done. Cure and resume the task.
|
||||
*/
|
||||
printf("Curing\n");
|
||||
if (compel_cure(ctl))
|
||||
err_and_ret("Can't cure victim");
|
||||
|
||||
if (compel_resume_task(pid, state, state))
|
||||
err_and_ret("Can't unseize task");
|
||||
|
||||
printf("Done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int chk(int fd, int val)
|
||||
{
|
||||
int v = 0;
|
||||
|
||||
read(fd, &v, sizeof(v));
|
||||
printf("%d, want %d\n", v, val);
|
||||
return v == val;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int p_in[2], p_out[2], p_err[2], pid, i, pass = 1;
|
||||
|
||||
/*
|
||||
* Prepare IO-s and fork the victim binary
|
||||
*/
|
||||
if (pipe(p_in) || pipe(p_out) || pipe(p_err)) {
|
||||
perror("Can't make pipe");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pid = vfork();
|
||||
if (pid == 0) {
|
||||
close(p_in[1]); dup2(p_in[0], 0); close(p_in[0]);
|
||||
close(p_out[0]); dup2(p_out[1], 1); close(p_out[1]);
|
||||
close(p_err[0]); dup2(p_err[1], 2); close(p_err[1]);
|
||||
execl("./victim", "victim", NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(p_in[0]); close(p_out[1]); close(p_err[1]);
|
||||
|
||||
/*
|
||||
* Tell the little guy some numbers
|
||||
*/
|
||||
i = 1; write(p_in[1], &i, sizeof(i));
|
||||
i = 42; write(p_in[1], &i, sizeof(i));
|
||||
|
||||
printf("Checking the victim alive\n");
|
||||
pass = chk(p_out[0], 1);
|
||||
pass = chk(p_out[0], 42);
|
||||
if (!pass)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Now do the infection with parasite.c
|
||||
*/
|
||||
|
||||
printf("Infecting the victim\n");
|
||||
if (do_infection(pid))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Tell the victim some more stuff to check it's alive
|
||||
*/
|
||||
i = 1234; write(p_in[1], &i, sizeof(i));
|
||||
i = 4096; write(p_in[1], &i, sizeof(i));
|
||||
|
||||
/*
|
||||
* Stop the victim and check the infection went well
|
||||
*/
|
||||
printf("Closing victim stdin\n");
|
||||
close(p_in[1]);
|
||||
printf("Waiting for victim to die\n");
|
||||
wait(NULL);
|
||||
|
||||
printf("Checking the result\n");
|
||||
|
||||
/* These two came from parasite */
|
||||
pass = chk(p_out[0], 138);
|
||||
pass = chk(p_out[0], 403);
|
||||
|
||||
/* These two came from post-infect */
|
||||
pass = chk(p_out[0], 1234);
|
||||
pass = chk(p_out[0], 4096);
|
||||
|
||||
if (pass)
|
||||
printf("All OK\n");
|
||||
else
|
||||
printf("Something went WRONG\n");
|
||||
|
||||
return 0;
|
||||
}
|
15
compel/test/infect/victim.c
Normal file
15
compel/test/infect/victim.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (1) {
|
||||
if (read(0, &i, sizeof(i)) != sizeof(i))
|
||||
break;
|
||||
|
||||
write(1, &i, sizeof(i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user