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;
}
Exemple #2
0
static void unseize_task_and_threads(const struct pstree_item *item, int st)
{
	int i;

	if (item->state == TASK_DEAD)
		return;

	/*
	 * The st is the state we want to switch tasks into,
	 * the item->state is the state task was in when we seized one.
	 */

	unseize_task(item->pid.real, item->state, st);

	if (st == TASK_DEAD)
		return;

	for (i = 1; i < item->nr_threads; i++)
		if (ptrace(PTRACE_DETACH, item->threads[i].real, NULL, NULL))
			pr_perror("Unable to detach from %d", item->threads[i].real);
}