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

📄 ptrace.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdef PTRACE_SINGLEBLOCK#define is_singleblock(request)		((request) == PTRACE_SINGLEBLOCK)#else#define is_singleblock(request)		0#endif#ifdef PTRACE_SYSEMU#define is_sysemu_singlestep(request)	((request) == PTRACE_SYSEMU_SINGLESTEP)#else#define is_sysemu_singlestep(request)	0#endifstatic int ptrace_resume(struct task_struct *child, long request, long data){	if (!valid_signal(data))		return -EIO;	if (request == PTRACE_SYSCALL)		set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);	else		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);#ifdef TIF_SYSCALL_EMU	if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP)		set_tsk_thread_flag(child, TIF_SYSCALL_EMU);	else		clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);#endif	if (is_singleblock(request)) {		if (unlikely(!arch_has_block_step()))			return -EIO;		user_enable_block_step(child);	} else if (is_singlestep(request) || is_sysemu_singlestep(request)) {		if (unlikely(!arch_has_single_step()))			return -EIO;		user_enable_single_step(child);	}	else		user_disable_single_step(child);	child->exit_code = data;	wake_up_process(child);	return 0;}int ptrace_request(struct task_struct *child, long request,		   long addr, long data){	int ret = -EIO;	siginfo_t siginfo;	switch (request) {	case PTRACE_PEEKTEXT:	case PTRACE_PEEKDATA:		return generic_ptrace_peekdata(child, addr, data);	case PTRACE_POKETEXT:	case PTRACE_POKEDATA:		return generic_ptrace_pokedata(child, addr, data);#ifdef PTRACE_OLDSETOPTIONS	case PTRACE_OLDSETOPTIONS:#endif	case PTRACE_SETOPTIONS:		ret = ptrace_setoptions(child, data);		break;	case PTRACE_GETEVENTMSG:		ret = put_user(child->ptrace_message, (unsigned long __user *) data);		break;	case PTRACE_GETSIGINFO:		ret = ptrace_getsiginfo(child, &siginfo);		if (!ret)			ret = copy_siginfo_to_user((siginfo_t __user *) data,						   &siginfo);		break;	case PTRACE_SETSIGINFO:		if (copy_from_user(&siginfo, (siginfo_t __user *) data,				   sizeof siginfo))			ret = -EFAULT;		else			ret = ptrace_setsiginfo(child, &siginfo);		break;	case PTRACE_DETACH:	 /* detach a process that was attached. */		ret = ptrace_detach(child, data);		break;#ifdef PTRACE_SINGLESTEP	case PTRACE_SINGLESTEP:#endif#ifdef PTRACE_SINGLEBLOCK	case PTRACE_SINGLEBLOCK:#endif#ifdef PTRACE_SYSEMU	case PTRACE_SYSEMU:	case PTRACE_SYSEMU_SINGLESTEP:#endif	case PTRACE_SYSCALL:	case PTRACE_CONT:		return ptrace_resume(child, request, data);	case PTRACE_KILL:		if (child->exit_state)	/* already dead */			return 0;		return ptrace_resume(child, request, SIGKILL);	default:		break;	}	return ret;}/** * ptrace_traceme  --  helper for PTRACE_TRACEME * * Performs checks and sets PT_PTRACED. * Should be used by all ptrace implementations for PTRACE_TRACEME. */int ptrace_traceme(void){	int ret = -EPERM;	/*	 * Are we already being traced?	 */repeat:	task_lock(current);	if (!(current->ptrace & PT_PTRACED)) {		/*		 * See ptrace_attach() comments about the locking here.		 */		unsigned long flags;		if (!write_trylock_irqsave(&tasklist_lock, flags)) {			task_unlock(current);			do {				cpu_relax();			} while (!write_can_lock(&tasklist_lock));			goto repeat;		}		ret = security_ptrace_traceme(current->parent);		/*		 * Set the ptrace bit in the process ptrace flags.		 * Then link us on our parent's ptraced list.		 */		if (!ret) {			current->ptrace |= PT_PTRACED;			__ptrace_link(current, current->real_parent);		}		write_unlock_irqrestore(&tasklist_lock, flags);	}	task_unlock(current);	return ret;}/** * ptrace_get_task_struct  --  grab a task struct reference for ptrace * @pid:       process id to grab a task_struct reference of * * This function is a helper for ptrace implementations.  It checks * permissions and then grabs a task struct for use of the actual * ptrace implementation. * * Returns the task_struct for @pid or an ERR_PTR() on failure. */struct task_struct *ptrace_get_task_struct(pid_t pid){	struct task_struct *child;	read_lock(&tasklist_lock);	child = find_task_by_vpid(pid);	if (child)		get_task_struct(child);	read_unlock(&tasklist_lock);	if (!child)		return ERR_PTR(-ESRCH);	return child;}#ifndef arch_ptrace_attach#define arch_ptrace_attach(child)	do { } while (0)#endifasmlinkage long sys_ptrace(long request, long pid, long addr, long data){	struct task_struct *child;	long ret;	/*	 * This lock_kernel fixes a subtle race with suid exec	 */	lock_kernel();	if (request == PTRACE_TRACEME) {		ret = ptrace_traceme();		if (!ret)			arch_ptrace_attach(current);		goto out;	}	child = ptrace_get_task_struct(pid);	if (IS_ERR(child)) {		ret = PTR_ERR(child);		goto out;	}	if (request == PTRACE_ATTACH) {		ret = ptrace_attach(child);		/*		 * Some architectures need to do book-keeping after		 * a ptrace attach.		 */		if (!ret)			arch_ptrace_attach(child);		goto out_put_task_struct;	}	ret = ptrace_check_attach(child, request == PTRACE_KILL);	if (ret < 0)		goto out_put_task_struct;	ret = arch_ptrace(child, request, addr, data);	if (ret < 0)		goto out_put_task_struct; out_put_task_struct:	put_task_struct(child); out:	unlock_kernel();	return ret;}int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data){	unsigned long tmp;	int copied;	copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);	if (copied != sizeof(tmp))		return -EIO;	return put_user(tmp, (unsigned long __user *)data);}int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data){	int copied;	copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);	return (copied == sizeof(data)) ? 0 : -EIO;}#if defined CONFIG_COMPAT && defined __ARCH_WANT_COMPAT_SYS_PTRACE#include <linux/compat.h>int compat_ptrace_request(struct task_struct *child, compat_long_t request,			  compat_ulong_t addr, compat_ulong_t data){	compat_ulong_t __user *datap = compat_ptr(data);	compat_ulong_t word;	siginfo_t siginfo;	int ret;	switch (request) {	case PTRACE_PEEKTEXT:	case PTRACE_PEEKDATA:		ret = access_process_vm(child, addr, &word, sizeof(word), 0);		if (ret != sizeof(word))			ret = -EIO;		else			ret = put_user(word, datap);		break;	case PTRACE_POKETEXT:	case PTRACE_POKEDATA:		ret = access_process_vm(child, addr, &data, sizeof(data), 1);		ret = (ret != sizeof(data) ? -EIO : 0);		break;	case PTRACE_GETEVENTMSG:		ret = put_user((compat_ulong_t) child->ptrace_message, datap);		break;	case PTRACE_GETSIGINFO:		ret = ptrace_getsiginfo(child, &siginfo);		if (!ret)			ret = copy_siginfo_to_user32(				(struct compat_siginfo __user *) datap,				&siginfo);		break;	case PTRACE_SETSIGINFO:		memset(&siginfo, 0, sizeof siginfo);		if (copy_siginfo_from_user32(			    &siginfo, (struct compat_siginfo __user *) datap))			ret = -EFAULT;		else			ret = ptrace_setsiginfo(child, &siginfo);		break;	default:		ret = ptrace_request(child, request, addr, data);	}	return ret;}asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,				  compat_long_t addr, compat_long_t data){	struct task_struct *child;	long ret;	/*	 * This lock_kernel fixes a subtle race with suid exec	 */	lock_kernel();	if (request == PTRACE_TRACEME) {		ret = ptrace_traceme();		goto out;	}	child = ptrace_get_task_struct(pid);	if (IS_ERR(child)) {		ret = PTR_ERR(child);		goto out;	}	if (request == PTRACE_ATTACH) {		ret = ptrace_attach(child);		/*		 * Some architectures need to do book-keeping after		 * a ptrace attach.		 */		if (!ret)			arch_ptrace_attach(child);		goto out_put_task_struct;	}	ret = ptrace_check_attach(child, request == PTRACE_KILL);	if (!ret)		ret = compat_arch_ptrace(child, request, addr, data); out_put_task_struct:	put_task_struct(child); out:	unlock_kernel();	return ret;}#endif	/* CONFIG_COMPAT && __ARCH_WANT_COMPAT_SYS_PTRACE */

⌨️ 快捷键说明

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