powerpc/xmon: add read-only mode
Operations which write to memory and special purpose registers should be restricted on systems with integrity guarantees (such as Secure Boot) and, optionally, to avoid self-destructive behaviors. Add a config option, XMON_DEFAULT_RO_MODE, to set default xmon behavior. The kernel cmdline options xmon=ro and xmon=rw override this default. The following xmon operations are affected: memops: disable memmove disable memset disable memzcan memex: no-op'd mwrite super_regs: no-op'd write_spr bpt_cmds: disable proc_call: disable Signed-off-by: Christopher M. Riedl <cmr@informatik.wtf> Reviewed-by: Oliver O'Halloran <oohall@gmail.com> Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
5d085ec04a
commit
0acb5f6456
|
@ -117,6 +117,14 @@ config XMON_DISASSEMBLY
|
||||||
to say Y here, unless you're building for a memory-constrained
|
to say Y here, unless you're building for a memory-constrained
|
||||||
system.
|
system.
|
||||||
|
|
||||||
|
config XMON_DEFAULT_RO_MODE
|
||||||
|
bool "Restrict xmon to read-only operations by default"
|
||||||
|
depends on XMON
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Operate xmon in read-only mode. The cmdline options 'xmon=rw' and
|
||||||
|
'xmon=ro' override this default.
|
||||||
|
|
||||||
config DEBUGGER
|
config DEBUGGER
|
||||||
bool
|
bool
|
||||||
depends on KGDB || XMON
|
depends on KGDB || XMON
|
||||||
|
|
|
@ -80,6 +80,7 @@ static int set_indicator_token = RTAS_UNKNOWN_SERVICE;
|
||||||
#endif
|
#endif
|
||||||
static unsigned long in_xmon __read_mostly = 0;
|
static unsigned long in_xmon __read_mostly = 0;
|
||||||
static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT);
|
static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT);
|
||||||
|
static bool xmon_is_ro = IS_ENABLED(CONFIG_XMON_DEFAULT_RO_MODE);
|
||||||
|
|
||||||
static unsigned long adrs;
|
static unsigned long adrs;
|
||||||
static int size = 1;
|
static int size = 1;
|
||||||
|
@ -202,6 +203,8 @@ static void dump_tlb_book3e(void);
|
||||||
#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
|
#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const char *xmon_ro_msg = "Operation disabled: xmon in read-only mode\n";
|
||||||
|
|
||||||
static char *help_string = "\
|
static char *help_string = "\
|
||||||
Commands:\n\
|
Commands:\n\
|
||||||
b show breakpoints\n\
|
b show breakpoints\n\
|
||||||
|
@ -989,6 +992,10 @@ cmds(struct pt_regs *excp)
|
||||||
memlocate();
|
memlocate();
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
|
if (xmon_is_ro) {
|
||||||
|
printf(xmon_ro_msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
memzcan();
|
memzcan();
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
|
@ -1042,6 +1049,10 @@ cmds(struct pt_regs *excp)
|
||||||
set_lpp_cmd();
|
set_lpp_cmd();
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
|
if (xmon_is_ro) {
|
||||||
|
printf(xmon_ro_msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
bpt_cmds();
|
bpt_cmds();
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
|
@ -1055,6 +1066,10 @@ cmds(struct pt_regs *excp)
|
||||||
bootcmds();
|
bootcmds();
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
|
if (xmon_is_ro) {
|
||||||
|
printf(xmon_ro_msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
proccall();
|
proccall();
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
|
@ -1777,6 +1792,11 @@ read_spr(int n, unsigned long *vp)
|
||||||
static void
|
static void
|
||||||
write_spr(int n, unsigned long val)
|
write_spr(int n, unsigned long val)
|
||||||
{
|
{
|
||||||
|
if (xmon_is_ro) {
|
||||||
|
printf(xmon_ro_msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (setjmp(bus_error_jmp) == 0) {
|
if (setjmp(bus_error_jmp) == 0) {
|
||||||
catch_spr_faults = 1;
|
catch_spr_faults = 1;
|
||||||
sync();
|
sync();
|
||||||
|
@ -2016,6 +2036,12 @@ mwrite(unsigned long adrs, void *buf, int size)
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
|
if (xmon_is_ro) {
|
||||||
|
printf(xmon_ro_msg);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
if (setjmp(bus_error_jmp) == 0) {
|
if (setjmp(bus_error_jmp) == 0) {
|
||||||
catch_memory_errors = 1;
|
catch_memory_errors = 1;
|
||||||
sync();
|
sync();
|
||||||
|
@ -2880,9 +2906,17 @@ memops(int cmd)
|
||||||
scanhex((void *)&mcount);
|
scanhex((void *)&mcount);
|
||||||
switch( cmd ){
|
switch( cmd ){
|
||||||
case 'm':
|
case 'm':
|
||||||
|
if (xmon_is_ro) {
|
||||||
|
printf(xmon_ro_msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
memmove((void *)mdest, (void *)msrc, mcount);
|
memmove((void *)mdest, (void *)msrc, mcount);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
|
if (xmon_is_ro) {
|
||||||
|
printf(xmon_ro_msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
memset((void *)mdest, mval, mcount);
|
memset((void *)mdest, mval, mcount);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
|
@ -3792,6 +3826,14 @@ static int __init early_parse_xmon(char *p)
|
||||||
} else if (strncmp(p, "on", 2) == 0) {
|
} else if (strncmp(p, "on", 2) == 0) {
|
||||||
xmon_init(1);
|
xmon_init(1);
|
||||||
xmon_on = 1;
|
xmon_on = 1;
|
||||||
|
} else if (strncmp(p, "rw", 2) == 0) {
|
||||||
|
xmon_init(1);
|
||||||
|
xmon_on = 1;
|
||||||
|
xmon_is_ro = false;
|
||||||
|
} else if (strncmp(p, "ro", 2) == 0) {
|
||||||
|
xmon_init(1);
|
||||||
|
xmon_on = 1;
|
||||||
|
xmon_is_ro = true;
|
||||||
} else if (strncmp(p, "off", 3) == 0)
|
} else if (strncmp(p, "off", 3) == 0)
|
||||||
xmon_on = 0;
|
xmon_on = 0;
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue