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

📄 ptrace.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	char nat = 0;	int i;	if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs)))		return -EIO;	pt = ia64_task_regs(child);	sw = (struct switch_stack *) (child->thread.ksp + 16);	unw_init_from_blocked_task(&info, child);	if (unw_unwind_to_user(&info) < 0) {		return -EIO;	}	if (((unsigned long) ppr & 0x7) != 0) {		dprintk("ptrace:unaligned register address %p\n", ppr);		return -EIO;	}	if (access_uarea(child, PT_CR_IPSR, &psr, 0) < 0	    || access_uarea(child, PT_AR_EC, &ec, 0) < 0	    || access_uarea(child, PT_AR_LC, &lc, 0) < 0	    || access_uarea(child, PT_AR_RNAT, &rnat, 0) < 0	    || access_uarea(child, PT_AR_BSP, &bsp, 0) < 0	    || access_uarea(child, PT_CFM, &cfm, 0)	    || access_uarea(child, PT_NAT_BITS, &nat_bits, 0))		return -EIO;	/* control regs */	retval |= __put_user(pt->cr_iip, &ppr->cr_iip);	retval |= __put_user(psr, &ppr->cr_ipsr);	/* app regs */	retval |= __put_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]);	retval |= __put_user(pt->ar_rsc, &ppr->ar[PT_AUR_RSC]);	retval |= __put_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]);	retval |= __put_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]);	retval |= __put_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);	retval |= __put_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]);	retval |= __put_user(ec, &ppr->ar[PT_AUR_EC]);	retval |= __put_user(lc, &ppr->ar[PT_AUR_LC]);	retval |= __put_user(rnat, &ppr->ar[PT_AUR_RNAT]);	retval |= __put_user(bsp, &ppr->ar[PT_AUR_BSP]);	retval |= __put_user(cfm, &ppr->cfm);	/* gr1-gr3 */	retval |= __copy_to_user(&ppr->gr[1], &pt->r1, sizeof(long));	retval |= __copy_to_user(&ppr->gr[2], &pt->r2, sizeof(long) *2);	/* gr4-gr7 */	for (i = 4; i < 8; i++) {		if (unw_access_gr(&info, i, &val, &nat, 0) < 0)			return -EIO;		retval |= __put_user(val, &ppr->gr[i]);	}	/* gr8-gr11 */	retval |= __copy_to_user(&ppr->gr[8], &pt->r8, sizeof(long) * 4);	/* gr12-gr15 */	retval |= __copy_to_user(&ppr->gr[12], &pt->r12, sizeof(long) * 2);	retval |= __copy_to_user(&ppr->gr[14], &pt->r14, sizeof(long));	retval |= __copy_to_user(&ppr->gr[15], &pt->r15, sizeof(long));	/* gr16-gr31 */	retval |= __copy_to_user(&ppr->gr[16], &pt->r16, sizeof(long) * 16);	/* b0 */	retval |= __put_user(pt->b0, &ppr->br[0]);	/* b1-b5 */	for (i = 1; i < 6; i++) {		if (unw_access_br(&info, i, &val, 0) < 0)			return -EIO;		__put_user(val, &ppr->br[i]);	}	/* b6-b7 */	retval |= __put_user(pt->b6, &ppr->br[6]);	retval |= __put_user(pt->b7, &ppr->br[7]);	/* fr2-fr5 */	for (i = 2; i < 6; i++) {		if (unw_get_fr(&info, i, &fpval) < 0)			return -EIO;		retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval));	}	/* fr6-fr11 */	retval |= __copy_to_user(&ppr->fr[6], &pt->f6,				 sizeof(struct ia64_fpreg) * 6);	/* fp scratch regs(12-15) */	retval |= __copy_to_user(&ppr->fr[12], &sw->f12,				 sizeof(struct ia64_fpreg) * 4);	/* fr16-fr31 */	for (i = 16; i < 32; i++) {		if (unw_get_fr(&info, i, &fpval) < 0)			return -EIO;		retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval));	}	/* fph */	ia64_flush_fph(child);	retval |= __copy_to_user(&ppr->fr[32], &child->thread.fph,				 sizeof(ppr->fr[32]) * 96);	/*  preds */	retval |= __put_user(pt->pr, &ppr->pr);	/* nat bits */	retval |= __put_user(nat_bits, &ppr->nat);	ret = retval ? -EIO : 0;	return ret;}static longptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr){	unsigned long psr, rsc, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;	struct unw_frame_info info;	struct switch_stack *sw;	struct ia64_fpreg fpval;	struct pt_regs *pt;	long ret, retval = 0;	int i;	memset(&fpval, 0, sizeof(fpval));	if (!access_ok(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs)))		return -EIO;	pt = ia64_task_regs(child);	sw = (struct switch_stack *) (child->thread.ksp + 16);	unw_init_from_blocked_task(&info, child);	if (unw_unwind_to_user(&info) < 0) {		return -EIO;	}	if (((unsigned long) ppr & 0x7) != 0) {		dprintk("ptrace:unaligned register address %p\n", ppr);		return -EIO;	}	/* control regs */	retval |= __get_user(pt->cr_iip, &ppr->cr_iip);	retval |= __get_user(psr, &ppr->cr_ipsr);	/* app regs */	retval |= __get_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]);	retval |= __get_user(rsc, &ppr->ar[PT_AUR_RSC]);	retval |= __get_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]);	retval |= __get_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]);	retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);	retval |= __get_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]);	retval |= __get_user(ec, &ppr->ar[PT_AUR_EC]);	retval |= __get_user(lc, &ppr->ar[PT_AUR_LC]);	retval |= __get_user(rnat, &ppr->ar[PT_AUR_RNAT]);	retval |= __get_user(bsp, &ppr->ar[PT_AUR_BSP]);	retval |= __get_user(cfm, &ppr->cfm);	/* gr1-gr3 */	retval |= __copy_from_user(&pt->r1, &ppr->gr[1], sizeof(long));	retval |= __copy_from_user(&pt->r2, &ppr->gr[2], sizeof(long) * 2);	/* gr4-gr7 */	for (i = 4; i < 8; i++) {		retval |= __get_user(val, &ppr->gr[i]);		/* NaT bit will be set via PT_NAT_BITS: */		if (unw_set_gr(&info, i, val, 0) < 0)			return -EIO;	}	/* gr8-gr11 */	retval |= __copy_from_user(&pt->r8, &ppr->gr[8], sizeof(long) * 4);	/* gr12-gr15 */	retval |= __copy_from_user(&pt->r12, &ppr->gr[12], sizeof(long) * 2);	retval |= __copy_from_user(&pt->r14, &ppr->gr[14], sizeof(long));	retval |= __copy_from_user(&pt->r15, &ppr->gr[15], sizeof(long));	/* gr16-gr31 */	retval |= __copy_from_user(&pt->r16, &ppr->gr[16], sizeof(long) * 16);	/* b0 */	retval |= __get_user(pt->b0, &ppr->br[0]);	/* b1-b5 */	for (i = 1; i < 6; i++) {		retval |= __get_user(val, &ppr->br[i]);		unw_set_br(&info, i, val);	}	/* b6-b7 */	retval |= __get_user(pt->b6, &ppr->br[6]);	retval |= __get_user(pt->b7, &ppr->br[7]);	/* fr2-fr5 */	for (i = 2; i < 6; i++) {		retval |= __copy_from_user(&fpval, &ppr->fr[i], sizeof(fpval));		if (unw_set_fr(&info, i, fpval) < 0)			return -EIO;	}	/* fr6-fr11 */	retval |= __copy_from_user(&pt->f6, &ppr->fr[6],				   sizeof(ppr->fr[6]) * 6);	/* fp scratch regs(12-15) */	retval |= __copy_from_user(&sw->f12, &ppr->fr[12],				   sizeof(ppr->fr[12]) * 4);	/* fr16-fr31 */	for (i = 16; i < 32; i++) {		retval |= __copy_from_user(&fpval, &ppr->fr[i],					   sizeof(fpval));		if (unw_set_fr(&info, i, fpval) < 0)			return -EIO;	}	/* fph */	ia64_sync_fph(child);	retval |= __copy_from_user(&child->thread.fph, &ppr->fr[32],				   sizeof(ppr->fr[32]) * 96);	/* preds */	retval |= __get_user(pt->pr, &ppr->pr);	/* nat bits */	retval |= __get_user(nat_bits, &ppr->nat);	retval |= access_uarea(child, PT_CR_IPSR, &psr, 1);	retval |= access_uarea(child, PT_AR_RSC, &rsc, 1);	retval |= access_uarea(child, PT_AR_EC, &ec, 1);	retval |= access_uarea(child, PT_AR_LC, &lc, 1);	retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1);	retval |= access_uarea(child, PT_AR_BSP, &bsp, 1);	retval |= access_uarea(child, PT_CFM, &cfm, 1);	retval |= access_uarea(child, PT_NAT_BITS, &nat_bits, 1);	ret = retval ? -EIO : 0;	return ret;}/* * Called by kernel/ptrace.c when detaching.. * * Make sure the single step bit is not set. */voidptrace_disable (struct task_struct *child){	struct ia64_psr *child_psr = ia64_psr(ia64_task_regs(child));	/* make sure the single step/taken-branch trap bits are not set: */	child_psr->ss = 0;	child_psr->tb = 0;}asmlinkage longsys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data){	struct pt_regs *pt;	unsigned long urbs_end, peek_or_poke;	struct task_struct *child;	struct switch_stack *sw;	long ret;	lock_kernel();	ret = -EPERM;	if (request == PTRACE_TRACEME) {		/* are we already being traced? */		if (current->ptrace & PT_PTRACED)			goto out;		ret = security_ptrace(current->parent, current);		if (ret)			goto out;		current->ptrace |= PT_PTRACED;		ret = 0;		goto out;	}	peek_or_poke = (request == PTRACE_PEEKTEXT			|| request == PTRACE_PEEKDATA			|| request == PTRACE_POKETEXT			|| request == PTRACE_POKEDATA);	ret = -ESRCH;	read_lock(&tasklist_lock);	{		child = find_task_by_pid(pid);		if (child) {			if (peek_or_poke)				child = find_thread_for_addr(child, addr);			get_task_struct(child);		}	}	read_unlock(&tasklist_lock);	if (!child)		goto out;	ret = -EPERM;	if (pid == 1)		/* no messing around with init! */		goto out_tsk;	if (request == PTRACE_ATTACH) {		ret = ptrace_attach(child);		goto out_tsk;	}	ret = ptrace_check_attach(child, request == PTRACE_KILL);	if (ret < 0)		goto out_tsk;	pt = ia64_task_regs(child);	sw = (struct switch_stack *) (child->thread.ksp + 16);	switch (request) {	      case PTRACE_PEEKTEXT:	      case PTRACE_PEEKDATA:		/* read word at location addr */		urbs_end = ia64_get_user_rbs_end(child, pt, NULL);		ret = ia64_peek(child, sw, urbs_end, addr, &data);		if (ret == 0) {			ret = data;			/* ensure "ret" is not mistaken as an error code: */			force_successful_syscall_return();		}		goto out_tsk;	      case PTRACE_POKETEXT:	      case PTRACE_POKEDATA:		/* write the word at location addr */		urbs_end = ia64_get_user_rbs_end(child, pt, NULL);		ret = ia64_poke(child, sw, urbs_end, addr, data);		goto out_tsk;	      case PTRACE_PEEKUSR:		/* read the word at addr in the USER area */		if (access_uarea(child, addr, &data, 0) < 0) {			ret = -EIO;			goto out_tsk;		}		ret = data;		/* ensure "ret" is not mistaken as an error code */		force_successful_syscall_return();		goto out_tsk;	      case PTRACE_POKEUSR:		/* write the word at addr in the USER area */		if (access_uarea(child, addr, &data, 1) < 0) {			ret = -EIO;			goto out_tsk;		}		ret = 0;		goto out_tsk;	      case PTRACE_OLD_GETSIGINFO:		/* for backwards-compatibility */		ret = ptrace_request(child, PTRACE_GETSIGINFO, addr, data);		goto out_tsk;	      case PTRACE_OLD_SETSIGINFO:		/* for backwards-compatibility */		ret = ptrace_request(child, PTRACE_SETSIGINFO, addr, data);		goto out_tsk;	      case PTRACE_SYSCALL:		/* continue and stop at next (return from) syscall */	      case PTRACE_CONT:		/* restart after signal. */		ret = -EIO;		if (!valid_signal(data))			goto out_tsk;		if (request == PTRACE_SYSCALL)			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);		else			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);		child->exit_code = data;		/*		 * Make sure the single step/taken-branch trap bits		 * are not set:		 */		ia64_psr(pt)->ss = 0;		ia64_psr(pt)->tb = 0;		wake_up_process(child);		ret = 0;		goto out_tsk;	      case PTRACE_KILL:		/*		 * Make the child exit.  Best I can do is send it a		 * sigkill.  Perhaps it should be put in the status		 * that it wants to exit.		 */		if (child->exit_state == EXIT_ZOMBIE)			/* already dead */			goto out_tsk;		child->exit_code = SIGKILL;		ptrace_disable(child);		wake_up_process(child);		ret = 0;		goto out_tsk;	      case PTRACE_SINGLESTEP:		/* let child execute for one instruction */	      case PTRACE_SINGLEBLOCK:		ret = -EIO;		if (!valid_signal(data))			goto out_tsk;		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);		if (request == PTRACE_SINGLESTEP) {			ia64_psr(pt)->ss = 1;		} else {			ia64_psr(pt)->tb = 1;		}		child->exit_code = data;		/* give it a chance to run. */		wake_up_process(child);		ret = 0;		goto out_tsk;	      case PTRACE_DETACH:		/* detach a process that was attached. */		ret = ptrace_detach(child, data);		goto out_tsk;	      case PTRACE_GETREGS:		ret = ptrace_getregs(child,				     (struct pt_all_user_regs __user *) data);		goto out_tsk;	      case PTRACE_SETREGS:		ret = ptrace_setregs(child,				     (struct pt_all_user_regs __user *) data);		goto out_tsk;	      default:		ret = ptrace_request(child, request, addr, data);		goto out_tsk;	}  out_tsk:	put_task_struct(child);  out:	unlock_kernel();	return ret;}voidsyscall_trace (void){	if (!test_thread_flag(TIF_SYSCALL_TRACE))		return;	if (!(current->ptrace & PT_PTRACED))		return;	/*	 * The 0x80 provides a way for the tracing parent to	 * distinguish between a syscall stop and SIGTRAP delivery.	 */	ptrace_notify(SIGTRAP		      | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));	/*	 * This isn't the same as continuing with a signal, but it	 * will do for normal use.  strace only continues with a	 * signal if the stopping signal is not SIGTRAP.  -brl	 */	if (current->exit_code) {		send_sig(current->exit_code, current, 1);		current->exit_code = 0;	}}/* "asmlinkage" so the input arguments are preserved... */asmlinkage voidsyscall_trace_enter (long arg0, long arg1, long arg2, long arg3,		     long arg4, long arg5, long arg6, long arg7,		     struct pt_regs regs){	if (test_thread_flag(TIF_SYSCALL_TRACE) 	    && (current->ptrace & PT_PTRACED))		syscall_trace();	if (unlikely(current->audit_context)) {		long syscall;		int arch;		if (IS_IA32_PROCESS(&regs)) {			syscall = regs.r1;			arch = AUDIT_ARCH_I386;		} else {			syscall = regs.r15;			arch = AUDIT_ARCH_IA64;		}		audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3);	}}/* "asmlinkage" so the input arguments are preserved... */asmlinkage voidsyscall_trace_leave (long arg0, long arg1, long arg2, long arg3,		     long arg4, long arg5, long arg6, long arg7,		     struct pt_regs regs){	if (unlikely(current->audit_context))		audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8);	if (test_thread_flag(TIF_SYSCALL_TRACE)	    && (current->ptrace & PT_PTRACED))		syscall_trace();}

⌨️ 快捷键说明

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