mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
BACKPORT: fiq_debugger: restrict access to critical commands.
Sysrq must be enabled via /proc/sys/kernel/sysrq as a security measure to enable various critical fiq debugger commands that either leak information or can be used as a system attack. Default disabled, this will leave the reboot, reset, irqs, sleep, nosleep, console and ps commands. Reboot and reset commands will be restricted from taking any parameters. We will also switch to showing the limited command set in this mode. Signed-off-by: Mark Salyzyn <salyzyn@google.com> Bug: 32402555 [d-cagle@codeaurora.org: Resolve merge conflict] Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 1031836c0895f1f5a05c25efec83bfa11aa08ca9 Signed-off-by: Dennis Cagle <d-cagle@codeaurora.org> Backport reference: * Adapted for arch/arm/common/fiq_debugger.c * Adapt to the old use of debug_printf Change-Id: I0a6aecd9b3d5bd62db06beac76682349854198d7 Signed-off-by: Adrian DC <radian.dc@gmail.com> CVE-2017-0510 Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
parent
983c575421
commit
065dbe59f8
3 changed files with 62 additions and 33 deletions
|
@ -29,6 +29,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
|
@ -600,12 +601,13 @@ static void debug_work(struct work_struct *work)
|
|||
cmd += 6;
|
||||
while (*cmd == ' ')
|
||||
cmd++;
|
||||
if (cmd != '\0')
|
||||
if ((cmd != '\0') && sysrq_on())
|
||||
kernel_restart(cmd);
|
||||
else
|
||||
kernel_restart(NULL);
|
||||
} else {
|
||||
debug_printf(state, "unknown work command '%s'\n", work_cmd);
|
||||
debug_printf(state, "unknown work command '%s'\n",
|
||||
work_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -628,26 +630,40 @@ static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd)
|
|||
|
||||
static void debug_help(struct fiq_debugger_state *state)
|
||||
{
|
||||
debug_printf(state, "FIQ Debugger commands:\n"
|
||||
" pc PC status\n"
|
||||
" regs Register dump\n"
|
||||
" allregs Extended Register dump\n"
|
||||
" bt Stack trace\n"
|
||||
" reboot [<c>] Reboot with command <c>\n"
|
||||
" reset [<c>] Hard reset with command <c>\n"
|
||||
" irqs Interupt status\n"
|
||||
" kmsg Kernel log\n"
|
||||
" version Kernel version\n");
|
||||
debug_printf(state, " sleep Allow sleep while in FIQ\n"
|
||||
" nosleep Disable sleep while in FIQ\n"
|
||||
" console Switch terminal to console\n"
|
||||
" cpu Current CPU\n"
|
||||
" cpu <number> Switch to CPU<number>\n");
|
||||
debug_printf(state, " ps Process list\n"
|
||||
" sysrq sysrq options\n"
|
||||
" sysrq <param> Execute sysrq with <param>\n");
|
||||
debug_printf(state,
|
||||
"FIQ Debugger commands:\n");
|
||||
if (sysrq_on()) {
|
||||
debug_printf(state,
|
||||
" pc PC status\n"
|
||||
" regs Register dump\n"
|
||||
" allregs Extended Register dump\n"
|
||||
" bt Stack trace\n");
|
||||
debug_printf(state,
|
||||
" reboot [<c>] Reboot with command <c>\n"
|
||||
" reset [<c>] Hard reset with command <c>\n"
|
||||
" irqs Interrupt status\n"
|
||||
" kmsg Kernel log\n"
|
||||
" version Kernel version\n");
|
||||
debug_printf(state,
|
||||
" cpu Current CPU\n"
|
||||
" cpu <number> Switch to CPU<number>\n"
|
||||
" sysrq sysrq options\n"
|
||||
" sysrq <param> Execute sysrq with <param>\n");
|
||||
} else {
|
||||
debug_printf(state,
|
||||
" reboot Reboot\n"
|
||||
" reset Hard reset\n"
|
||||
" irqs Interrupt status\n");
|
||||
}
|
||||
debug_printf(state,
|
||||
" sleep Allow sleep while in FIQ\n"
|
||||
" nosleep Disable sleep while in FIQ\n"
|
||||
" console Switch terminal to console\n"
|
||||
" ps Process list\n");
|
||||
#ifdef CONFIG_KGDB
|
||||
debug_printf(state, " kgdb Enter kernel debugger\n");
|
||||
if (fiq_kgdb_enable) {
|
||||
debug_printf(state,
|
||||
" kgdb Enter kernel debugger\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -677,19 +693,24 @@ static bool debug_fiq_exec(struct fiq_debugger_state *state,
|
|||
if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) {
|
||||
debug_help(state);
|
||||
} else if (!strcmp(cmd, "pc")) {
|
||||
debug_printf(state, " pc %08x cpsr %08x mode %s\n",
|
||||
regs[15], regs[16], mode_name(regs[16]));
|
||||
if (sysrq_on())
|
||||
debug_printf(state, " pc %08x cpsr %08x mode %s\n",
|
||||
regs[15], regs[16], mode_name(regs[16]));
|
||||
} else if (!strcmp(cmd, "regs")) {
|
||||
dump_regs(state, regs);
|
||||
if (sysrq_on())
|
||||
dump_regs(state, regs);
|
||||
} else if (!strcmp(cmd, "allregs")) {
|
||||
dump_allregs(state, regs);
|
||||
if (sysrq_on())
|
||||
dump_allregs(state, regs);
|
||||
} else if (!strcmp(cmd, "bt")) {
|
||||
dump_stacktrace(state, (struct pt_regs *)regs, 100, svc_sp);
|
||||
if (sysrq_on())
|
||||
dump_stacktrace(state, (struct pt_regs *)regs,
|
||||
100, svc_sp);
|
||||
} else if (!strncmp(cmd, "reset", 5)) {
|
||||
cmd += 5;
|
||||
while (*cmd == ' ')
|
||||
cmd++;
|
||||
if (*cmd) {
|
||||
if (*cmd && sysrq_on()) {
|
||||
char tmp_cmd[32];
|
||||
strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd));
|
||||
machine_restart(tmp_cmd);
|
||||
|
@ -699,9 +720,12 @@ static bool debug_fiq_exec(struct fiq_debugger_state *state,
|
|||
} else if (!strcmp(cmd, "irqs")) {
|
||||
dump_irqs(state);
|
||||
} else if (!strcmp(cmd, "kmsg")) {
|
||||
dump_kernel_log(state);
|
||||
if (sysrq_on())
|
||||
dump_kernel_log(state);
|
||||
} else if (!strcmp(cmd, "version")) {
|
||||
debug_printf(state, "%s\n", linux_banner);
|
||||
if (sysrq_on())
|
||||
debug_printf(state, "%s\n",
|
||||
linux_banner);
|
||||
} else if (!strcmp(cmd, "sleep")) {
|
||||
state->no_sleep = false;
|
||||
debug_printf(state, "enabling sleep\n");
|
||||
|
@ -713,14 +737,17 @@ static bool debug_fiq_exec(struct fiq_debugger_state *state,
|
|||
debug_uart_flush(state);
|
||||
state->console_enable = true;
|
||||
} else if (!strcmp(cmd, "cpu")) {
|
||||
debug_printf(state, "cpu %d\n", state->current_cpu);
|
||||
} else if (!strncmp(cmd, "cpu ", 4)) {
|
||||
if (sysrq_on())
|
||||
debug_printf(state, "cpu %d\n",
|
||||
state->current_cpu);
|
||||
} else if (!strncmp(cmd, "cpu ", 4) && sysrq_on()) {
|
||||
unsigned long cpu = 0;
|
||||
if (strict_strtoul(cmd + 4, 10, &cpu) == 0)
|
||||
switch_cpu(state, cpu);
|
||||
else
|
||||
debug_printf(state, "invalid cpu\n");
|
||||
debug_printf(state, "cpu %d\n", state->current_cpu);
|
||||
debug_printf(state, "cpu %d\n",
|
||||
state->current_cpu);
|
||||
} else {
|
||||
if (state->debug_busy) {
|
||||
debug_printf(state,
|
||||
|
|
|
@ -49,10 +49,11 @@
|
|||
static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
|
||||
static bool __read_mostly sysrq_always_enabled;
|
||||
|
||||
static bool sysrq_on(void)
|
||||
bool sysrq_on(void)
|
||||
{
|
||||
return sysrq_enabled || sysrq_always_enabled;
|
||||
}
|
||||
EXPORT_SYMBOL(sysrq_on);
|
||||
|
||||
/*
|
||||
* A value of 1 means 'all', other nonzero values are an op mask:
|
||||
|
|
|
@ -45,6 +45,7 @@ struct sysrq_key_op {
|
|||
* are available -- else NULL's).
|
||||
*/
|
||||
|
||||
bool sysrq_on(void);
|
||||
void handle_sysrq(int key);
|
||||
void __handle_sysrq(int key, bool check_mask);
|
||||
int register_sysrq_key(int key, struct sysrq_key_op *op);
|
||||
|
|
Loading…
Reference in a new issue