25
25
#include <linux/nmi.h>
26
26
#include <linux/ctype.h>
27
27
#include <linux/highmem.h>
28
+ #include <linux/security.h>
28
29
29
30
#include <asm/debugfs.h>
30
31
#include <asm/ptrace.h>
@@ -187,6 +188,8 @@ static void dump_tlb_44x(void);
187
188
static void dump_tlb_book3e (void );
188
189
#endif
189
190
191
+ static void clear_all_bpt (void );
192
+
190
193
#ifdef CONFIG_PPC64
191
194
#define REG "%.16lx"
192
195
#else
@@ -283,10 +286,38 @@ Commands:\n\
283
286
" U show uptime information\n"
284
287
" ? help\n"
285
288
" # 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"
288
291
;
289
292
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
+
290
321
static struct pt_regs * xmon_regs ;
291
322
292
323
static inline void sync (void )
@@ -438,7 +469,10 @@ static bool wait_for_other_cpus(int ncpus)
438
469
439
470
return false;
440
471
}
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
442
476
443
477
static inline int unrecoverable_excp (struct pt_regs * regs )
444
478
{
@@ -455,6 +489,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
455
489
int cmd = 0 ;
456
490
struct bpt * bp ;
457
491
long recurse_jmp [JMP_BUF_LEN ];
492
+ bool locked_down ;
458
493
unsigned long offset ;
459
494
unsigned long flags ;
460
495
#ifdef CONFIG_SMP
@@ -465,6 +500,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
465
500
local_irq_save (flags );
466
501
hard_irq_disable ();
467
502
503
+ locked_down = xmon_is_locked_down ();
504
+
468
505
if (!fromipi ) {
469
506
tracing_enabled = tracing_is_on ();
470
507
tracing_off ();
@@ -518,7 +555,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
518
555
519
556
if (!fromipi ) {
520
557
get_output_lock ();
521
- excprint (regs );
558
+ if (!locked_down )
559
+ excprint (regs );
522
560
if (bp ) {
523
561
printf ("cpu 0x%x stopped at breakpoint 0x%tx (" ,
524
562
cpu , BP_NUM (bp ));
@@ -570,10 +608,14 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
570
608
}
571
609
remove_bpts ();
572
610
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
+
577
619
mb ();
578
620
xmon_gate = 1 ;
579
621
barrier ();
@@ -597,8 +639,9 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
597
639
spin_cpu_relax ();
598
640
touch_nmi_watchdog ();
599
641
} else {
600
- cmd = cmds (regs );
601
- if (cmd != 0 ) {
642
+ if (!locked_down )
643
+ cmd = cmds (regs );
644
+ if (locked_down || cmd != 0 ) {
602
645
/* exiting xmon */
603
646
insert_bpts ();
604
647
xmon_gate = 0 ;
@@ -635,13 +678,16 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
635
678
"can't continue\n" );
636
679
remove_bpts ();
637
680
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
+ }
642
687
}
643
688
644
- cmd = cmds (regs );
689
+ if (!locked_down )
690
+ cmd = cmds (regs );
645
691
646
692
insert_bpts ();
647
693
in_xmon = 0 ;
@@ -670,7 +716,10 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
670
716
}
671
717
}
672
718
#endif
673
- insert_cpu_bpts ();
719
+ if (locked_down )
720
+ clear_all_bpt ();
721
+ else
722
+ insert_cpu_bpts ();
674
723
675
724
touch_nmi_watchdog ();
676
725
local_irq_restore (flags );
@@ -3768,6 +3817,11 @@ static void xmon_init(int enable)
3768
3817
#ifdef CONFIG_MAGIC_SYSRQ
3769
3818
static void sysrq_handle_xmon (int key )
3770
3819
{
3820
+ if (xmon_is_locked_down ()) {
3821
+ clear_all_bpt ();
3822
+ xmon_init (0 );
3823
+ return ;
3824
+ }
3771
3825
/* ensure xmon is enabled */
3772
3826
xmon_init (1 );
3773
3827
debugger (get_irq_regs ());
@@ -3789,7 +3843,6 @@ static int __init setup_xmon_sysrq(void)
3789
3843
device_initcall (setup_xmon_sysrq );
3790
3844
#endif /* CONFIG_MAGIC_SYSRQ */
3791
3845
3792
- #ifdef CONFIG_DEBUG_FS
3793
3846
static void clear_all_bpt (void )
3794
3847
{
3795
3848
int i ;
@@ -3807,18 +3860,22 @@ static void clear_all_bpt(void)
3807
3860
iabr = NULL ;
3808
3861
dabr .enabled = 0 ;
3809
3862
}
3810
-
3811
- printf ("xmon: All breakpoints cleared\n" );
3812
3863
}
3813
3864
3865
+ #ifdef CONFIG_DEBUG_FS
3814
3866
static int xmon_dbgfs_set (void * data , u64 val )
3815
3867
{
3816
3868
xmon_on = !!val ;
3817
3869
xmon_init (xmon_on );
3818
3870
3819
3871
/* make sure all breakpoints removed when disabling */
3820
- if (!xmon_on )
3872
+ if (!xmon_on ) {
3821
3873
clear_all_bpt ();
3874
+ get_output_lock ();
3875
+ printf ("xmon: All breakpoints cleared\n" );
3876
+ release_output_lock ();
3877
+ }
3878
+
3822
3879
return 0 ;
3823
3880
}
3824
3881
@@ -3844,7 +3901,11 @@ static int xmon_early __initdata;
3844
3901
3845
3902
static int __init early_parse_xmon (char * p )
3846
3903
{
3847
- if (!p || strncmp (p , "early" , 5 ) == 0 ) {
3904
+ if (xmon_is_locked_down ()) {
3905
+ xmon_init (0 );
3906
+ xmon_early = 0 ;
3907
+ xmon_on = 0 ;
3908
+ } else if (!p || strncmp (p , "early" , 5 ) == 0 ) {
3848
3909
/* just "xmon" is equivalent to "xmon=early" */
3849
3910
xmon_init (1 );
3850
3911
xmon_early = 1 ;
0 commit comments