cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ptrace_64.c (5657B)


      1/*
      2 * Copyright 2003 PathScale, Inc.
      3 * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
      4 *
      5 * Licensed under the GPL
      6 */
      7
      8#include <linux/mm.h>
      9#include <linux/sched.h>
     10#include <linux/errno.h>
     11#define __FRAME_OFFSETS
     12#include <asm/ptrace.h>
     13#include <linux/uaccess.h>
     14#include <registers.h>
     15#include <asm/ptrace-abi.h>
     16
     17/*
     18 * determines which flags the user has access to.
     19 * 1 = access 0 = no access
     20 */
     21#define FLAG_MASK 0x44dd5UL
     22
     23static const int reg_offsets[] =
     24{
     25	[R8 >> 3] = HOST_R8,
     26	[R9 >> 3] = HOST_R9,
     27	[R10 >> 3] = HOST_R10,
     28	[R11 >> 3] = HOST_R11,
     29	[R12 >> 3] = HOST_R12,
     30	[R13 >> 3] = HOST_R13,
     31	[R14 >> 3] = HOST_R14,
     32	[R15 >> 3] = HOST_R15,
     33	[RIP >> 3] = HOST_IP,
     34	[RSP >> 3] = HOST_SP,
     35	[RAX >> 3] = HOST_AX,
     36	[RBX >> 3] = HOST_BX,
     37	[RCX >> 3] = HOST_CX,
     38	[RDX >> 3] = HOST_DX,
     39	[RSI >> 3] = HOST_SI,
     40	[RDI >> 3] = HOST_DI,
     41	[RBP >> 3] = HOST_BP,
     42	[CS >> 3] = HOST_CS,
     43	[SS >> 3] = HOST_SS,
     44	[FS_BASE >> 3] = HOST_FS_BASE,
     45	[GS_BASE >> 3] = HOST_GS_BASE,
     46	[DS >> 3] = HOST_DS,
     47	[ES >> 3] = HOST_ES,
     48	[FS >> 3] = HOST_FS,
     49	[GS >> 3] = HOST_GS,
     50	[EFLAGS >> 3] = HOST_EFLAGS,
     51	[ORIG_RAX >> 3] = HOST_ORIG_AX,
     52};
     53
     54int putreg(struct task_struct *child, int regno, unsigned long value)
     55{
     56	switch (regno) {
     57	case R8:
     58	case R9:
     59	case R10:
     60	case R11:
     61	case R12:
     62	case R13:
     63	case R14:
     64	case R15:
     65	case RIP:
     66	case RSP:
     67	case RAX:
     68	case RBX:
     69	case RCX:
     70	case RDX:
     71	case RSI:
     72	case RDI:
     73	case RBP:
     74		break;
     75
     76	case ORIG_RAX:
     77		/* Update the syscall number. */
     78		UPT_SYSCALL_NR(&child->thread.regs.regs) = value;
     79		break;
     80
     81	case FS:
     82	case GS:
     83	case DS:
     84	case ES:
     85	case SS:
     86	case CS:
     87		if (value && (value & 3) != 3)
     88			return -EIO;
     89		value &= 0xffff;
     90		break;
     91
     92	case FS_BASE:
     93	case GS_BASE:
     94		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
     95			return -EIO;
     96		break;
     97
     98	case EFLAGS:
     99		value &= FLAG_MASK;
    100		child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
    101		return 0;
    102
    103	default:
    104		panic("Bad register in putreg(): %d\n", regno);
    105	}
    106
    107	child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value;
    108	return 0;
    109}
    110
    111int poke_user(struct task_struct *child, long addr, long data)
    112{
    113	if ((addr & 3) || addr < 0)
    114		return -EIO;
    115
    116	if (addr < MAX_REG_OFFSET)
    117		return putreg(child, addr, data);
    118	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
    119		(addr <= offsetof(struct user, u_debugreg[7]))) {
    120		addr -= offsetof(struct user, u_debugreg[0]);
    121		addr = addr >> 3;
    122		if ((addr == 4) || (addr == 5))
    123			return -EIO;
    124		child->thread.arch.debugregs[addr] = data;
    125		return 0;
    126	}
    127	return -EIO;
    128}
    129
    130unsigned long getreg(struct task_struct *child, int regno)
    131{
    132	unsigned long mask = ~0UL;
    133
    134	switch (regno) {
    135	case R8:
    136	case R9:
    137	case R10:
    138	case R11:
    139	case R12:
    140	case R13:
    141	case R14:
    142	case R15:
    143	case RIP:
    144	case RSP:
    145	case RAX:
    146	case RBX:
    147	case RCX:
    148	case RDX:
    149	case RSI:
    150	case RDI:
    151	case RBP:
    152	case ORIG_RAX:
    153	case EFLAGS:
    154	case FS_BASE:
    155	case GS_BASE:
    156		break;
    157	case FS:
    158	case GS:
    159	case DS:
    160	case ES:
    161	case SS:
    162	case CS:
    163		mask = 0xffff;
    164		break;
    165	default:
    166		panic("Bad register in getreg: %d\n", regno);
    167	}
    168	return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]];
    169}
    170
    171int peek_user(struct task_struct *child, long addr, long data)
    172{
    173	/* read the word at location addr in the USER area. */
    174	unsigned long tmp;
    175
    176	if ((addr & 3) || addr < 0)
    177		return -EIO;
    178
    179	tmp = 0;  /* Default return condition */
    180	if (addr < MAX_REG_OFFSET)
    181		tmp = getreg(child, addr);
    182	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
    183		(addr <= offsetof(struct user, u_debugreg[7]))) {
    184		addr -= offsetof(struct user, u_debugreg[0]);
    185		addr = addr >> 2;
    186		tmp = child->thread.arch.debugregs[addr];
    187	}
    188	return put_user(tmp, (unsigned long *) data);
    189}
    190
    191/* XXX Mostly copied from sys-i386 */
    192int is_syscall(unsigned long addr)
    193{
    194	unsigned short instr;
    195	int n;
    196
    197	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
    198	if (n) {
    199		/*
    200		 * access_process_vm() grants access to vsyscall and stub,
    201		 * while copy_from_user doesn't. Maybe access_process_vm is
    202		 * slow, but that doesn't matter, since it will be called only
    203		 * in case of singlestepping, if copy_from_user failed.
    204		 */
    205		n = access_process_vm(current, addr, &instr, sizeof(instr),
    206				FOLL_FORCE);
    207		if (n != sizeof(instr)) {
    208			printk("is_syscall : failed to read instruction from "
    209			       "0x%lx\n", addr);
    210			return 1;
    211		}
    212	}
    213	/* sysenter */
    214	return instr == 0x050f;
    215}
    216
    217static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
    218{
    219	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
    220	struct user_i387_struct fpregs;
    221
    222	err = save_i387_registers(userspace_pid[cpu],
    223				  (unsigned long *) &fpregs);
    224	if (err)
    225		return err;
    226
    227	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
    228	if (n > 0)
    229		return -EFAULT;
    230
    231	return n;
    232}
    233
    234static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
    235{
    236	int n, cpu = ((struct thread_info *) child->stack)->cpu;
    237	struct user_i387_struct fpregs;
    238
    239	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
    240	if (n > 0)
    241		return -EFAULT;
    242
    243	return restore_i387_registers(userspace_pid[cpu],
    244				      (unsigned long *) &fpregs);
    245}
    246
    247long subarch_ptrace(struct task_struct *child, long request,
    248		    unsigned long addr, unsigned long data)
    249{
    250	int ret = -EIO;
    251	void __user *datap = (void __user *) data;
    252
    253	switch (request) {
    254	case PTRACE_GETFPREGS: /* Get the child FPU state. */
    255		ret = get_fpregs(datap, child);
    256		break;
    257	case PTRACE_SETFPREGS: /* Set the child FPU state. */
    258		ret = set_fpregs(datap, child);
    259		break;
    260	case PTRACE_ARCH_PRCTL:
    261		/* XXX Calls ptrace on the host - needs some SMP thinking */
    262		ret = arch_prctl(child, data, (void __user *) addr);
    263		break;
    264	}
    265
    266	return ret;
    267}