patch-2.1.23 linux/arch/ppc/kernel/ptrace.c
Next file: linux/arch/ppc/kernel/signal.c
Previous file: linux/arch/ppc/kernel/process.c
Back to the patch index
Back to the overall index
- Lines: 274
- Date:
Sun Jan 26 12:07:05 1997
- Orig file:
v2.1.22/linux/arch/ppc/kernel/ptrace.c
- Orig date:
Wed Dec 18 15:58:43 1996
diff -u --recursive --new-file v2.1.22/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
@@ -18,6 +18,8 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
@@ -376,34 +378,37 @@
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
- struct user * dummy;
-
- dummy = NULL;
+ struct user * dummy = NULL;
+ int ret = -EPERM;
+ lock_kernel();
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->flags & PF_PTRACED)
- return -EPERM;
+ goto out;
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
- return 0;
+ ret = 0;
+ goto out;
}
if (pid == 1) /* you may not mess with init */
- return -EPERM;
+ goto out;
+ ret = -ESRCH;
if (!(child = get_task(pid)))
- return -ESRCH;
+ goto out;
+ ret = -EPERM;
if (request == PTRACE_ATTACH) {
if (child == current)
- return -EPERM;
+ goto out;
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->gid)) && !suser())
- return -EPERM;
+ goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
- return -EPERM;
+ goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
@@ -411,73 +416,75 @@
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
- return 0;
+ ret = 0;
+ goto out;
}
+ ret = -ESRCH;
if (!(child->flags & PF_PTRACED))
- return -ESRCH;
+ goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
- return -ESRCH;
+ goto out;
}
if (child->p_pptr != current)
- return -ESRCH;
+ goto out;
switch (request) {
/* If I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
- int res;
- res = read_long(child, addr, &tmp);
- if (res < 0)
- return res;
- res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
- if (!res)
+ ret = read_long(child, addr, &tmp);
+ if (ret < 0)
+ goto out;
+ ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
+ if (!ret)
put_user(tmp, (unsigned long *) data);
- return res;
+ goto out;
}
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
- int res;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO;
- res = verify_area(VERIFY_WRITE, (void *) data,
+ ret = verify_area(VERIFY_WRITE, (void *) data,
sizeof(long));
- if (res)
- return res;
+ if (ret)
+ goto out;
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
- if (addr < PT_FPR0) {
+ if (addr < PT_FPR0)
tmp = get_reg(child, addr);
- }
#if 0
else if (addr >= PT_FPR0 && addr < PT_FPR31)
tmp = child->tss.fpr[addr - PT_FPR0];
#endif
else
- return -EIO;
- put_user(tmp,(unsigned long *) data);
- return 0;
+ ret = -EIO;
+ if(!ret)
+ put_user(tmp,(unsigned long *) data);
+ goto out;
}
/* If I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- return write_long(child,addr,data);
+ ret = write_long(child,addr,data);
+ goto out;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- return -EIO;
+ goto out;
addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_R3)
- return -EIO;
+ goto out;
#if 0 /* Let this check be in 'put_reg' */
if (addr == PT_SR) {
data &= SR_MASK;
@@ -487,22 +494,24 @@
#endif
if (addr < PT_FPR0) {
if (put_reg(child, addr, data))
- return -EIO;
- return 0;
+ goto out;
+ ret = 0;
+ goto out;
}
#if 0
- if (addr >= 21 && addr < 48)
- {
+ if (addr >= 21 && addr < 48) {
child->tss.fp[addr - 21] = data;
- return 0;
+ ret = 0;
+ goto out;
}
#endif
- return -EIO;
+ goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
@@ -511,7 +520,8 @@
wake_up_process(child);
/* make sure the single step bit is not set. */
clear_single_step(child);
- return 0;
+ ret = 0;
+ goto out;
}
/*
@@ -520,29 +530,33 @@
* exit.
*/
case PTRACE_KILL: {
+ ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */
- return 0;
+ goto out;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
clear_single_step(child);
- return 0;
+ goto out;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
child->flags &= ~PF_TRACESYS;
set_single_step(child);
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
- return 0;
+ ret = 0;
+ goto out;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
+ ret = -EIO;
if ((unsigned long) data >= NSIG)
- return -EIO;
+ goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
@@ -551,19 +565,25 @@
SET_LINKS(child);
/* make sure the single step bit is not set. */
clear_single_step(child);
- return 0;
+ ret = 0;
+ goto out;
}
default:
- return -EIO;
+ ret = -EIO;
+ goto out;
}
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage void syscall_trace(void)
{
+ lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
- return;
+ goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current);
@@ -576,5 +596,6 @@
if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0;
- return;
+out:
+ unlock_kernel();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov