diff mbox series

[mips-fixes] MIPS: relocatable: fix possible boot hangup with KASLR enabled

Message ID 20210110142023.185275-1-alobakin@pm.me
State Accepted
Commit 69e976831cd53f9ba304fd20305b2025ecc78eab
Headers show
Series [mips-fixes] MIPS: relocatable: fix possible boot hangup with KASLR enabled | expand

Commit Message

Alexander Lobakin Jan. 10, 2021, 2:21 p.m. UTC
LLVM-built Linux triggered a boot hangup with KASLR enabled.

arch/mips/kernel/relocate.c:get_random_boot() uses linux_banner,
which is a string constant, as a random seed, but accesses it
as an array of unsigned long (in rotate_xor()).
When the address of linux_banner is not aligned to sizeof(long),
such access emits unaligned access exception and hangs the kernel.

Use PTR_ALIGN() to align input address to sizeof(long) and also
align down the input length to prevent possible access-beyond-end.

Fixes: 405bc8fd12f5 ("MIPS: Kernel: Implement KASLR using CONFIG_RELOCATABLE")
Cc: stable@vger.kernel.org # 4.7+
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
---
 arch/mips/kernel/relocate.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Comments

Nathan Chancellor Jan. 11, 2021, 5:21 a.m. UTC | #1
On Sun, Jan 10, 2021 at 02:21:05PM +0000, Alexander Lobakin wrote:
> LLVM-built Linux triggered a boot hangup with KASLR enabled.

> 

> arch/mips/kernel/relocate.c:get_random_boot() uses linux_banner,

> which is a string constant, as a random seed, but accesses it

> as an array of unsigned long (in rotate_xor()).

> When the address of linux_banner is not aligned to sizeof(long),

> such access emits unaligned access exception and hangs the kernel.

> 

> Use PTR_ALIGN() to align input address to sizeof(long) and also

> align down the input length to prevent possible access-beyond-end.

> 

> Fixes: 405bc8fd12f5 ("MIPS: Kernel: Implement KASLR using CONFIG_RELOCATABLE")

> Cc: stable@vger.kernel.org # 4.7+

> Signed-off-by: Alexander Lobakin <alobakin@pm.me>


Apologies for not being familiar enough with the issue to give a review
but I did reproduce the hang that the commit mentions with
malta_kvm_guest_defconfig + CONFIG_RELOCATABLE=y +
CONFIG_RANDOMIZE_BASE=y and this patch does resolve it so:

Tested-by: Nathan Chancellor <natechancellor@gmail.com>


> ---

>  arch/mips/kernel/relocate.c | 10 ++++++++--

>  1 file changed, 8 insertions(+), 2 deletions(-)

> 

> diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c

> index 47aeb3350a76..0e365b7c742d 100644

> --- a/arch/mips/kernel/relocate.c

> +++ b/arch/mips/kernel/relocate.c

> @@ -187,8 +187,14 @@ static int __init relocate_exception_table(long offset)

>  static inline __init unsigned long rotate_xor(unsigned long hash,

>  					      const void *area, size_t size)

>  {

> -	size_t i;

> -	unsigned long *ptr = (unsigned long *)area;

> +	const typeof(hash) *ptr = PTR_ALIGN(area, sizeof(hash));

> +	size_t diff, i;

> +

> +	diff = (void *)ptr - area;

> +	if (unlikely(size < diff + sizeof(hash)))

> +		return hash;

> +

> +	size = ALIGN_DOWN(size - diff, sizeof(hash));

>  

>  	for (i = 0; i < size / sizeof(hash); i++) {

>  		/* Rotate by odd number of bits and XOR. */

> -- 

> 2.30.0

> 

>
Kees Cook Jan. 11, 2021, 7:52 p.m. UTC | #2
On Sun, Jan 10, 2021 at 02:21:05PM +0000, Alexander Lobakin wrote:
> LLVM-built Linux triggered a boot hangup with KASLR enabled.

> 

> arch/mips/kernel/relocate.c:get_random_boot() uses linux_banner,

> which is a string constant, as a random seed, but accesses it

> as an array of unsigned long (in rotate_xor()).

> When the address of linux_banner is not aligned to sizeof(long),

> such access emits unaligned access exception and hangs the kernel.

> 

> Use PTR_ALIGN() to align input address to sizeof(long) and also

> align down the input length to prevent possible access-beyond-end.

> 

> Fixes: 405bc8fd12f5 ("MIPS: Kernel: Implement KASLR using CONFIG_RELOCATABLE")

> Cc: stable@vger.kernel.org # 4.7+

> Signed-off-by: Alexander Lobakin <alobakin@pm.me>


Reviewed-by: Kees Cook <keescook@chromium.org>


-- 
Kees Cook
Thomas Bogendoerfer Jan. 13, 2021, 10:43 a.m. UTC | #3
On Sun, Jan 10, 2021 at 02:21:05PM +0000, Alexander Lobakin wrote:
> LLVM-built Linux triggered a boot hangup with KASLR enabled.

> 

> arch/mips/kernel/relocate.c:get_random_boot() uses linux_banner,

> which is a string constant, as a random seed, but accesses it

> as an array of unsigned long (in rotate_xor()).

> When the address of linux_banner is not aligned to sizeof(long),

> such access emits unaligned access exception and hangs the kernel.

> 

> Use PTR_ALIGN() to align input address to sizeof(long) and also

> align down the input length to prevent possible access-beyond-end.

> 

> Fixes: 405bc8fd12f5 ("MIPS: Kernel: Implement KASLR using CONFIG_RELOCATABLE")

> Cc: stable@vger.kernel.org # 4.7+

> Signed-off-by: Alexander Lobakin <alobakin@pm.me>

> ---

>  arch/mips/kernel/relocate.c | 10 ++++++++--

>  1 file changed, 8 insertions(+), 2 deletions(-)


applied to mips-fixes.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]
diff mbox series

Patch

diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c
index 47aeb3350a76..0e365b7c742d 100644
--- a/arch/mips/kernel/relocate.c
+++ b/arch/mips/kernel/relocate.c
@@ -187,8 +187,14 @@  static int __init relocate_exception_table(long offset)
 static inline __init unsigned long rotate_xor(unsigned long hash,
 					      const void *area, size_t size)
 {
-	size_t i;
-	unsigned long *ptr = (unsigned long *)area;
+	const typeof(hash) *ptr = PTR_ALIGN(area, sizeof(hash));
+	size_t diff, i;
+
+	diff = (void *)ptr - area;
+	if (unlikely(size < diff + sizeof(hash)))
+		return hash;
+
+	size = ALIGN_DOWN(size - diff, sizeof(hash));
 
 	for (i = 0; i < size / sizeof(hash); i++) {
 		/* Rotate by odd number of bits and XOR. */