Commit a66f2e57 authored by Eugeniy Paltsev's avatar Eugeniy Paltsev Committed by Vineet Gupta

ARC: U-boot: check arguments paranoidly

Handle U-boot arguments paranoidly:
 * don't allow to pass unknown tag.
 * try to use external device tree blob only if corresponding tag
   (TAG_DTB) is set.
 * don't check uboot_tag if kernel build with no ARC_UBOOT_SUPPORT.

NOTE:
If U-boot args are invalid we skip them and try to use embedded device
tree blob. We can't panic on invalid U-boot args as we really pass
invalid args due to bug in U-boot code.
This happens if we don't provide external DTB to U-boot and
don't set 'bootargs' U-boot environment variable (which is default
case at least for HSDK board) In that case we will pass
{r0 = 1 (bootargs in r2); r1 = 0; r2 = 0;} to linux which is invalid.

While I'm at it refactor U-boot arguments handling code.

Cc: stable@vger.kernel.org
Tested-by: default avatarCorentin LABBE <clabbe@baylibre.com>
Signed-off-by: default avatarEugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent e494239a
...@@ -103,9 +103,9 @@ ENTRY(stext) ...@@ -103,9 +103,9 @@ ENTRY(stext)
#ifdef CONFIG_ARC_UBOOT_SUPPORT #ifdef CONFIG_ARC_UBOOT_SUPPORT
; Uboot - kernel ABI ; Uboot - kernel ABI
; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2 ; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
; r1 = magic number (board identity, unused as of now ; r1 = magic number (always zero as of now)
; r2 = pointer to uboot provided cmdline or external DTB in mem ; r2 = pointer to uboot provided cmdline or external DTB in mem
; These are handled later in setup_arch() ; These are handled later in handle_uboot_args()
st r0, [@uboot_tag] st r0, [@uboot_tag]
st r2, [@uboot_arg] st r2, [@uboot_arg]
#endif #endif
......
...@@ -462,43 +462,80 @@ void setup_processor(void) ...@@ -462,43 +462,80 @@ void setup_processor(void)
arc_chk_core_config(); arc_chk_core_config();
} }
static inline int is_kernel(unsigned long addr) static inline bool uboot_arg_invalid(unsigned long addr)
{ {
if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) /*
return 1; * Check that it is a untranslated address (although MMU is not enabled
return 0; * yet, it being a high address ensures this is not by fluke)
*/
if (addr < PAGE_OFFSET)
return true;
/* Check that address doesn't clobber resident kernel image */
return addr >= (unsigned long)_stext && addr <= (unsigned long)_end;
} }
void __init setup_arch(char **cmdline_p) #define IGNORE_ARGS "Ignore U-boot args: "
/* uboot_tag values for U-boot - kernel ABI revision 0; see head.S */
#define UBOOT_TAG_NONE 0
#define UBOOT_TAG_CMDLINE 1
#define UBOOT_TAG_DTB 2
void __init handle_uboot_args(void)
{ {
bool use_embedded_dtb = true;
bool append_cmdline = false;
#ifdef CONFIG_ARC_UBOOT_SUPPORT #ifdef CONFIG_ARC_UBOOT_SUPPORT
/* make sure that uboot passed pointer to cmdline/dtb is valid */ /* check that we know this tag */
if (uboot_tag && is_kernel((unsigned long)uboot_arg)) if (uboot_tag != UBOOT_TAG_NONE &&
panic("Invalid uboot arg\n"); uboot_tag != UBOOT_TAG_CMDLINE &&
uboot_tag != UBOOT_TAG_DTB) {
pr_warn(IGNORE_ARGS "invalid uboot tag: '%08x'\n", uboot_tag);
goto ignore_uboot_args;
}
/* See if u-boot passed an external Device Tree blob */ if (uboot_tag != UBOOT_TAG_NONE &&
machine_desc = setup_machine_fdt(uboot_arg); /* uboot_tag == 2 */ uboot_arg_invalid((unsigned long)uboot_arg)) {
if (!machine_desc) pr_warn(IGNORE_ARGS "invalid uboot arg: '%px'\n", uboot_arg);
goto ignore_uboot_args;
}
/* see if U-boot passed an external Device Tree blob */
if (uboot_tag == UBOOT_TAG_DTB) {
machine_desc = setup_machine_fdt((void *)uboot_arg);
/* external Device Tree blob is invalid - use embedded one */
use_embedded_dtb = !machine_desc;
}
if (uboot_tag == UBOOT_TAG_CMDLINE)
append_cmdline = true;
ignore_uboot_args:
#endif #endif
{
/* No, so try the embedded one */ if (use_embedded_dtb) {
machine_desc = setup_machine_fdt(__dtb_start); machine_desc = setup_machine_fdt(__dtb_start);
if (!machine_desc) if (!machine_desc)
panic("Embedded DT invalid\n"); panic("Embedded DT invalid\n");
}
/* /*
* If we are here, it is established that @uboot_arg didn't * NOTE: @boot_command_line is populated by setup_machine_fdt() so this
* point to DT blob. Instead if u-boot says it is cmdline, * append processing can only happen after.
* append to embedded DT cmdline.
* setup_machine_fdt() would have populated @boot_command_line
*/ */
if (uboot_tag == 1) { if (append_cmdline) {
/* Ensure a whitespace between the 2 cmdlines */ /* Ensure a whitespace between the 2 cmdlines */
strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
strlcat(boot_command_line, uboot_arg, strlcat(boot_command_line, uboot_arg, COMMAND_LINE_SIZE);
COMMAND_LINE_SIZE);
}
} }
}
void __init setup_arch(char **cmdline_p)
{
handle_uboot_args();
/* Save unparsed command line copy for /proc/cmdline */ /* Save unparsed command line copy for /proc/cmdline */
*cmdline_p = boot_command_line; *cmdline_p = boot_command_line;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment