Beispiel #1
0
long arch_ptrace(struct task_struct *child, long request,
		 unsigned long addr, unsigned long data)
{
	int i, ret;
	unsigned long __user *p = (void __user *)data;
	void __user *vp = p;

	switch (request) {
	/* read word at location addr. */
	case PTRACE_PEEKTEXT:
	case PTRACE_PEEKDATA:
		ret = generic_ptrace_peekdata(child, addr, data);
		break;

	/* read the word at location addr in the USER area. */
	case PTRACE_PEEKUSR:
		ret = peek_user(child, addr, data);
		break;

	/* write the word at location addr. */
	case PTRACE_POKETEXT:
	case PTRACE_POKEDATA:
		ret = generic_ptrace_pokedata(child, addr, data);
		break;

	/* write the word at location addr in the USER area */
	case PTRACE_POKEUSR:
		ret = poke_user(child, addr, data);
		break;

	case PTRACE_SYSEMU:
	case PTRACE_SYSEMU_SINGLESTEP:
		ret = -EIO;
		break;

#ifdef PTRACE_GETREGS
	case PTRACE_GETREGS: { /* Get all gp regs from the child. */
		if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) {
			ret = -EIO;
			break;
		}
		for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
			__put_user(getreg(child, i), p);
			p++;
		}
		ret = 0;
		break;
	}
#endif
#ifdef PTRACE_SETREGS
	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
		unsigned long tmp = 0;
		if (!access_ok(VERIFY_READ, p, MAX_REG_OFFSET)) {
			ret = -EIO;
			break;
		}
		for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
			__get_user(tmp, p);
			putreg(child, i, tmp);
			p++;
		}
		ret = 0;
		break;
	}
#endif
#ifdef PTRACE_GETFPREGS
	case PTRACE_GETFPREGS: /* Get the child FPU state. */
		ret = get_fpregs(vp, child);
		break;
#endif
#ifdef PTRACE_SETFPREGS
	case PTRACE_SETFPREGS: /* Set the child FPU state. */
		ret = set_fpregs(vp, child);
		break;
#endif
	case PTRACE_GET_THREAD_AREA:
		ret = ptrace_get_thread_area(child, addr, vp);
		break;

	case PTRACE_SET_THREAD_AREA:
		ret = ptrace_set_thread_area(child, addr, vp);
		break;

	case PTRACE_FAULTINFO: {
		/*
		 * Take the info from thread->arch->faultinfo,
		 * but transfer max. sizeof(struct ptrace_faultinfo).
		 * On i386, ptrace_faultinfo is smaller!
		 */
		ret = copy_to_user(p, &child->thread.arch.faultinfo,
				   sizeof(struct ptrace_faultinfo)) ?
			-EIO : 0;
		break;
	}

#ifdef PTRACE_LDT
	case PTRACE_LDT: {
		struct ptrace_ldt ldt;

		if (copy_from_user(&ldt, p, sizeof(ldt))) {
			ret = -EIO;
			break;
		}

		/*
		 * This one is confusing, so just punt and return -EIO for
		 * now
		 */
		ret = -EIO;
		break;
	}
#endif
#ifdef PTRACE_ARCH_PRCTL
	case PTRACE_ARCH_PRCTL:
		/* XXX Calls ptrace on the host - needs some SMP thinking */
		ret = arch_prctl(child, data, (void __user *) addr);
		break;
#endif
	default:
		ret = ptrace_request(child, request, addr, data);
		if (ret == -EIO)
			ret = subarch_ptrace(child, request, addr, data);
		break;
	}

	return ret;
}
Beispiel #2
0
long arch_ptrace(struct task_struct *child, long request,
		 unsigned long addr, unsigned long data)
{
	int i, ret;
	unsigned long __user *p = (void __user *)data;
	void __user *vp = p;

	switch (request) {
	/* read the word at location addr in the USER area. */
	case PTRACE_PEEKUSR:
		ret = peek_user(child, addr, data);
		break;

	/* write the word at location addr in the USER area */
	case PTRACE_POKEUSR:
		ret = poke_user(child, addr, data);
		break;

	case PTRACE_SYSEMU:
	case PTRACE_SYSEMU_SINGLESTEP:
		ret = -EIO;
		break;

#ifdef PTRACE_GETREGS
	case PTRACE_GETREGS: { /* Get all gp regs from the child. */
		if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) {
			ret = -EIO;
			break;
		}
		for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
			__put_user(getreg(child, i), p);
			p++;
		}
		ret = 0;
		break;
	}
#endif
#ifdef PTRACE_SETREGS
	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
		unsigned long tmp = 0;
		if (!access_ok(VERIFY_READ, p, MAX_REG_OFFSET)) {
			ret = -EIO;
			break;
		}
		for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
			__get_user(tmp, p);
			putreg(child, i, tmp);
			p++;
		}
		ret = 0;
		break;
	}
#endif
	case PTRACE_GET_THREAD_AREA:
		ret = ptrace_get_thread_area(child, addr, vp);
		break;

	case PTRACE_SET_THREAD_AREA:
		ret = ptrace_set_thread_area(child, addr, vp);
		break;

	default:
		ret = ptrace_request(child, request, addr, data);
		if (ret == -EIO)
			ret = subarch_ptrace(child, request, addr, data);
		break;
	}

	return ret;
}
Beispiel #3
0
long sys_ptrace(long request, long pid, long addr, long data)
{
    struct task_struct *child;
    int i, ret;

    lock_kernel();
    ret = -EPERM;
    if (request == PTRACE_TRACEME) {
        /* are we already being traced? */
        if (current->ptrace & PT_PTRACED)
            goto out;

        ret = security_ptrace(current->parent, current);
        if (ret)
            goto out;

        /* set the ptrace bit in the process flags. */
        current->ptrace |= PT_PTRACED;
        ret = 0;
        goto out;
    }
    ret = -ESRCH;
    read_lock(&tasklist_lock);
    child = find_task_by_pid(pid);
    if (child)
        get_task_struct(child);
    read_unlock(&tasklist_lock);
    if (!child)
        goto out;

    ret = -EPERM;
    if (pid == 1)		/* you may not mess with init */
        goto out_tsk;

    if (request == PTRACE_ATTACH) {
        ret = ptrace_attach(child);
        goto out_tsk;
    }

#ifdef SUBACH_PTRACE_SPECIAL
    SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
#endif

    ret = ptrace_check_attach(child, request == PTRACE_KILL);
    if (ret < 0)
        goto out_tsk;

    switch (request) {
    /* when I and D space are separate, these will need to be fixed. */
    case PTRACE_PEEKTEXT: /* read word at location addr. */
    case PTRACE_PEEKDATA: {
        unsigned long tmp;
        int copied;

        ret = -EIO;
        copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
        if (copied != sizeof(tmp))
            break;
        ret = put_user(tmp, (unsigned long __user *) data);
        break;
    }

    /* read the word at location addr in the USER area. */
    case PTRACE_PEEKUSR:
        ret = peek_user(child, addr, data);
        break;

    /* when I and D space are separate, this will have to be fixed. */
    case PTRACE_POKETEXT: /* write the word at location addr. */
    case PTRACE_POKEDATA:
        ret = -EIO;
        if (access_process_vm(child, addr, &data, sizeof(data),
                              1) != sizeof(data))
            break;
        ret = 0;
        break;

    case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
        ret = poke_user(child, addr, data);
        break;

    case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
    case PTRACE_CONT: { /* restart after signal. */
        ret = -EIO;
        if (!valid_signal(data))
            break;

        set_singlestepping(child, 0);
        if (request == PTRACE_SYSCALL) {
            set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
        }
        else {
            clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
        }
        child->exit_code = data;
        wake_up_process(child);
        ret = 0;
        break;
    }

    /*
     * make the child exit.  Best I can do is send it a sigkill.
     * perhaps it should be put in the status that it wants to
     * exit.
     */
    case PTRACE_KILL: {
        ret = 0;
        if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
            break;

        set_singlestepping(child, 0);
        child->exit_code = SIGKILL;
        wake_up_process(child);
        break;
    }

    case PTRACE_SINGLESTEP: {  /* set the trap flag. */
        ret = -EIO;
        if (!valid_signal(data))
            break;
        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
        set_singlestepping(child, 1);
        child->exit_code = data;
        /* give it a chance to run. */
        wake_up_process(child);
        ret = 0;
        break;
    }

    case PTRACE_DETACH:
        /* detach a process that was attached. */
        ret = ptrace_detach(child, data);
        break;

#ifdef PTRACE_GETREGS
    case PTRACE_GETREGS: { /* Get all gp regs from the child. */
        if (!access_ok(VERIFY_WRITE, (unsigned long *)data,
                       MAX_REG_OFFSET)) {
            ret = -EIO;
            break;
        }
        for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
            __put_user(getreg(child, i),
                       (unsigned long __user *) data);
            data += sizeof(long);
        }
        ret = 0;
        break;
    }
#endif
#ifdef PTRACE_SETREGS
    case PTRACE_SETREGS: { /* Set all gp regs in the child. */
        unsigned long tmp = 0;
        if (!access_ok(VERIFY_READ, (unsigned *)data,
                       MAX_REG_OFFSET)) {
            ret = -EIO;
            break;
        }
        for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
            __get_user(tmp, (unsigned long __user *) data);
            putreg(child, i, tmp);
            data += sizeof(long);
        }
        ret = 0;
        break;
    }
#endif
#ifdef PTRACE_GETFPREGS
    case PTRACE_GETFPREGS: /* Get the child FPU state. */
        ret = get_fpregs(data, child);
        break;
#endif
#ifdef PTRACE_SETFPREGS
    case PTRACE_SETFPREGS: /* Set the child FPU state. */
        ret = set_fpregs(data, child);
        break;
#endif
#ifdef PTRACE_GETFPXREGS
    case PTRACE_GETFPXREGS: /* Get the child FPU state. */
        ret = get_fpxregs(data, child);
        break;
#endif
#ifdef PTRACE_SETFPXREGS
    case PTRACE_SETFPXREGS: /* Set the child FPU state. */
        ret = set_fpxregs(data, child);
        break;
#endif
    case PTRACE_FAULTINFO: {
        /* Take the info from thread->arch->faultinfo,
         * but transfer max. sizeof(struct ptrace_faultinfo).
         * On i386, ptrace_faultinfo is smaller!
         */
        ret = copy_to_user((unsigned long __user *) data,
                           &child->thread.arch.faultinfo,
                           sizeof(struct ptrace_faultinfo));
        if(ret)
            break;
        break;
    }

#ifdef PTRACE_LDT
    case PTRACE_LDT: {
        struct ptrace_ldt ldt;

        if(copy_from_user(&ldt, (unsigned long __user *) data,
                          sizeof(ldt))) {
            ret = -EIO;
            break;
        }

        /* This one is confusing, so just punt and return -EIO for
         * now
         */
        ret = -EIO;
        break;
    }
#endif
#ifdef CONFIG_PROC_MM
    case PTRACE_SWITCH_MM: {
        struct mm_struct *old = child->mm;
        struct mm_struct *new = proc_mm_get_mm(data);

        if(IS_ERR(new)) {
            ret = PTR_ERR(new);
            break;
        }

        atomic_inc(&new->mm_users);
        child->mm = new;
        child->active_mm = new;
        mmput(old);
        ret = 0;
        break;
    }
#endif
    default:
        ret = ptrace_request(child, request, addr, data);
        break;
    }
out_tsk:
    put_task_struct(child);
out:
    unlock_kernel();
    return ret;
}
Beispiel #4
0
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
    int i, ret;
    unsigned long __user *p = (void __user *)(unsigned long)data;

    switch (request) {
    /* when I and D space are separate, these will need to be fixed. */
    case PTRACE_PEEKTEXT: /* read word at location addr. */
    case PTRACE_PEEKDATA: {
        unsigned long tmp;
        int copied;

        ret = -EIO;
        copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
        if (copied != sizeof(tmp))
            break;
        ret = put_user(tmp, p);
        break;
    }

    /* read the word at location addr in the USER area. */
    case PTRACE_PEEKUSR:
        ret = peek_user(child, addr, data);
        break;

    /* when I and D space are separate, this will have to be fixed. */
    case PTRACE_POKETEXT: /* write the word at location addr. */
    case PTRACE_POKEDATA:
        ret = -EIO;
        if (access_process_vm(child, addr, &data, sizeof(data),
                              1) != sizeof(data))
            break;
        ret = 0;
        break;

    case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
        ret = poke_user(child, addr, data);
        break;

    case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
    case PTRACE_CONT: { /* restart after signal. */
        ret = -EIO;
        if (!valid_signal(data))
            break;

        set_singlestepping(child, 0);
        if (request == PTRACE_SYSCALL) {
            set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
        }
        else {
            clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
        }
        child->exit_code = data;
        wake_up_process(child);
        ret = 0;
        break;
    }

    /*
     * make the child exit.  Best I can do is send it a sigkill.
     * perhaps it should be put in the status that it wants to
     * exit.
     */
    case PTRACE_KILL: {
        ret = 0;
        if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
            break;

        set_singlestepping(child, 0);
        child->exit_code = SIGKILL;
        wake_up_process(child);
        break;
    }

    case PTRACE_SINGLESTEP: {  /* set the trap flag. */
        ret = -EIO;
        if (!valid_signal(data))
            break;
        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
        set_singlestepping(child, 1);
        child->exit_code = data;
        /* give it a chance to run. */
        wake_up_process(child);
        ret = 0;
        break;
    }

    case PTRACE_DETACH:
        /* detach a process that was attached. */
        ret = ptrace_detach(child, data);
        break;

#ifdef PTRACE_GETREGS
    case PTRACE_GETREGS: { /* Get all gp regs from the child. */
        if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) {
            ret = -EIO;
            break;
        }
        for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
            __put_user(getreg(child, i), p);
            p++;
        }
        ret = 0;
        break;
    }
#endif
#ifdef PTRACE_SETREGS
    case PTRACE_SETREGS: { /* Set all gp regs in the child. */
        unsigned long tmp = 0;
        if (!access_ok(VERIFY_READ, p, MAX_REG_OFFSET)) {
            ret = -EIO;
            break;
        }
        for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
            __get_user(tmp, p);
            putreg(child, i, tmp);
            p++;
        }
        ret = 0;
        break;
    }
#endif
#ifdef PTRACE_GETFPREGS
    case PTRACE_GETFPREGS: /* Get the child FPU state. */
        ret = get_fpregs(data, child);
        break;
#endif
#ifdef PTRACE_SETFPREGS
    case PTRACE_SETFPREGS: /* Set the child FPU state. */
        ret = set_fpregs(data, child);
        break;
#endif
#ifdef PTRACE_GETFPXREGS
    case PTRACE_GETFPXREGS: /* Get the child FPU state. */
        ret = get_fpxregs(data, child);
        break;
#endif
#ifdef PTRACE_SETFPXREGS
    case PTRACE_SETFPXREGS: /* Set the child FPU state. */
        ret = set_fpxregs(data, child);
        break;
#endif
    case PTRACE_GET_THREAD_AREA:
        ret = ptrace_get_thread_area(child, addr,
                                     (struct user_desc __user *) data);
        break;

    case PTRACE_SET_THREAD_AREA:
        ret = ptrace_set_thread_area(child, addr,
                                     (struct user_desc __user *) data);
        break;

    case PTRACE_FAULTINFO: {
        /* Take the info from thread->arch->faultinfo,
         * but transfer max. sizeof(struct ptrace_faultinfo).
         * On i386, ptrace_faultinfo is smaller!
         */
        ret = copy_to_user(p, &child->thread.arch.faultinfo,
                           sizeof(struct ptrace_faultinfo));
        if(ret)
            break;
        break;
    }

#ifdef PTRACE_LDT
    case PTRACE_LDT: {
        struct ptrace_ldt ldt;

        if(copy_from_user(&ldt, p, sizeof(ldt))) {
            ret = -EIO;
            break;
        }

        /* This one is confusing, so just punt and return -EIO for
         * now
         */
        ret = -EIO;
        break;
    }
#endif
#ifdef CONFIG_PROC_MM
    case PTRACE_SWITCH_MM: {
        struct mm_struct *old = child->mm;
        struct mm_struct *new = proc_mm_get_mm(data);

        if(IS_ERR(new)) {
            ret = PTR_ERR(new);
            break;
        }

        atomic_inc(&new->mm_users);
        child->mm = new;
        child->active_mm = new;
        mmput(old);
        ret = 0;
        break;
    }
#endif
    default:
        ret = ptrace_request(child, request, addr, data);
        break;
    }

    return ret;
}
T
Mem_space::peek (T const *addr, bool user_space)
{
  return user_space ? peek_user (addr) : *addr;
}