Exemple #1
0
int cr_exec(int pid, char **opt)
{
	char *sys_name = opt[0];
	struct syscall_exec_desc *si;
	struct parasite_ctl *ctl;
	struct vm_area_list vmas;
	int ret = -1, prev_state;
	struct proc_status_creds *creds;

	if (!sys_name) {
		pr_err("Syscall name required\n");
		goto out;
	}

	si = find_syscall(sys_name);
	if (!si) {
		pr_err("Unknown syscall [%s]\n", sys_name);
		goto out;
	}

	if (seize_catch_task(pid))
		goto out;

	prev_state = ret = seize_wait_task(pid, -1, &creds);
	if (ret < 0) {
		pr_err("Can't seize task %d\n", pid);
		goto out;
	}

	/*
	 * We don't seize a task's threads here, and there is no reason to
	 * compare threads' creds in this use case anyway, so let's just free
	 * the creds.
	 */
	free(creds);

	ret = collect_mappings(pid, &vmas, NULL);
	if (ret) {
		pr_err("Can't collect vmas for %d\n", pid);
		goto out_unseize;
	}

	ctl = parasite_prep_ctl(pid, &vmas);
	if (!ctl) {
		pr_err("Can't prep ctl %d\n", pid);
		goto out_unseize;
	}

	ret = execute_syscall(ctl, si, opt + 1);
	if (ret < 0)
		pr_err("Can't execute syscall remotely\n");

	parasite_cure_seized(ctl);
out_unseize:
	unseize_task(pid, prev_state, prev_state);
out:
	return ret;
}
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;
}