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

📄 ptrace_32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* By Ross Biro 1/23/92 *//* * Pentium III FXSR, SSE support *	Gareth Hughes <gareth@valinux.com>, May 2000 */#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>/* * 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), NT(14), IOPL(12-13), IF(9). * Also masks reserved bits (31-22, 15, 5, 3, 1). */#define FLAG_MASK 0x00050dd5/* set's the trap flag. */#define TRAP_FLAG 0x100/* * Offset of eflags on child stack.. */#define EFL_OFFSET offsetof(struct pt_regs, eflags)static inline struct pt_regs *get_child_regs(struct task_struct *task){	void *stack_top = (void *)task->thread.esp0;	return stack_top - sizeof(struct pt_regs);}/* * This routine will get a word off of the processes privileged stack. * the offset is bytes into the pt_regs structure on the stack. * This routine assumes that all the privileged stacks are in our * data space. */   static inline int get_stack_long(struct task_struct *task, int offset){	unsigned char *stack;	stack = (unsigned char *)task->thread.esp0 - sizeof(struct pt_regs);	stack += offset;	return (*((int *)stack));}/* * This routine will put a word on the processes privileged stack. * the offset is bytes into the pt_regs structure on the stack. * This routine assumes that all the privileged stacks are in our * data space. */static inline int put_stack_long(struct task_struct *task, int offset,	unsigned long data){	unsigned char * stack;	stack = (unsigned char *)task->thread.esp0 - sizeof(struct pt_regs);	stack += offset;	*(unsigned long *) stack = data;	return 0;}static int putreg(struct task_struct *child,	unsigned long regno, unsigned long value){	switch (regno >> 2) {		case GS:			if (value && (value & 3) != 3)				return -EIO;			child->thread.gs = value;			return 0;		case DS:		case ES:		case FS:			if (value && (value & 3) != 3)				return -EIO;			value &= 0xffff;			break;		case SS:		case CS:			if ((value & 3) != 3)				return -EIO;			value &= 0xffff;			break;		case EFL:			value &= FLAG_MASK;			value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;			break;	}	if (regno > FS*4)		regno -= 1*4;	put_stack_long(child, regno, value);	return 0;}static unsigned long getreg(struct task_struct *child,	unsigned long regno){	unsigned long retval = ~0UL;	switch (regno >> 2) {		case GS:			retval = child->thread.gs;			break;		case DS:		case ES:		case FS:		case SS:		case CS:			retval = 0xffff;			/* fall through */		default:			if (regno > FS*4)				regno -= 1*4;			retval &= get_stack_long(child, regno);	}	return retval;}#define LDT_SEGMENT 4static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_regs *regs){	unsigned long addr, seg;	addr = regs->eip;	seg = regs->xcs & 0xffff;	if (regs->eflags & VM_MASK) {		addr = (addr & 0xffff) + (seg << 4);		return addr;	}	/*	 * 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 inline int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs){	int i, copied;	unsigned char opcode[15];	unsigned long addr = convert_eip_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;		/* 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 0xf0: case 0xf2: case 0xf3:			continue;		/*		 * 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 = get_child_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 = get_child_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);	clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);}/* * Perform get_thread_area on behalf of the traced child. */static intptrace_get_thread_area(struct task_struct *child,		       int idx, struct user_desc __user *user_desc){	struct user_desc info;	struct desc_struct *desc;/* * Get the current Thread-Local Storage area: */#define GET_BASE(desc) ( \	(((desc)->a >> 16) & 0x0000ffff) | \	(((desc)->b << 16) & 0x00ff0000) | \	( (desc)->b        & 0xff000000)   )#define GET_LIMIT(desc) ( \	((desc)->a & 0x0ffff) | \	 ((desc)->b & 0xf0000) )#define GET_32BIT(desc)		(((desc)->b >> 22) & 1)#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)		return -EINVAL;	desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;	info.entry_number = idx;	info.base_addr = GET_BASE(desc);	info.limit = GET_LIMIT(desc);	info.seg_32bit = GET_32BIT(desc);	info.contents = GET_CONTENTS(desc);	info.read_exec_only = !GET_WRITABLE(desc);	info.limit_in_pages = GET_LIMIT_PAGES(desc);	info.seg_not_present = !GET_PRESENT(desc);	info.useable = GET_USEABLE(desc);	if (copy_to_user(user_desc, &info, sizeof(info)))		return -EFAULT;	return 0;}/* * Perform set_thread_area on behalf of the traced child. */static intptrace_set_thread_area(struct task_struct *child,		       int idx, struct user_desc __user *user_desc){	struct user_desc info;	struct desc_struct *desc;	if (copy_from_user(&info, user_desc, sizeof(info)))		return -EFAULT;	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)		return -EINVAL;	desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;	if (LDT_empty(&info)) {		desc->a = 0;		desc->b = 0;	} else {		desc->a = LDT_entry_a(&info);		desc->b = LDT_entry_b(&info);	}	return 0;}long arch_ptrace(struct task_struct *child, long request, long addr, long data){

⌨️ 快捷键说明

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