Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 75
b: refs/heads/master
c: aa85b9a
h: refs/heads/master
i:
  73: 72d6cd0
  71: 7d40d27
v: v3
  • Loading branch information
Andi Kleen authored and Linus Torvalds committed Apr 16, 2005
1 parent 5253ff8 commit 8a5ab84
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b6d9a5d81c6159ad651b5c6bb9223d14e33d8033
refs/heads/master: aa85b9af5bdae1f8b84d80367324e4410c3f0674
79 changes: 50 additions & 29 deletions trunk/arch/x86_64/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ static inline unsigned long get_stack_long(struct task_struct *task, int offset)
return (*((unsigned long *)stack));
}

static inline struct pt_regs *get_child_regs(struct task_struct *task)
{
struct pt_regs *regs = (void *)task->thread.rsp0;
return regs - 1;
}

/*
* this routine will put a word on the processes privileged stack.
* the offset is how far from the base addr as stored in the TSS.
Expand All @@ -80,18 +86,50 @@ static inline long put_stack_long(struct task_struct *task, int offset,
return 0;
}

static void set_singlestep(struct task_struct *child)
{
struct pt_regs *regs = get_child_regs(child);

/*
* Always set TIF_SINGLESTEP - this guarantees that
* we single-step system calls etc.. This will also
* cause us to set TF when returning to user mode.
*/
set_tsk_thread_flag(child, TIF_SINGLESTEP);

/*
* If TF was already set, don't do anything else
*/
if (regs->eflags & TRAP_FLAG)
return;

/* Set TF on the kernel stack.. */
regs->eflags |= TRAP_FLAG;

child->ptrace |= PT_DTRACE;
}

static void clear_singlestep(struct task_struct *child)
{
/* Always clear TIF_SINGLESTEP... */
clear_tsk_thread_flag(child, TIF_SINGLESTEP);

/* But touch TF only if it was set by us.. */
if (child->ptrace & PT_DTRACE) {
struct pt_regs *regs = get_child_regs(child);
regs->eflags &= ~TRAP_FLAG;
child->ptrace &= ~PT_DTRACE;
}
}

/*
* Called by kernel/ptrace.c when detaching..
*
* Make sure the single step bit is not set.
*/
void ptrace_disable(struct task_struct *child)
{
long tmp;

clear_tsk_thread_flag(child, TIF_SINGLESTEP);
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
clear_singlestep(child);
}

static int putreg(struct task_struct *child,
Expand Down Expand Up @@ -338,8 +376,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
}
break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
long tmp;
case PTRACE_CONT: /* restart after signal. */

ret = -EIO;
if ((unsigned long) data > _NSIG)
Expand All @@ -350,14 +387,11 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = data;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET);
tmp &= ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET,tmp);
/* make sure the single step bit is not set. */
clear_singlestep(child);
wake_up_process(child);
ret = 0;
break;
}

#ifdef CONFIG_IA32_EMULATION
/* This makes only sense with 32bit programs. Allow a
Expand Down Expand Up @@ -394,41 +428,28 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
long tmp;

case PTRACE_KILL:
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
clear_singlestep(child);
wake_up_process(child);
break;
}

case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp;

case PTRACE_SINGLESTEP: /* set the trap flag. */
ret = -EIO;
if ((unsigned long) data > _NSIG)
break;
clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
if ((child->ptrace & PT_DTRACE) == 0) {
/* Spurious delayed TF traps may occur */
child->ptrace |= PT_DTRACE;
}
tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
set_tsk_thread_flag(child, TIF_SINGLESTEP);
set_singlestep(child);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
ret = 0;
break;
}

case PTRACE_DETACH:
/* detach a process that was attached. */
Expand Down

0 comments on commit 8a5ab84

Please sign in to comment.