Beispiel #1
0
int restore_sigcontext(struct pt_regs *regs,
		       struct sigcontext __user *sc)
{
	int err = 0;
	int i;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	/*
	 * Enforce that sigcontext is like pt_regs, and doesn't mess
	 * up our stack alignment rules.
	 */
	BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs));
	BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0);

	for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
		err |= __get_user(regs->regs[i], &sc->gregs[i]);

	/* Ensure that the PL is always set to USER_PL. */
	regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1));

	regs->faultnum = INT_SWINT_1_SIGRETURN;

	return err;
}
Beispiel #2
0
/* Put registers back to task. */
static void putregs(struct task_struct *child, struct pt_regs *uregs)
{
	struct pt_regs *regs = task_pt_regs(child);

	/* Don't allow overwriting the kernel-internal flags word. */
	uregs->flags = regs->flags;

	/* Only allow setting the ICS bit in the ex1 word. */
	uregs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(uregs->ex1));

	*regs = *uregs;
}
/* Put registers back to task. */
static void putregs(struct task_struct *child, struct pt_regs *uregs)
{
	struct pt_regs *regs = task_pt_regs(child);

	/*
	 * Don't allow overwriting the kernel-internal flags word.
	 * But do set PT_FLAGS_RESTORE_REGS so that the kernel will reload
	 * all the callee-saved registers when returning to userspace.
	 */ 
	uregs->flags = regs->flags | PT_FLAGS_RESTORE_REGS;

	/* Only allow setting the ICS bit in the ex1 word. */
	uregs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(uregs->ex1));

	*regs = *uregs;
}
int restore_sigcontext(struct pt_regs *regs,
		       struct sigcontext __user *sc)
{
	int err = 0;
	int i;

	
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs));
	BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0);

	for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
		err |= __get_user(regs->regs[i], &sc->gregs[i]);

	
	regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1));

	regs->faultnum = INT_SWINT_1_SIGRETURN;

	return err;
}
Beispiel #5
0
int restore_sigcontext(struct pt_regs *regs,
		       struct sigcontext __user *sc)
{
	int err;

	/* Always make any pending restarted system calls return -EINTR */
	current->restart_block.fn = do_no_restart_syscall;

	/*
	 * Enforce that sigcontext is like pt_regs, and doesn't mess
	 * up our stack alignment rules.
	 */
	BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs));
	BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0);
	err = __copy_from_user(regs, sc, sizeof(*regs));

	/* Ensure that the PL is always set to USER_PL. */
	regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1));

	regs->faultnum = INT_SWINT_1_SIGRETURN;

	return err;
}
long arch_ptrace(struct task_struct *child, long request,
		 unsigned long addr, unsigned long data)
{
	unsigned long __user *datap = (long __user __force *)data;
	unsigned long tmp;
	long ret = -EIO;
	char *childreg;
	struct pt_regs copyregs;
	int ex1_offset;

	switch (request) {

	case PTRACE_PEEKUSR:  /*                             */
		if (addr >= PTREGS_SIZE)
			break;
		childreg = (char *)task_pt_regs(child) + addr;
#ifdef CONFIG_COMPAT
		if (is_compat_task()) {
			if (addr & (sizeof(compat_long_t)-1))
				break;
			ret = put_user(*(compat_long_t *)childreg,
				       (compat_long_t __user *)datap);
		} else
#endif
		{
			if (addr & (sizeof(long)-1))
				break;
			ret = put_user(*(long *)childreg, datap);
		}
		break;

	case PTRACE_POKEUSR:  /*                            */
		if (addr >= PTREGS_SIZE)
			break;
		childreg = (char *)task_pt_regs(child) + addr;

		/*                                                  */
		ex1_offset = PTREGS_OFFSET_EX1;
#if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN)
		if (is_compat_task())   /*                   */
			ex1_offset += sizeof(compat_long_t);
#endif
		if (addr == ex1_offset)
			data = PL_ICS_EX1(USER_PL, EX1_ICS(data));

#ifdef CONFIG_COMPAT
		if (is_compat_task()) {
			if (addr & (sizeof(compat_long_t)-1))
				break;
			*(compat_long_t *)childreg = data;
		} else
#endif
		{
			if (addr & (sizeof(long)-1))
				break;
			*(long *)childreg = data;
		}
		ret = 0;
		break;

	case PTRACE_GETREGS:  /*                                   */
		if (copy_to_user(datap, task_pt_regs(child),
				 sizeof(struct pt_regs)) == 0) {
			ret = 0;
		}
		break;

	case PTRACE_SETREGS:  /*                                 */
		if (copy_from_user(&copyregs, datap,
				   sizeof(struct pt_regs)) == 0) {
			copyregs.ex1 =
				PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1));
			*task_pt_regs(child) = copyregs;
			ret = 0;
		}
		break;

	case PTRACE_GETFPREGS:  /*                          */
	case PTRACE_SETFPREGS:  /*                          */
		break;

	case PTRACE_SETOPTIONS:
		/*                                       */
		child->ptrace &= ~PT_TRACE_MASK_TILE;
		tmp = data & PTRACE_O_MASK_TILE;
		data &= ~PTRACE_O_MASK_TILE;
		ret = ptrace_request(child, request, addr, data);
		if (tmp & PTRACE_O_TRACEMIGRATE)
			child->ptrace |= PT_TRACE_MIGRATE;
		break;

	default:
#ifdef CONFIG_COMPAT
		if (task_thread_info(current)->status & TS_COMPAT) {
			ret = compat_ptrace_request(child, request,
						    addr, data);
			break;
		}
#endif
		ret = ptrace_request(child, request, addr, data);
		break;
	}

	return ret;
}