2525#include <linux/nmi.h>
2626#include <linux/ctype.h>
2727#include <linux/highmem.h>
28+ #include <linux/security.h>
2829
2930#include <asm/debugfs.h>
3031#include <asm/ptrace.h>
@@ -187,6 +188,8 @@ static void dump_tlb_44x(void);
187188static void dump_tlb_book3e (void );
188189#endif
189190
191+ static void clear_all_bpt (void );
192+
190193#ifdef CONFIG_PPC64
191194#define REG "%.16lx"
192195#else
@@ -283,10 +286,38 @@ Commands:\n\
283286" U show uptime information\n"
284287" ? help\n"
285288" # n limit output to n lines per page (for dp, dpa, dl)\n"
286- " zr reboot\n\
287- zh halt\n"
289+ " zr reboot\n"
290+ " zh halt\n"
288291;
289292
293+ #ifdef CONFIG_SECURITY
294+ static bool xmon_is_locked_down (void )
295+ {
296+ static bool lockdown ;
297+
298+ if (!lockdown ) {
299+ lockdown = !!security_locked_down (LOCKDOWN_XMON_RW );
300+ if (lockdown ) {
301+ printf ("xmon: Disabled due to kernel lockdown\n" );
302+ xmon_is_ro = true;
303+ }
304+ }
305+
306+ if (!xmon_is_ro ) {
307+ xmon_is_ro = !!security_locked_down (LOCKDOWN_XMON_WR );
308+ if (xmon_is_ro )
309+ printf ("xmon: Read-only due to kernel lockdown\n" );
310+ }
311+
312+ return lockdown ;
313+ }
314+ #else /* CONFIG_SECURITY */
315+ static inline bool xmon_is_locked_down (void )
316+ {
317+ return false;
318+ }
319+ #endif
320+
290321static struct pt_regs * xmon_regs ;
291322
292323static inline void sync (void )
@@ -438,7 +469,10 @@ static bool wait_for_other_cpus(int ncpus)
438469
439470 return false;
440471}
441- #endif /* CONFIG_SMP */
472+ #else /* CONFIG_SMP */
473+ static inline void get_output_lock (void ) {}
474+ static inline void release_output_lock (void ) {}
475+ #endif
442476
443477static inline int unrecoverable_excp (struct pt_regs * regs )
444478{
@@ -455,6 +489,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
455489 int cmd = 0 ;
456490 struct bpt * bp ;
457491 long recurse_jmp [JMP_BUF_LEN ];
492+ bool locked_down ;
458493 unsigned long offset ;
459494 unsigned long flags ;
460495#ifdef CONFIG_SMP
@@ -465,6 +500,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
465500 local_irq_save (flags );
466501 hard_irq_disable ();
467502
503+ locked_down = xmon_is_locked_down ();
504+
468505 if (!fromipi ) {
469506 tracing_enabled = tracing_is_on ();
470507 tracing_off ();
@@ -518,7 +555,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
518555
519556 if (!fromipi ) {
520557 get_output_lock ();
521- excprint (regs );
558+ if (!locked_down )
559+ excprint (regs );
522560 if (bp ) {
523561 printf ("cpu 0x%x stopped at breakpoint 0x%tx (" ,
524562 cpu , BP_NUM (bp ));
@@ -570,10 +608,14 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
570608 }
571609 remove_bpts ();
572610 disable_surveillance ();
573- /* for breakpoint or single step, print the current instr. */
574- if (bp || TRAP (regs ) == 0xd00 )
575- ppc_inst_dump (regs -> nip , 1 , 0 );
576- printf ("enter ? for help\n" );
611+
612+ if (!locked_down ) {
613+ /* for breakpoint or single step, print curr insn */
614+ if (bp || TRAP (regs ) == 0xd00 )
615+ ppc_inst_dump (regs -> nip , 1 , 0 );
616+ printf ("enter ? for help\n" );
617+ }
618+
577619 mb ();
578620 xmon_gate = 1 ;
579621 barrier ();
@@ -597,8 +639,9 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
597639 spin_cpu_relax ();
598640 touch_nmi_watchdog ();
599641 } else {
600- cmd = cmds (regs );
601- if (cmd != 0 ) {
642+ if (!locked_down )
643+ cmd = cmds (regs );
644+ if (locked_down || cmd != 0 ) {
602645 /* exiting xmon */
603646 insert_bpts ();
604647 xmon_gate = 0 ;
@@ -635,13 +678,16 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
635678 "can't continue\n" );
636679 remove_bpts ();
637680 disable_surveillance ();
638- /* for breakpoint or single step, print the current instr. */
639- if (bp || TRAP (regs ) == 0xd00 )
640- ppc_inst_dump (regs -> nip , 1 , 0 );
641- printf ("enter ? for help\n" );
681+ if (!locked_down ) {
682+ /* for breakpoint or single step, print current insn */
683+ if (bp || TRAP (regs ) == 0xd00 )
684+ ppc_inst_dump (regs -> nip , 1 , 0 );
685+ printf ("enter ? for help\n" );
686+ }
642687 }
643688
644- cmd = cmds (regs );
689+ if (!locked_down )
690+ cmd = cmds (regs );
645691
646692 insert_bpts ();
647693 in_xmon = 0 ;
@@ -670,7 +716,10 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
670716 }
671717 }
672718#endif
673- insert_cpu_bpts ();
719+ if (locked_down )
720+ clear_all_bpt ();
721+ else
722+ insert_cpu_bpts ();
674723
675724 touch_nmi_watchdog ();
676725 local_irq_restore (flags );
@@ -3761,6 +3810,11 @@ static void xmon_init(int enable)
37613810#ifdef CONFIG_MAGIC_SYSRQ
37623811static void sysrq_handle_xmon (int key )
37633812{
3813+ if (xmon_is_locked_down ()) {
3814+ clear_all_bpt ();
3815+ xmon_init (0 );
3816+ return ;
3817+ }
37643818 /* ensure xmon is enabled */
37653819 xmon_init (1 );
37663820 debugger (get_irq_regs ());
@@ -3782,7 +3836,6 @@ static int __init setup_xmon_sysrq(void)
37823836device_initcall (setup_xmon_sysrq );
37833837#endif /* CONFIG_MAGIC_SYSRQ */
37843838
3785- #ifdef CONFIG_DEBUG_FS
37863839static void clear_all_bpt (void )
37873840{
37883841 int i ;
@@ -3800,18 +3853,22 @@ static void clear_all_bpt(void)
38003853 iabr = NULL ;
38013854 dabr .enabled = 0 ;
38023855 }
3803-
3804- printf ("xmon: All breakpoints cleared\n" );
38053856}
38063857
3858+ #ifdef CONFIG_DEBUG_FS
38073859static int xmon_dbgfs_set (void * data , u64 val )
38083860{
38093861 xmon_on = !!val ;
38103862 xmon_init (xmon_on );
38113863
38123864 /* make sure all breakpoints removed when disabling */
3813- if (!xmon_on )
3865+ if (!xmon_on ) {
38143866 clear_all_bpt ();
3867+ get_output_lock ();
3868+ printf ("xmon: All breakpoints cleared\n" );
3869+ release_output_lock ();
3870+ }
3871+
38153872 return 0 ;
38163873}
38173874
@@ -3837,7 +3894,11 @@ static int xmon_early __initdata;
38373894
38383895static int __init early_parse_xmon (char * p )
38393896{
3840- if (!p || strncmp (p , "early" , 5 ) == 0 ) {
3897+ if (xmon_is_locked_down ()) {
3898+ xmon_init (0 );
3899+ xmon_early = 0 ;
3900+ xmon_on = 0 ;
3901+ } else if (!p || strncmp (p , "early" , 5 ) == 0 ) {
38413902 /* just "xmon" is equivalent to "xmon=early" */
38423903 xmon_init (1 );
38433904 xmon_early = 1 ;
0 commit comments