Skip to content

Commit

Permalink
kgdb, x86, arm, mips, powerpc: ignore user space single stepping
Browse files Browse the repository at this point in the history
On the x86 arch, user space single step exceptions should be ignored
if they occur in the kernel space, such as ptrace stepping through a
system call.

First check if it is kgdb that is executing a single step, then ensure
it is not an accidental traversal into the user space, while in kgdb,
any other time the TIF_SINGLESTEP is set, kgdb should ignore the
exception.

On x86, arm, mips and powerpc, the kgdb_contthread usage was
inconsistent with the way single stepping is implemented in the kgdb
core.  The arch specific stub should always set the
kgdb_cpu_doing_single_step correctly if it is single stepping.  This
allows kgdb to correctly process an instruction steps if ptrace
happens to be requesting an instruction step over a system call.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
  • Loading branch information
Jason Wessel committed Sep 26, 2008
1 parent 18d6522 commit d7161a6
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 18 deletions.
2 changes: 0 additions & 2 deletions arch/arm/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
case 'D':
case 'k':
case 'c':
kgdb_contthread = NULL;

/*
* Try to read optional parameter, pc unchanged if no parm.
* If this was a compiled breakpoint, we need to move
Expand Down
3 changes: 1 addition & 2 deletions arch/mips/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,

atomic_set(&kgdb_cpu_doing_single_step, -1);
if (remcom_in_buffer[0] == 's')
if (kgdb_contthread)
atomic_set(&kgdb_cpu_doing_single_step, cpu);
atomic_set(&kgdb_cpu_doing_single_step, cpu);

return 0;
}
Expand Down
5 changes: 2 additions & 3 deletions arch/powerpc/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,8 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
linux_regs->msr |= MSR_SE;
#endif
kgdb_single_step = 1;
if (kgdb_contthread)
atomic_set(&kgdb_cpu_doing_single_step,
raw_smp_processor_id());
atomic_set(&kgdb_cpu_doing_single_step,
raw_smp_processor_id());
}
return 0;
}
Expand Down
18 changes: 11 additions & 7 deletions arch/x86/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,10 +378,8 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
if (remcomInBuffer[0] == 's') {
linux_regs->flags |= X86_EFLAGS_TF;
kgdb_single_step = 1;
if (kgdb_contthread) {
atomic_set(&kgdb_cpu_doing_single_step,
raw_smp_processor_id());
}
atomic_set(&kgdb_cpu_doing_single_step,
raw_smp_processor_id());
}

get_debugreg(dr6, 6);
Expand Down Expand Up @@ -466,9 +464,15 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)

case DIE_DEBUG:
if (atomic_read(&kgdb_cpu_doing_single_step) ==
raw_smp_processor_id() &&
user_mode(regs))
return single_step_cont(regs, args);
raw_smp_processor_id()) {
if (user_mode(regs))
return single_step_cont(regs, args);
break;
} else if (test_thread_flag(TIF_SINGLESTEP))
/* This means a user thread is single stepping
* a system call which should be ignored
*/
return NOTIFY_DONE;
/* fall through */
default:
if (user_mode(regs))
Expand Down
8 changes: 4 additions & 4 deletions kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
* Get the passive CPU lock which will hold all the non-primary
* CPU in a spin state while the debugger is active
*/
if (!kgdb_single_step || !kgdb_contthread) {
if (!kgdb_single_step) {
for (i = 0; i < NR_CPUS; i++)
atomic_set(&passive_cpu_wait[i], 1);
}
Expand All @@ -1475,7 +1475,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)

#ifdef CONFIG_SMP
/* Signal the other CPUs to enter kgdb_wait() */
if ((!kgdb_single_step || !kgdb_contthread) && kgdb_do_roundup)
if ((!kgdb_single_step) && kgdb_do_roundup)
kgdb_roundup_cpus(flags);
#endif

Expand All @@ -1494,7 +1494,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code);
kgdb_deactivate_sw_breakpoints();
kgdb_single_step = 0;
kgdb_contthread = NULL;
kgdb_contthread = current;
exception_level = 0;

/* Talk to debugger with gdbserial protocol */
Expand All @@ -1508,7 +1508,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
kgdb_info[ks->cpu].task = NULL;
atomic_set(&cpu_in_kgdb[ks->cpu], 0);

if (!kgdb_single_step || !kgdb_contthread) {
if (!kgdb_single_step) {
for (i = NR_CPUS-1; i >= 0; i--)
atomic_set(&passive_cpu_wait[i], 0);
/*
Expand Down

0 comments on commit d7161a6

Please sign in to comment.