[CRIU] [PATCH 3/3] compel: test -- Add example-1
Cyrill Gorcunov
gorcunov at openvz.org
Wed Nov 23 07:33:57 PST 2016
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
Makefile | 1 +
Makefile.compel | 16 +++++
compel/test/Makefile | 22 ++++++
compel/test/example-1/Makefile | 61 ++++++++++++++++
compel/test/example-1/donor.c | 56 +++++++++++++++
compel/test/example-1/log.c | 44 ++++++++++++
compel/test/example-1/log.h | 45 ++++++++++++
compel/test/example-1/modifier-pie.c | 34 +++++++++
compel/test/example-1/modifier.c | 136 +++++++++++++++++++++++++++++++++++
9 files changed, 415 insertions(+)
create mode 100644 compel/test/Makefile
create mode 100644 compel/test/example-1/Makefile
create mode 100644 compel/test/example-1/donor.c
create mode 100644 compel/test/example-1/log.c
create mode 100644 compel/test/example-1/log.h
create mode 100644 compel/test/example-1/modifier-pie.c
create mode 100644 compel/test/example-1/modifier.c
diff --git a/Makefile b/Makefile
index 6a7cbc279b2f..cc5c388ef429 100644
--- a/Makefile
+++ b/Makefile
@@ -257,6 +257,7 @@ clean: subclean
$(Q) $(MAKE) $(build)=criu $@
$(Q) $(MAKE) $(build)=compel $@
$(Q) $(MAKE) $(build)=compel/plugins $@
+ $(Q) $(MAKE) $(build)=compel/test clean-examples
$(Q) $(MAKE) $(build)=soccr $@
.PHONY: clean
diff --git a/Makefile.compel b/Makefile.compel
index 42d05bc412f0..a7371fbc215d 100644
--- a/Makefile.compel
+++ b/Makefile.compel
@@ -69,3 +69,19 @@ LIBCOMPEL_SO_CFLAGS += $(CFLAGS) -rdynamic -Wl,-soname,$(LIBCOMPEL_SO).$(COMPEL_
compel/$(LIBCOMPEL_SO): compel/libcompel.a
$(call msg-link, $@)
$(Q) $(CC) -shared $(LIBCOMPEL_SO_CFLAGS) -o $@ -Wl,--whole-archive $^ -Wl,--no-whole-archive $(LDFLAGS)
+
+compel-install-targets += compel/$(LIBCOMPEL_SO)
+compel-install-targets += compel/compel
+compel-install-targets += compel/plugins/std.built-in.o
+compel-install-targets += compel/plugins/fds.built-in.o
+
+#
+# Tests
+compel/test/%: $(compel-install-targets) compel/libcompel.a compel/compel-host
+ $(Q) $(MAKE) $(build)=compel/test $@
+compel/test: $(compel-install-targets) compel/libcompel.a compel/compel-host
+ $(Q) $(MAKE) $(build)=compel/test all
+.PHONY: compel/test
+compel/test-run: compel/test
+ $(Q) $(MAKE) $(build)=compel/test test-run
+.PHONY: compel/test-run
diff --git a/compel/test/Makefile b/compel/test/Makefile
new file mode 100644
index 000000000000..6d7c74336438
--- /dev/null
+++ b/compel/test/Makefile
@@ -0,0 +1,22 @@
+compel_host := compel/compel-host
+export compel_host
+
+compel/test/example-1/%:
+ $(Q) $(MAKE) $(build)=compel/test/example-1 $@
+compel/test/example-1:
+ $(Q) $(MAKE) $(build)=compel/test/example-1 all
+.PHONY: compel/test/example-1
+all-y += compel/test/example-1
+
+test-run-example-1: compel/test/example-1
+ $(E) " RUN " $@
+ $(Q) $(MAKE) $(build)=compel/test/example-1 run
+.PHONY: test-run-example-1
+
+test-run: test-run-example-1
+ @true
+.PHONY: test-run
+
+clean-examples:
+ $(Q) $(MAKE) $(build)=compel/test/example-1 clean
+.PHONY: clean-examples
diff --git a/compel/test/example-1/Makefile b/compel/test/example-1/Makefile
new file mode 100644
index 000000000000..909c47c09d6a
--- /dev/null
+++ b/compel/test/example-1/Makefile
@@ -0,0 +1,61 @@
+ccflags-y += -I compel/include/uapi
+ccflags-y += -I compel/plugins/include/uapi
+ccflags-y += -iquote include
+
+compel_pack_lds-native := compel/arch/$(ARCH)/scripts/compel-pack.lds.S
+
+target += donor modifier modifierpie
+
+donor-obj-y += donor.o
+donor-obj-e += log.o
+
+modifier-obj-y += modifier.o
+modifier-obj-y += log.o
+
+ifneq ($(filter-out clean mrproper,$(MAKECMDGOALS)),)
+modifierpie-flags := $(shell $(compel_host) --arch=$(ARCH) cflags)
+endif
+modifierpie-obj-y += modifier-pie.o
+modifierpie-obj-e += ./compel/plugins/std.built-in.o
+modifierpie-obj-e += ./compel/plugins/fds.built-in.o
+
+CFLAGS_modifier-pie.o := $(modifierpie-flags) $(ccflags-y)
+
+$(obj)/donor.built-in.o: $(obj)/log.o
+
+$(obj)/modifierpie.built-in.bin.o: $(obj)/modifierpie.built-in.o $(modifierpie-obj-e)
+ $(call msg-gen, $@)
+ $(Q) $(LD) -r -T $(compel_pack_lds-native) -o $@ $<
+
+$(obj)/modifierpie-blob.h: $(obj)/modifierpie.built-in.bin.o $(compel_host)
+ $(call msg-gen, $@)
+ $(Q) $(compel_host) piegen -f $< \
+ -l 4 \
+ -v modifier_relocs \
+ -p modifier_blob_offset__ \
+ -s modifier_blob \
+ -r modifier_nr_gotpcrel \
+ -u $(SRC_DIR)/compel/include/uapi \
+ -o $@
+
+$(obj)/modifier.d: $(obj)/modifierpie-blob.h
+$(obj)/modifier.i: $(obj)/modifierpie-blob.h
+$(obj)/modifier.o: $(obj)/modifierpie-blob.h
+
+$(obj)/donor: $(obj)/donor.built-in.o
+ $(call msg-link,$@)
+ $(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
+
+$(obj)/modifier: $(obj)/modifier.built-in.o compel/libcompel.a
+ $(call msg-link,$@)
+ $(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
+
+all-y += $(obj)/donor $(obj)/modifier
+cleanup-y += $(obj)/donor $(obj)/modifier
+cleanup-y += $(obj)/modifierpie-blob.h
+cleanup-y += $(obj)/modifierpie.built-in.bin.o
+cleanup-y += $(obj)/pie.txt
+
+run: $(obj)/donor $(obj)/modifier
+ $(obj)/run.sh $(obj)/donor $(obj)/modifier $(obj)/pie.txt 2
+.PHONY: run
diff --git a/compel/test/example-1/donor.c b/compel/test/example-1/donor.c
new file mode 100644
index 000000000000..f4bb022d0333
--- /dev/null
+++ b/compel/test/example-1/donor.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+static int variable = 1;
+
+/* argv[1] -- info path, argv[2] -- new value */
+int main(int argc, char *argv[])
+{
+ int expected = 0, nr_waits = 20;
+ char info[128];
+ int i, fd, size;
+
+ if (argc < 3) {
+ printf("FAIL: Not enough params passed\n");
+ exit(1);
+ }
+
+ expected = atoi(argv[2]);
+
+ printf("INFO: donor %d variable %p value %d => %d\n",
+ getpid(), &variable, variable, expected);
+
+ fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0) {
+ printf("FAIL: Can't open %s: %m\n", argv[1]);
+ exit(1);
+ }
+
+ snprintf(info, sizeof(info), "%d %p\n", getpid(), &variable);
+ size = strlen(info);
+ if (write(fd, info, size) != size) {
+ printf("FAIL: Incomplete write of data\n");
+ exit(1);
+ }
+ close(fd);
+
+ for (i = 0; i < nr_waits; i++) {
+ printf("INFO: %d: %s (got %d expected %d nr %d/%d)\n",
+ getpid(),
+ expected == variable ? "Match" : "Mismatch",
+ variable, expected, i, nr_waits);
+ if (expected == variable) {
+ printf("PASS: %d\n", getpid());
+ exit(0);
+ }
+ sleep(1);
+ }
+
+ printf("FAIL: %d\n", getpid());
+ return 1;
+}
diff --git a/compel/test/example-1/log.c b/compel/test/example-1/log.c
new file mode 100644
index 000000000000..a3493a94d777
--- /dev/null
+++ b/compel/test/example-1/log.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "log.h"
+
+static unsigned int current_loglevel = LOG_DEBUG;
+
+unsigned int log_get_loglevel(void)
+{
+ return current_loglevel;
+}
+
+void __print_on_level(unsigned int loglevel, const char *format, va_list params)
+{
+ int size, ret, off = 0;
+ int __errno = errno;
+ char buffer[1024];
+
+ if (loglevel != LOG_MSG && loglevel > current_loglevel)
+ return;
+
+ size = vsnprintf(buffer, sizeof(buffer), format, params);
+
+ while (off < size) {
+ ret = write(STDOUT_FILENO, buffer + off, size - off);
+ if (ret <= 0)
+ break;
+ off += ret;
+ }
+ errno = __errno;
+}
+
+void print_on_level(unsigned int loglevel, const char *format, ...)
+{
+ va_list params;
+
+ va_start(params, format);
+ __print_on_level(loglevel, format, params);
+ va_end(params);
+}
diff --git a/compel/test/example-1/log.h b/compel/test/example-1/log.h
new file mode 100644
index 000000000000..8b7f90094ed8
--- /dev/null
+++ b/compel/test/example-1/log.h
@@ -0,0 +1,45 @@
+#ifndef EXAMPLE_1_LOG_H__
+#define EXAMPLE_1_LOG_H__
+
+#include <compel/loglevels.h>
+
+extern unsigned int log_get_loglevel(void);
+extern void __print_on_level(unsigned int loglevel, const char *format, va_list params);
+extern void print_on_level(unsigned int loglevel, const char *format, ...);
+
+#ifndef LOG_PREFIX
+# define LOG_PREFIX
+#endif
+
+#define pr_msg(fmt, ...) \
+ print_on_level(LOG_MSG, \
+ fmt, ##__VA_ARGS__)
+
+#define pr_info(fmt, ...) \
+ print_on_level(LOG_INFO, \
+ LOG_PREFIX fmt, ##__VA_ARGS__)
+
+#define pr_err(fmt, ...) \
+ print_on_level(LOG_ERROR, \
+ "Error (%s:%d): " LOG_PREFIX fmt, \
+ __FILE__, __LINE__, ##__VA_ARGS__)
+
+#define pr_err_once(fmt, ...) \
+ print_once(LOG_ERROR, fmt, ##__VA_ARGS__)
+
+#define pr_warn(fmt, ...) \
+ print_on_level(LOG_WARN, \
+ "Warn (%s:%d): " LOG_PREFIX fmt, \
+ __FILE__, __LINE__, ##__VA_ARGS__)
+
+#define pr_warn_once(fmt, ...) \
+ print_once(LOG_WARN, fmt, ##__VA_ARGS__)
+
+#define pr_debug(fmt, ...) \
+ print_on_level(LOG_DEBUG, \
+ LOG_PREFIX fmt, ##__VA_ARGS__)
+
+#define pr_perror(fmt, ...) \
+ pr_err(fmt ": %s\n", ##__VA_ARGS__, strerror(errno))
+
+#endif /* EXAMPLE_1_LOG_H__ */
diff --git a/compel/test/example-1/modifier-pie.c b/compel/test/example-1/modifier-pie.c
new file mode 100644
index 000000000000..4a3b5826c40e
--- /dev/null
+++ b/compel/test/example-1/modifier-pie.c
@@ -0,0 +1,34 @@
+#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>
+
+/*
+ * These are 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_MODIFY PARASITE_USER_CMDS
+
+typedef struct {
+ int *pvar;
+ int val;
+} parasite_mod_t;
+
+int parasite_daemon_cmd(int cmd, void *args)
+{
+ std_printf("INFO: modifier-pie: parasite_daemon_cmd %d\n", cmd);
+
+ if (cmd == PARASITE_CMD_MODIFY) {
+ parasite_mod_t *p = args;
+ *p->pvar = p->val;
+ return 0;
+ }
+
+ return -EINVAL;
+}
diff --git a/compel/test/example-1/modifier.c b/compel/test/example-1/modifier.c
new file mode 100644
index 000000000000..354b8801e8b4
--- /dev/null
+++ b/compel/test/example-1/modifier.c
@@ -0,0 +1,136 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <compel/compel.h>
+
+#include "log.h"
+#include "common/list.h"
+#include "common/page.h"
+
+#include "modifierpie-blob.h"
+
+#define CONFIG_PIEGEN
+#define pie_size(__pie_name) (round_up(sizeof(__pie_name##_blob) + \
+ __pie_name ## _nr_gotpcrel * sizeof(long), page_size()))
+
+extern int compel_stop_task(pid_t pid);
+
+#define PARASITE_CMD_MODIFY PARASITE_USER_CMDS
+
+typedef struct {
+ int *pvar;
+ int val;
+} parasite_mod_t;
+
+/* argv[1] -- info path, argv[2] -- new value */
+int main(int argc, char *argv[])
+{
+ struct parasite_blob_desc *pbd;
+ struct parasite_ctl *ctl;
+ struct infect_ctx *ictx;
+ parasite_mod_t *mod;
+ char line[128];
+ FILE *f;
+ int i;
+
+ pid_t donor_pid;
+ int *variable;
+
+ if (argc < 2) {
+ pr_err("FAIL: Two args required\n");
+ exit(1);
+ }
+
+ compel_log_init(__print_on_level, 4);
+
+ for (i = 0; i < 10; i++) {
+ if (access(argv[1], R_OK)) {
+ sleep(3);
+ continue;
+ }
+ sleep(1);
+ break;
+ }
+
+ if (i >= 10) {
+ pr_err("FAIL: Can't access %s\n", argv[1]);
+ exit(1);
+ }
+
+ f = fopen(argv[1], "r");
+ if (!f) {
+ pr_perror("FAIL: Can't open %s", argv[1]);
+ exit(1);
+ }
+
+ if (!fgets(line, sizeof(line), f)) {
+ pr_err("FAIL: Can't read data from %s\n", argv[1]);
+ exit(1);
+ }
+ fclose(f);
+
+ if (sscanf(line, "%d %p", &donor_pid, &variable) != 2) {
+ pr_err("FAIL: Can't parse data from %s\n", argv[1]);
+ exit(1);
+ }
+
+ if (compel_stop_task(donor_pid) < 0) {
+ pr_err("FAIL: Can't stop task %d\n", donor_pid);
+ exit(1);
+ }
+
+ ctl = compel_prepare(donor_pid);
+ if (!ctl) {
+ pr_err("FAIL: Can't prepare compel for %d\n", donor_pid);
+ exit(1);
+ }
+
+ ictx = compel_infect_ctx(ctl);
+ ictx->log_fd = STDOUT_FILENO;
+
+ pbd = compel_parasite_blob_desc(ctl);
+ pbd->mem = modifier_blob;
+ pbd->bsize = sizeof(modifier_blob);
+ pbd->size = pie_size(modifier);
+ pbd->parasite_ip_off = modifier_blob_offset____export_parasite_head_start;
+ pbd->addr_cmd_off = modifier_blob_offset____export_parasite_cmd;
+ pbd->addr_arg_off = modifier_blob_offset____export_parasite_args;
+ pbd->relocs = modifier_relocs;
+ pbd->nr_relocs = sizeof(modifier_relocs) / sizeof(modifier_relocs[0]);
+
+ if (compel_infect(ctl, 1, 16 << 10) < 0) {
+ pr_err("FAIL: Can't infect %d\n", donor_pid);
+ if (compel_cure(ctl))
+ pr_err("FAIL: Can't cure %d\n", donor_pid);
+ exit(1);
+ }
+
+ mod = compel_parasite_args(ctl, parasite_mod_t);
+ mod->pvar = (int *)(unsigned long)variable;
+ mod->val = atoi(argv[2]);
+
+ if (compel_rpc_call_sync(PARASITE_CMD_MODIFY, ctl)) {
+ pr_err("FAIL: Parasite cmd %d for %d failer\n",
+ PARASITE_CMD_MODIFY, donor_pid);
+ if (compel_cure(ctl))
+ pr_err("FAIL: Can't cure %d\n", donor_pid);
+ exit(1);
+ }
+
+ if (compel_stop_daemon(ctl)) {
+ pr_err("FAIL: Can't stop daemon for %d\n", donor_pid);
+ if (compel_cure(ctl))
+ pr_err("FAIL: Can't cure %d\n", donor_pid);
+ exit(1);
+ }
+
+ if (compel_cure(ctl)) {
+ pr_err("FAIL: Can't cure %d\n", donor_pid);
+ exit(1);
+ }
+
+ return 0;
+}
--
2.7.4
More information about the CRIU
mailing list