[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