Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 481bed45 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds
Browse files

[PATCH] consolidate sys_ptrace()



The sys_ptrace boilerplate code (everything outside the big switch
statement for the arch-specific requests) is shared by most architectures.
This patch moves it to kernel/ptrace.c and leaves the arch-specific code as
arch_ptrace.

Some architectures have a too different ptrace so we have to exclude them.
They continue to keep their implementations.  For sh64 I had to add a
sh64_ptrace wrapper because it does some initialization on the first call.
For um I removed an ifdefed SUBARCH_PTRACE_SPECIAL block, but
SUBARCH_PTRACE_SPECIAL isn't defined anywhere in the tree.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarPaul Mackerras <paulus@samba.org>
Acked-by: default avatarRalf Baechle <ralf@linux-mips.org>
Acked-By: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Acked-by: default avatarPaul Mundt <lethal@linux-sh.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent db73e9aa
Loading
Loading
Loading
Loading
+1 −48
Original line number Diff line number Diff line
@@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)

#endif

static int do_ptrace(int request, struct task_struct *child, long addr, long data)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
	unsigned long tmp;
	int ret;
@@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
	return ret;
}

asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
{
	struct task_struct *child;
	int 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;
		/* set the ptrace bit in the process flags. */
		current->ptrace |= PT_PTRACED;
		ret = 0;
		goto out;
	}
	ret = -ESRCH;
	read_lock(&tasklist_lock);
	child = find_task_by_pid(pid);
	if (child)
		get_task_struct(child);
	read_unlock(&tasklist_lock);
	if (!child)
		goto out;

	ret = -EPERM;
	if (pid == 1)		/* you may not mess 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)
		ret = do_ptrace(request, child, addr, data);

out_tsk:
	put_task_struct(child);
out:
	unlock_kernel();
	return ret;
}

asmlinkage void syscall_trace(int why, struct pt_regs *regs)
{
	unsigned long ip;
+1 −48
Original line number Diff line number Diff line
@@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
			      sizeof(struct user_fp)) ? -EFAULT : 0;
}

static int do_ptrace(int request, struct task_struct *child, long addr, long data)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
	unsigned long tmp;
	int ret;
@@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
	return ret;
}

asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
{
	struct task_struct *child;
	int 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;
		/* set the ptrace bit in the process flags. */
		current->ptrace |= PT_PTRACED;
		ret = 0;
		goto out;
	}
	ret = -ESRCH;
	read_lock(&tasklist_lock);
	child = find_task_by_pid(pid);
	if (child)
		get_task_struct(child);
	read_unlock(&tasklist_lock);
	if (!child)
		goto out;

	ret = -EPERM;
	if (pid == 1)		/* you may not mess 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)
		ret = do_ptrace(request, child, addr, data);

out_tsk:
	put_task_struct(child);
out:
	unlock_kernel();
	return ret;
}

asmlinkage void syscall_trace(int why, struct pt_regs *regs)
{
	unsigned long ip;
+2 −49
Original line number Diff line number Diff line
@@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child)
 * (in user space) where the result of the ptrace call is written (instead of
 * being returned).
 */
asmlinkage int 
sys_ptrace(long request, long pid, long addr, long data)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
	struct task_struct *child;
	int ret;
	unsigned long __user *datap = (unsigned long __user *)data;

	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;
		/* set the ptrace bit in the process flags. */
		current->ptrace |= PT_PTRACED;
		ret = 0;
		goto out;
	}
	
	ret = -ESRCH;
	read_lock(&tasklist_lock);
	child = find_task_by_pid(pid);
	
	if (child)
		get_task_struct(child);
	
	read_unlock(&tasklist_lock);
	
	if (!child)
		goto out;
	
	ret = -EPERM;
	
	if (pid == 1)		/* Leave the init process alone! */
		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;

	switch (request) {
		/* Read word at location address. */ 
		case PTRACE_PEEKTEXT:
@@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data)
			ret = ptrace_request(child, request, addr, data);
			break;
	}
out_tsk:
	put_task_struct(child);
out:
	unlock_kernel();

	return ret;
}

+2 −49
Original line number Diff line number Diff line
@@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child)
}


asmlinkage int
sys_ptrace(long request, long pid, long addr, long data)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
	struct task_struct *child;
	int ret;
	unsigned long __user *datap = (unsigned long __user *)data;

	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;
		/* set the ptrace bit in the process flags. */
		current->ptrace |= PT_PTRACED;
		ret = 0;
		goto out;
	}

	ret = -ESRCH;
	read_lock(&tasklist_lock);
	child = find_task_by_pid(pid);

	if (child)
		get_task_struct(child);

	read_unlock(&tasklist_lock);

	if (!child)
		goto out;

	ret = -EPERM;

	if (pid == 1)		/* Leave the init process alone! */
		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;

	switch (request) {
		/* Read word at location address. */
		case PTRACE_PEEKTEXT:
@@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data)
			ret = ptrace_request(child, request, addr, data);
			break;
	}
out_tsk:
	put_task_struct(child);
out:
	unlock_kernel();

	return ret;
}

+1 −42
Original line number Diff line number Diff line
@@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child)
	child->thread.frame0->__status |= REG__STATUS_STEP;
}

asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
	struct task_struct *child;
	unsigned long tmp;
	int 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;
		/* set the ptrace bit in the process flags. */
		current->ptrace |= PT_PTRACED;
		ret = 0;
		goto out;
	}
	ret = -ESRCH;
	read_lock(&tasklist_lock);
	child = find_task_by_pid(pid);
	if (child)
		get_task_struct(child);
	read_unlock(&tasklist_lock);
	if (!child)
		goto out;

	ret = -EPERM;
	if (pid == 1)		/* you may not mess 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;

	switch (request) {
		/* when I and D space are separate, these will need to be fixed. */
	case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
		ret = -EIO;
		break;
	}
out_tsk:
	put_task_struct(child);
out:
	unlock_kernel();
	return ret;
}

Loading