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

📄 ptrace32.c

📁 linux-2.6.15.6
💻 C
字号:
/*  * 32bit ptrace for x86-64. * * Copyright 2001,2002 Andi Kleen, SuSE Labs. * Some parts copied from arch/i386/kernel/ptrace.c. See that file for earlier  * copyright. *  * This allows to access 64bit processes too; but there is no way to see the extended  * register contents. * * $Id: ptrace32.c,v 1.16 2003/03/14 16:06:35 ak Exp $ */ #include <linux/kernel.h>#include <linux/stddef.h>#include <linux/sched.h>#include <linux/syscalls.h>#include <linux/unistd.h>#include <linux/mm.h>#include <linux/ptrace.h>#include <asm/ptrace.h>#include <asm/compat.h>#include <asm/uaccess.h>#include <asm/user32.h>#include <asm/user.h>#include <asm/errno.h>#include <asm/debugreg.h>#include <asm/i387.h>#include <asm/fpu32.h>/* determines which flags the user has access to. *//* 1 = access 0 = no access */#define FLAG_MASK 0x44dd5UL#define R32(l,q) \	case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; breakstatic int putreg32(struct task_struct *child, unsigned regno, u32 val){	int i;	__u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs)); 	switch (regno) {	case offsetof(struct user32, regs.fs):		if (val && (val & 3) != 3) return -EIO; 		child->thread.fsindex = val & 0xffff;		break;	case offsetof(struct user32, regs.gs):		if (val && (val & 3) != 3) return -EIO; 		child->thread.gsindex = val & 0xffff;		break;	case offsetof(struct user32, regs.ds):		if (val && (val & 3) != 3) return -EIO; 		child->thread.ds = val & 0xffff;		break;	case offsetof(struct user32, regs.es):		child->thread.es = val & 0xffff;		break;	case offsetof(struct user32, regs.ss): 		if ((val & 3) != 3) return -EIO;        	stack[offsetof(struct pt_regs, ss)/8] = val & 0xffff;		break;	case offsetof(struct user32, regs.cs): 		if ((val & 3) != 3) return -EIO;		stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff;		break;	R32(ebx, rbx); 	R32(ecx, rcx);	R32(edx, rdx);	R32(edi, rdi);	R32(esi, rsi);	R32(ebp, rbp);	R32(eax, rax);	R32(orig_eax, orig_rax);	R32(eip, rip);	R32(esp, rsp);	case offsetof(struct user32, regs.eflags): {		__u64 *flags = &stack[offsetof(struct pt_regs, eflags)/8];		val &= FLAG_MASK;		*flags = val | (*flags & ~FLAG_MASK);		break;	}	case offsetof(struct user32, u_debugreg[4]): 	case offsetof(struct user32, u_debugreg[5]):		return -EIO;	case offsetof(struct user32, u_debugreg[0]):		child->thread.debugreg0 = val;		break;	case offsetof(struct user32, u_debugreg[1]):		child->thread.debugreg1 = val;		break;	case offsetof(struct user32, u_debugreg[2]):		child->thread.debugreg2 = val;		break;	case offsetof(struct user32, u_debugreg[3]):		child->thread.debugreg3 = val;		break;	case offsetof(struct user32, u_debugreg[6]):		child->thread.debugreg6 = val;		break; 	case offsetof(struct user32, u_debugreg[7]):		val &= ~DR_CONTROL_RESERVED;		/* See arch/i386/kernel/ptrace.c for an explanation of		 * this awkward check.*/		for(i=0; i<4; i++)			if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1)			       return -EIO;		child->thread.debugreg7 = val; 		break; 		    	default:		if (regno > sizeof(struct user32) || (regno & 3))			return -EIO;	       		/* Other dummy fields in the virtual user structure are ignored */ 		break; 			}	return 0;}#undef R32#define R32(l,q) \	case offsetof(struct user32, regs.l): *val = stack[offsetof(struct pt_regs, q)/8]; breakstatic int getreg32(struct task_struct *child, unsigned regno, u32 *val){	__u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs)); 	switch (regno) {	case offsetof(struct user32, regs.fs):	        *val = child->thread.fsindex;		break;	case offsetof(struct user32, regs.gs):		*val = child->thread.gsindex;		break;	case offsetof(struct user32, regs.ds):		*val = child->thread.ds;		break;	case offsetof(struct user32, regs.es):		*val = child->thread.es;		break;	R32(cs, cs);	R32(ss, ss);	R32(ebx, rbx); 	R32(ecx, rcx);	R32(edx, rdx);	R32(edi, rdi);	R32(esi, rsi);	R32(ebp, rbp);	R32(eax, rax);	R32(orig_eax, orig_rax);	R32(eip, rip);	R32(eflags, eflags);	R32(esp, rsp);	case offsetof(struct user32, u_debugreg[0]): 		*val = child->thread.debugreg0; 		break; 	case offsetof(struct user32, u_debugreg[1]): 		*val = child->thread.debugreg1; 		break; 	case offsetof(struct user32, u_debugreg[2]): 		*val = child->thread.debugreg2; 		break; 	case offsetof(struct user32, u_debugreg[3]): 		*val = child->thread.debugreg3; 		break; 	case offsetof(struct user32, u_debugreg[6]): 		*val = child->thread.debugreg6; 		break; 	case offsetof(struct user32, u_debugreg[7]): 		*val = child->thread.debugreg7; 		break; 		    	default:		if (regno > sizeof(struct user32) || (regno & 3))			return -EIO;		/* Other dummy fields in the virtual user structure are ignored */ 		*val = 0;		break; 			}	return 0;}#undef R32static struct task_struct *find_target(int request, int pid, int *err){ 	struct task_struct *child;	*err = -EPERM; 	if (pid == 1)		return NULL; 	*err = -ESRCH;	read_lock(&tasklist_lock);	child = find_task_by_pid(pid);	if (child)		get_task_struct(child);	read_unlock(&tasklist_lock);	if (child) { 		*err = -EPERM;		if (child->pid == 1) 			goto out;		*err = ptrace_check_attach(child, request == PTRACE_KILL); 		if (*err < 0) 			goto out;		return child; 	}  out:	if (child)	put_task_struct(child);	return NULL; 	} asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data){	struct task_struct *child;	struct pt_regs *childregs; 	void __user *datap = compat_ptr(data);	int ret;	__u32 val;	switch (request) { 	default:		return sys_ptrace(request, pid, addr, data); 	case PTRACE_PEEKTEXT:	case PTRACE_PEEKDATA:	case PTRACE_POKEDATA:	case PTRACE_POKETEXT:	case PTRACE_POKEUSR:       	case PTRACE_PEEKUSR:	case PTRACE_GETREGS:	case PTRACE_SETREGS:	case PTRACE_SETFPREGS:	case PTRACE_GETFPREGS:	case PTRACE_SETFPXREGS:	case PTRACE_GETFPXREGS:	case PTRACE_GETEVENTMSG:		break;	} 	child = find_target(request, pid, &ret);	if (!child)		return ret;	childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs)); 	switch (request) {	case PTRACE_PEEKDATA:	case PTRACE_PEEKTEXT:		ret = 0;		if (access_process_vm(child, addr, &val, sizeof(u32), 0)!=sizeof(u32))			ret = -EIO;		else			ret = put_user(val, (unsigned int __user *)datap); 		break; 	case PTRACE_POKEDATA:	case PTRACE_POKETEXT:		ret = 0;		if (access_process_vm(child, addr, &data, sizeof(u32), 1)!=sizeof(u32))			ret = -EIO; 		break;	case PTRACE_PEEKUSR:		ret = getreg32(child, addr, &val);		if (ret == 0)			ret = put_user(val, (__u32 __user *)datap);		break;	case PTRACE_POKEUSR:		ret = putreg32(child, addr, data);		break;	case PTRACE_GETREGS: { /* Get all gp regs from the child. */		int i;	  	if (!access_ok(VERIFY_WRITE, datap, 16*4)) {			ret = -EIO;			break;		}		ret = 0;		for ( i = 0; i <= 16*4 ; i += sizeof(__u32) ) {			getreg32(child, i, &val);			ret |= __put_user(val,(u32 __user *)datap);			datap += sizeof(u32);		}		break;	}	case PTRACE_SETREGS: { /* Set all gp regs in the child. */		unsigned long tmp;		int i;	  	if (!access_ok(VERIFY_READ, datap, 16*4)) {			ret = -EIO;			break;		}		ret = 0; 		for ( i = 0; i <= 16*4; i += sizeof(u32) ) {			ret |= __get_user(tmp, (u32 __user *)datap);			putreg32(child, i, tmp);			datap += sizeof(u32);		}		break;	}	case PTRACE_GETFPREGS:		ret = -EIO; 		if (!access_ok(VERIFY_READ, compat_ptr(data), 			       sizeof(struct user_i387_struct)))			break;		save_i387_ia32(child, datap, childregs, 1);		ret = 0; 			break;	case PTRACE_SETFPREGS:		ret = -EIO;		if (!access_ok(VERIFY_WRITE, datap, 			       sizeof(struct user_i387_struct)))			break;		ret = 0;		/* don't check EFAULT to be bug-to-bug compatible to i386 */		restore_i387_ia32(child, datap, 1);		break;	case PTRACE_GETFPXREGS: { 		struct user32_fxsr_struct __user *u = datap;		init_fpu(child); 		ret = -EIO;		if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))			break;			ret = -EFAULT;		if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u)))			break;		ret = __put_user(childregs->cs, &u->fcs);		ret |= __put_user(child->thread.ds, &u->fos); 		break; 	} 	case PTRACE_SETFPXREGS: { 		struct user32_fxsr_struct __user *u = datap;		unlazy_fpu(child);		ret = -EIO;		if (!access_ok(VERIFY_READ, u, sizeof(*u)))			break;		/* no checking to be bug-to-bug compatible with i386 */		__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u));		set_stopped_child_used_math(child);		child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;		ret = 0; 		break;	}	case PTRACE_GETEVENTMSG:		ret = put_user(child->ptrace_message,(unsigned int __user *)compat_ptr(data));		break;	default:		ret = -EINVAL;		break;	}	put_task_struct(child);	return ret;}

⌨️ 快捷键说明

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