⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ptrace_64.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* By Ross Biro 1/23/92 *//* * Pentium III FXSR, SSE support *	Gareth Hughes <gareth@valinux.com>, May 2000 *  * x86-64 port 2000-2002 Andi Kleen */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/smp.h>#include <linux/errno.h>#include <linux/ptrace.h>#include <linux/user.h>#include <linux/security.h>#include <linux/audit.h>#include <linux/seccomp.h>#include <linux/signal.h>#include <asm/uaccess.h>#include <asm/pgtable.h>#include <asm/system.h>#include <asm/processor.h>#include <asm/i387.h>#include <asm/debugreg.h>#include <asm/ldt.h>#include <asm/desc.h>#include <asm/proto.h>#include <asm/ia32.h>/* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. *//* * Determines which flags the user has access to [1 = access, 0 = no access]. * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9). * Also masks reserved bits (63-22, 15, 5, 3, 1). */#define FLAG_MASK 0x54dd5UL/* set's the trap flag. */#define TRAP_FLAG 0x100UL/* * eflags and offset of eflags on child stack.. */#define EFLAGS offsetof(struct pt_regs, eflags)#define EFL_OFFSET ((int)(EFLAGS-sizeof(struct pt_regs)))/* * this routine will get a word off of the processes privileged stack.  * the offset is how far from the base addr as stored in the TSS.   * this routine assumes that all the privileged stacks are in our * data space. */   static inline unsigned long get_stack_long(struct task_struct *task, int offset){	unsigned char *stack;	stack = (unsigned char *)task->thread.rsp0;	stack += offset;	return (*((unsigned long *)stack));}/* * this routine will put a word on the processes privileged stack.  * the offset is how far from the base addr as stored in the TSS.   * this routine assumes that all the privileged stacks are in our * data space. */static inline long put_stack_long(struct task_struct *task, int offset,	unsigned long data){	unsigned char * stack;	stack = (unsigned char *) task->thread.rsp0;	stack += offset;	*(unsigned long *) stack = data;	return 0;}#define LDT_SEGMENT 4unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *regs){	unsigned long addr, seg;	addr = regs->rip;	seg = regs->cs & 0xffff;	/*	 * We'll assume that the code segments in the GDT	 * are all zero-based. That is largely true: the	 * TLS segments are used for data, and the PNPBIOS	 * and APM bios ones we just ignore here.	 */	if (seg & LDT_SEGMENT) {		u32 *desc;		unsigned long base;		seg &= ~7UL;		mutex_lock(&child->mm->context.lock);		if (unlikely((seg >> 3) >= child->mm->context.size))			addr = -1L; /* bogus selector, access would fault */		else {			desc = child->mm->context.ldt + seg;			base = ((desc[0] >> 16) |				((desc[1] & 0xff) << 16) |				(desc[1] & 0xff000000));			/* 16-bit code segment? */			if (!((desc[1] >> 22) & 1))				addr &= 0xffff;			addr += base;		}		mutex_unlock(&child->mm->context.lock);	}	return addr;}static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs){	int i, copied;	unsigned char opcode[15];	unsigned long addr = convert_rip_to_linear(child, regs);	copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);	for (i = 0; i < copied; i++) {		switch (opcode[i]) {		/* popf and iret */		case 0x9d: case 0xcf:			return 1;			/* CHECKME: 64 65 */		/* opcode and address size prefixes */		case 0x66: case 0x67:			continue;		/* irrelevant prefixes (segment overrides and repeats) */		case 0x26: case 0x2e:		case 0x36: case 0x3e:		case 0x64: case 0x65:		case 0xf2: case 0xf3:			continue;		case 0x40 ... 0x4f:			if (regs->cs != __USER_CS)				/* 32-bit mode: register increment */				return 0;			/* 64-bit mode: REX prefix */			continue;			/* CHECKME: f2, f3 */		/*		 * pushf: NOTE! We should probably not let		 * the user see the TF bit being set. But		 * it's more pain than it's worth to avoid		 * it, and a debugger could emulate this		 * all in user space if it _really_ cares.		 */		case 0x9c:		default:			return 0;		}	}	return 0;}static void set_singlestep(struct task_struct *child){	struct pt_regs *regs = task_pt_regs(child);	/*	 * Always set TIF_SINGLESTEP - this guarantees that	 * we single-step system calls etc..  This will also	 * cause us to set TF when returning to user mode.	 */	set_tsk_thread_flag(child, TIF_SINGLESTEP);	/*	 * If TF was already set, don't do anything else	 */	if (regs->eflags & TRAP_FLAG)		return;	/* Set TF on the kernel stack.. */	regs->eflags |= TRAP_FLAG;	/*	 * ..but if TF is changed by the instruction we will trace,	 * don't mark it as being "us" that set it, so that we	 * won't clear it by hand later.	 */	if (is_setting_trap_flag(child, regs))		return;	child->ptrace |= PT_DTRACE;}static void clear_singlestep(struct task_struct *child){	/* Always clear TIF_SINGLESTEP... */	clear_tsk_thread_flag(child, TIF_SINGLESTEP);	/* But touch TF only if it was set by us.. */	if (child->ptrace & PT_DTRACE) {		struct pt_regs *regs = task_pt_regs(child);		regs->eflags &= ~TRAP_FLAG;		child->ptrace &= ~PT_DTRACE;	}}/* * Called by kernel/ptrace.c when detaching.. * * Make sure the single step bit is not set. */void ptrace_disable(struct task_struct *child){ 	clear_singlestep(child);}static int putreg(struct task_struct *child,	unsigned long regno, unsigned long value){	unsigned long tmp; 		switch (regno) {		case offsetof(struct user_regs_struct,fs):			if (value && (value & 3) != 3)				return -EIO;			child->thread.fsindex = value & 0xffff; 			return 0;		case offsetof(struct user_regs_struct,gs):			if (value && (value & 3) != 3)				return -EIO;			child->thread.gsindex = value & 0xffff;			return 0;		case offsetof(struct user_regs_struct,ds):			if (value && (value & 3) != 3)				return -EIO;			child->thread.ds = value & 0xffff;			return 0;		case offsetof(struct user_regs_struct,es): 			if (value && (value & 3) != 3)				return -EIO;			child->thread.es = value & 0xffff;			return 0;		case offsetof(struct user_regs_struct,ss):			if ((value & 3) != 3)				return -EIO;			value &= 0xffff;			return 0;		case offsetof(struct user_regs_struct,fs_base):			if (value >= TASK_SIZE_OF(child))				return -EIO;			child->thread.fs = value;			return 0;		case offsetof(struct user_regs_struct,gs_base):			if (value >= TASK_SIZE_OF(child))				return -EIO;			child->thread.gs = value;			return 0;		case offsetof(struct user_regs_struct, eflags):			value &= FLAG_MASK;			tmp = get_stack_long(child, EFL_OFFSET); 			tmp &= ~FLAG_MASK; 			value |= tmp;			break;		case offsetof(struct user_regs_struct,cs): 			if ((value & 3) != 3)				return -EIO;			value &= 0xffff;			break;	}	put_stack_long(child, regno - sizeof(struct pt_regs), value);	return 0;}static unsigned long getreg(struct task_struct *child, unsigned long regno){	unsigned long val;	switch (regno) {		case offsetof(struct user_regs_struct, fs):			return child->thread.fsindex;		case offsetof(struct user_regs_struct, gs):			return child->thread.gsindex;		case offsetof(struct user_regs_struct, ds):			return child->thread.ds;		case offsetof(struct user_regs_struct, es):			return child->thread.es; 		case offsetof(struct user_regs_struct, fs_base):			return child->thread.fs;		case offsetof(struct user_regs_struct, gs_base):			return child->thread.gs;		default:			regno = regno - sizeof(struct pt_regs);			val = get_stack_long(child, regno);			if (test_tsk_thread_flag(child, TIF_IA32))				val &= 0xffffffff;			return val;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -