Commit dd4d5aed authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by Andrei Vagin

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: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 16080b7f
parasite.h
parasite.po
spy
victim
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 $@ $^
#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;
}
#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;
}
#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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment