* [PATCH v3] mips: kernel: fix detect_memory_region() function
@ 2024-06-29 4:49 Shiji Yang
2024-06-30 6:56 ` Maciej W. Rozycki
0 siblings, 1 reply; 2+ messages in thread
From: Shiji Yang @ 2024-06-29 4:49 UTC (permalink / raw)
To: linux-mips
Cc: Thomas Bogendoerfer, Arnd Bergmann, Greg Kroah-Hartman,
Javier Martinez Canillas, Khalid Aziz, Baoquan He, Jiaxun Yang,
Serge Semin, linux-kernel, Shiji Yang, Mieczyslaw Nalewaj
1. Do not use memcmp() on unallocated memory, as the new introduced
fortify dynamic object size check[1] will return unexpected result.
2. Use a fixed pattern instead of a random function pointer as the
magic value. "0xaa5555aa" has a large information entropy and is
widely used in memory testing.
3. Flip the magic value and double check it to ensure memory overlap.
Tested on ralink/mt7620 and ath79/ar9344
[1] commit 439a1bcac648 ("fortify: Use __builtin_dynamic_object_size() when available")
Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
Tested-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
---
changes:
v2 -> v3:
* Using CKSEG1ADDR_OR_64BIT() instead of excluding 64bit system.
* Using volatile pointer to get and compare u32 data.
v1:
https://lore.kernel.org/all/TYAP286MB0315E609C476B86E22700626BC292@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM/
v2:
https://lore.kernel.org/all/TYCP286MB089598ABD1E2F66003D71EB8BCD52@TYCP286MB0895.JPNP286.PROD.OUTLOOK.COM/
arch/mips/kernel/setup.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 12a1a4ffb602..4197c7568f49 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -86,21 +86,26 @@ static struct resource bss_resource = { .name = "Kernel bss", };
unsigned long __kaslr_offset __ro_after_init;
EXPORT_SYMBOL(__kaslr_offset);
-static void *detect_magic __initdata = detect_memory_region;
-
#ifdef CONFIG_MIPS_AUTO_PFN_OFFSET
unsigned long ARCH_PFN_OFFSET;
EXPORT_SYMBOL(ARCH_PFN_OFFSET);
#endif
+#define MIPS_MEM_TEST_PATTERN 0xaa5555aa
+
void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max)
{
- void *dm = &detect_magic;
+ u32 detect_magic;
+ volatile u32 *dm = (volatile u32 *)CKSEG1ADDR_OR_64BIT(&detect_magic);
phys_addr_t size;
for (size = sz_min; size < sz_max; size <<= 1) {
- if (!memcmp(dm, dm + size, sizeof(detect_magic)))
- break;
+ *dm = MIPS_MEM_TEST_PATTERN;
+ if (*dm == *(volatile u32 *)((void *)dm + size)) {
+ *dm = ~MIPS_MEM_TEST_PATTERN;
+ if (*dm == *(volatile u32 *)((void *)dm + size))
+ break;
+ }
}
pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n",
--
2.45.1
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH v3] mips: kernel: fix detect_memory_region() function
2024-06-29 4:49 [PATCH v3] mips: kernel: fix detect_memory_region() function Shiji Yang
@ 2024-06-30 6:56 ` Maciej W. Rozycki
0 siblings, 0 replies; 2+ messages in thread
From: Maciej W. Rozycki @ 2024-06-30 6:56 UTC (permalink / raw)
To: Shiji Yang
Cc: linux-mips, Thomas Bogendoerfer, Arnd Bergmann,
Greg Kroah-Hartman, Javier Martinez Canillas, Khalid Aziz,
Baoquan He, Jiaxun Yang, Serge Semin, linux-kernel,
Mieczyslaw Nalewaj
On Sat, 29 Jun 2024, Shiji Yang wrote:
> 1. Do not use memcmp() on unallocated memory, as the new introduced
> fortify dynamic object size check[1] will return unexpected result.
That seems like a bug in the check to me. Why would `memcmp' referring
to a location within the data section cause an unexpected result, forcing
code to use an equivalent handcoded sequence? This defeats the purpose of
having possibly optimised code in `memcmp' for this.
> diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
> index 12a1a4ffb602..4197c7568f49 100644
> --- a/arch/mips/kernel/setup.c
> +++ b/arch/mips/kernel/setup.c
> @@ -86,21 +86,26 @@ static struct resource bss_resource = { .name = "Kernel bss", };
> unsigned long __kaslr_offset __ro_after_init;
> EXPORT_SYMBOL(__kaslr_offset);
>
> -static void *detect_magic __initdata = detect_memory_region;
> -
> #ifdef CONFIG_MIPS_AUTO_PFN_OFFSET
> unsigned long ARCH_PFN_OFFSET;
> EXPORT_SYMBOL(ARCH_PFN_OFFSET);
> #endif
>
> +#define MIPS_MEM_TEST_PATTERN 0xaa5555aa
> +
> void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max)
> {
> - void *dm = &detect_magic;
> + u32 detect_magic;
> + volatile u32 *dm = (volatile u32 *)CKSEG1ADDR_OR_64BIT(&detect_magic);
> phys_addr_t size;
>
> for (size = sz_min; size < sz_max; size <<= 1) {
> - if (!memcmp(dm, dm + size, sizeof(detect_magic)))
> - break;
> + *dm = MIPS_MEM_TEST_PATTERN;
> + if (*dm == *(volatile u32 *)((void *)dm + size)) {
> + *dm = ~MIPS_MEM_TEST_PATTERN;
> + if (*dm == *(volatile u32 *)((void *)dm + size))
Can't you just do *(dm + (size >> 2)) and avoid all the horrible casting?
Or maybe even dm[0] == dm[size >> 2]?
> + break;
> + }
> }
Anyway this code makes no sense to me, with or without the change. What
is it exactly supposed to peek at, the location of `detect_magic' plus
some offset?
What about the `start' parameter? What is it for, given that it's not
used in probing, but only for reporting and adding the memory region? Is
it not where probing is supposed to happen in the first place?
I can see how `ath79_detect_mem_size' this mess has come from made some
sense as in 9b75733b7b5e0^:arch/mips/ath79/setup.c -- a bit hackish, but
the size of the probing window set to 1024 bytes combined with comparing
against machine code from `ath79_detect_mem_size' made a false hit highly
unlikely. That sense has been lost since and your change partially fixes
it by making a check against both the straight and the complemented value
of a test pattern. Good.
But still that does not fix the issue with `start'. Given how this code
has been written I'm not even sure if it's suitable for nonzero `start' at
all. Or should the call to `memblock_add' just be adjusted accordingly:
memblock_add(start, size - start);
? This might make sense and if suitable, then it should be documented as
the feature of `detect_memory_region' (as should probably be that it will
round the amount of memory available down to the nearest power of two).
Alternatively the code can start probing at `start', but then it'll have
to be rewritten, because obviously `detect_magic' may not necessarily be
above `start'.
Maciej
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-06-30 6:56 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-29 4:49 [PATCH v3] mips: kernel: fix detect_memory_region() function Shiji Yang
2024-06-30 6:56 ` Maciej W. Rozycki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®