Exemplo n.º 1
0
struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
		struct vm_area_list *vma_area_list, struct parasite_drain_fd *dfds)
{
	int ret;
	struct parasite_ctl *ctl;

	ctl = parasite_prep_ctl(pid, vma_area_list);
	if (!ctl)
		return NULL;

	/*
	 * Inject a parasite engine. Ie allocate memory inside alien
	 * space and copy engine code there. Then re-map the engine
	 * locally, so we will get an easy way to access engine memory
	 * without using ptrace at all.
	 */

	ctl->args_size = parasite_args_size(vma_area_list, dfds);
	ret = parasite_map_exchange(ctl, parasite_size + ctl->args_size);
	if (ret)
		goto err_restore;

	pr_info("Putting parasite blob into %p->%p\n", ctl->local_map, ctl->remote_map);
	memcpy(ctl->local_map, parasite_blob, sizeof(parasite_blob));

	/* Setup the rest of a control block */
	ctl->parasite_ip	= (unsigned long)parasite_sym(ctl->remote_map, __export_parasite_head_start);
	ctl->addr_cmd		= parasite_sym(ctl->local_map, __export_parasite_cmd);
	ctl->addr_args		= parasite_sym(ctl->local_map, __export_parasite_args);

	ret = parasite_init(ctl, pid, item->nr_threads);
	if (ret) {
		pr_err("%d: Can't create a transport socket\n", pid);
		goto err_restore;
	}

	ctl->signals_blocked = 1;

	ret = parasite_set_logfd(ctl, pid);
	if (ret) {
		pr_err("%d: Can't set a logging descriptor\n", pid);
		goto err_restore;
	}

	ret = parasite_init_threads_seized(ctl, item);
	if (ret)
		goto err_restore;

	return ctl;

err_restore:
	parasite_cure_seized(ctl, item);
	return NULL;
}
Exemplo n.º 2
0
static int execute_syscall(struct parasite_ctl *ctl,
		struct syscall_exec_desc *scd, char **opt)
{
	int i, err;
	unsigned long args[MAX_ARGS] = {}, ret, r_mem_size = 0;
	unsigned int ret_args[MAX_ARGS] = {};
	void *r_mem = NULL;

	for (i = 0; i < MAX_ARGS; i++) {
		if (opt[i] == NULL)
			break;

		/*
		 * &foo -- argument string "foo"
		 * @<size> -- ret-arg of size <size>
		 */

		if ((opt[i][0] == '&') || (opt[i][0] == '@')) {
			int len;

			if (!r_mem) {
				err = parasite_map_exchange(ctl, PAGE_SIZE);
				if (err)
					return err;

				r_mem_size = PAGE_SIZE;
				r_mem = ctl->local_map;
			}

			if (opt[i][0] == '&') {
				len = strlen(opt[i]);
				if (r_mem_size < len) {
					pr_err("Arg size overflow\n");
					return -1;
				}

				memcpy(r_mem, opt[i] + 1, len);
			} else {
				len = strtol(opt[i] + 1, NULL, 0);
				if (!len || (r_mem_size < len)) {
					pr_err("Bad argument size %d\n", len);
					return -1;
				}

				ret_args[i] = len;
			}

			args[i] = (unsigned long)ctl->remote_map + (r_mem - ctl->local_map);
			pr_info("Pushing %c mem arg [%s]\n", opt[i][0], (char *)r_mem);
			r_mem_size -= len;
			r_mem += len;
		} else
			args[i] = strtol(opt[i], NULL, 0);
	}

	pr_info("Calling %d with %lu %lu %lu %lu %lu %lu\n", scd->nr,
			args[0], args[1], args[2], args[3], args[4], args[5]);

	err = syscall_seized(ctl, scd->nr, &ret,
			args[0], args[1], args[2], args[3], args[4], args[5]);
	if (err)
		return err;

	pr_msg("Syscall returned %lx(%d)\n", ret, (int)ret);
	for (i = 0; i < MAX_ARGS; i++) {
		unsigned long addr;

		if (!ret_args[i])
			continue;

		pr_msg("Argument %d returns:\n", i);
		addr = (unsigned long)ctl->local_map + (args[i] - (unsigned long)ctl->remote_map);
		print_data(0, (unsigned char *)addr, ret_args[i]);
	}

	return 0;
}