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

Commit d7161a65 authored by Jason Wessel's avatar Jason Wessel
Browse files

kgdb, x86, arm, mips, powerpc: ignore user space single stepping



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: default avatarJason Wessel <jason.wessel@windriver.com>
parent 18d6522b
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -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
+1 −2
Original line number Diff line number Diff line
@@ -236,7 +236,6 @@ 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);

		return 0;
+2 −3
Original line number Diff line number Diff line
@@ -347,7 +347,6 @@ 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());
		}
+11 −7
Original line number Diff line number Diff line
@@ -378,11 +378,9 @@ 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());
		}
		}

		get_debugreg(dr6, 6);
		if (!(dr6 & 0x4000)) {
@@ -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))
		    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))
+4 −4
Original line number Diff line number Diff line
@@ -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);
	}
@@ -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

@@ -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 */
@@ -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);
		/*