Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: Jason Wessel <jason.wessel@windriver.com>

+18 -18
-2
arch/arm/kernel/kgdb.c
··· 111 111 case 'D': 112 112 case 'k': 113 113 case 'c': 114 - kgdb_contthread = NULL; 115 - 116 114 /* 117 115 * Try to read optional parameter, pc unchanged if no parm. 118 116 * If this was a compiled breakpoint, we need to move
+1 -2
arch/mips/kernel/kgdb.c
··· 236 236 237 237 atomic_set(&kgdb_cpu_doing_single_step, -1); 238 238 if (remcom_in_buffer[0] == 's') 239 - if (kgdb_contthread) 240 - atomic_set(&kgdb_cpu_doing_single_step, cpu); 239 + atomic_set(&kgdb_cpu_doing_single_step, cpu); 241 240 242 241 return 0; 243 242 }
+2 -3
arch/powerpc/kernel/kgdb.c
··· 347 347 linux_regs->msr |= MSR_SE; 348 348 #endif 349 349 kgdb_single_step = 1; 350 - if (kgdb_contthread) 351 - atomic_set(&kgdb_cpu_doing_single_step, 352 - raw_smp_processor_id()); 350 + atomic_set(&kgdb_cpu_doing_single_step, 351 + raw_smp_processor_id()); 353 352 } 354 353 return 0; 355 354 }
+11 -7
arch/x86/kernel/kgdb.c
··· 378 378 if (remcomInBuffer[0] == 's') { 379 379 linux_regs->flags |= X86_EFLAGS_TF; 380 380 kgdb_single_step = 1; 381 - if (kgdb_contthread) { 382 - atomic_set(&kgdb_cpu_doing_single_step, 383 - raw_smp_processor_id()); 384 - } 381 + atomic_set(&kgdb_cpu_doing_single_step, 382 + raw_smp_processor_id()); 385 383 } 386 384 387 385 get_debugreg(dr6, 6); ··· 464 466 465 467 case DIE_DEBUG: 466 468 if (atomic_read(&kgdb_cpu_doing_single_step) == 467 - raw_smp_processor_id() && 468 - user_mode(regs)) 469 - return single_step_cont(regs, args); 469 + raw_smp_processor_id()) { 470 + if (user_mode(regs)) 471 + return single_step_cont(regs, args); 472 + break; 473 + } else if (test_thread_flag(TIF_SINGLESTEP)) 474 + /* This means a user thread is single stepping 475 + * a system call which should be ignored 476 + */ 477 + return NOTIFY_DONE; 470 478 /* fall through */ 471 479 default: 472 480 if (user_mode(regs))
+4 -4
kernel/kgdb.c
··· 1462 1462 * Get the passive CPU lock which will hold all the non-primary 1463 1463 * CPU in a spin state while the debugger is active 1464 1464 */ 1465 - if (!kgdb_single_step || !kgdb_contthread) { 1465 + if (!kgdb_single_step) { 1466 1466 for (i = 0; i < NR_CPUS; i++) 1467 1467 atomic_set(&passive_cpu_wait[i], 1); 1468 1468 } ··· 1475 1475 1476 1476 #ifdef CONFIG_SMP 1477 1477 /* Signal the other CPUs to enter kgdb_wait() */ 1478 - if ((!kgdb_single_step || !kgdb_contthread) && kgdb_do_roundup) 1478 + if ((!kgdb_single_step) && kgdb_do_roundup) 1479 1479 kgdb_roundup_cpus(flags); 1480 1480 #endif 1481 1481 ··· 1494 1494 kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code); 1495 1495 kgdb_deactivate_sw_breakpoints(); 1496 1496 kgdb_single_step = 0; 1497 - kgdb_contthread = NULL; 1497 + kgdb_contthread = current; 1498 1498 exception_level = 0; 1499 1499 1500 1500 /* Talk to debugger with gdbserial protocol */ ··· 1508 1508 kgdb_info[ks->cpu].task = NULL; 1509 1509 atomic_set(&cpu_in_kgdb[ks->cpu], 0); 1510 1510 1511 - if (!kgdb_single_step || !kgdb_contthread) { 1511 + if (!kgdb_single_step) { 1512 1512 for (i = NR_CPUS-1; i >= 0; i--) 1513 1513 atomic_set(&passive_cpu_wait[i], 0); 1514 1514 /*