False positive kmemleak report for dtb properties names on powerpc

2022-02-18 Thread Ariel Marcovitch

Hello!

I was running a powerpc 32bit kernel (built using 
qemu_ppc_mpc8544ds_defconfig
buildroot config, with enabling DEBUGFS+KMEMLEAK+HIGHMEM in the kernel 
config)
on qemu and invoked the kmemleak scan (twice. for some reason the first 
time wasn't enough).


(Actually the problem will probably reproduce on every ppc kernel with
HIGHMEM enabled, but I only checked this config)

I got 97 leak reports, all similar to the following:

```

unreferenced object 0xc1803840 (size 16):
  comm "swapper", pid 1, jiffies 4294892303 (age 39.320s)
  hex dump (first 16 bytes):
    64 65 76 69 63 65 5f 74 79 70 65 00 00 00 00 00 device_type.
  backtrace:
    [<(ptrval)>] kstrdup+0x40/0x98
    [<(ptrval)>] __of_add_property_sysfs+0xa4/0x10c
    [<(ptrval)>] __of_attach_node_sysfs+0xc0/0x110
    [<(ptrval)>] of_core_init+0xa8/0x15c
    [<(ptrval)>] driver_init+0x24/0x3c
    [<(ptrval)>] kernel_init_freeable+0xb8/0x23c
    [<(ptrval)>] kernel_init+0x24/0x14c
    [<(ptrval)>] ret_from_kernel_thread+0x5c/0x64
```

The objects in the reports are the names of the sysfs files created for 
the dtb

nodes and properties.

These are definitely not leaked, as they are even visible to the user as 
the sysfs file names.


These strings (for dtb properties, in the case of the shown report, but 
the case with dtb nodes is very similar) are created in 
__of_add_property_sysfs() and the pointer to them is stored in 
pp->attr.attr.name (so, actually stored in the memory pointed by pp)


pp is one of the dtb property objects which are allocated in 
early_init_dt_alloc_memory_arch() in of/fdt.c using memblock_alloc. This 
happens very early, in setup_arch()->unflatten_device_tree().


memblock_alloc lets kmemleak know about the allocated memory using 
kmemleak_alloc_phys (in mm/memblock.c:memblock_alloc_range_nid()).


The problem is with the following code (mm/kmemleak.c):

```c

void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count,
   gfp_t gfp)
{
    if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
    kmemleak_alloc(__va(phys), size, min_count, gfp);
}

```

When CONFIG_HIGHMEM is enabled, the pfn of the allocated memory is 
checked against max_low_pfn, to make sure it is not in the HIGHMEM zone.


However, when called through unflatten_device_tree(), max_low_pfn is not 
yet initialized in powerpc.


max_low_pfn is initialized (when NUMA is disabled) in 
arch/powerpc/mm/mem.c:mem_topology_setup() which is called only after 
unflatten_device_tree() is called in the same function (setup_arch()).


Because max_low_pfn is global it is 0 before initialization, so as far 
as kmemleak_alloc_phys() is concerned, every memory is HIGHMEM (: and 
the allocated memory is not tracked by kmemleak, causing references to 
objects allocated later with kmalloc() to be ignored and these objects 
are marked as leaked.


I actually tried to find out whether this happen on other arches as 
well, and it seems like arm64 also have this problem when dtb is used 
instead of acpi, although I haven't had the chance to confirm this.


I don't suppose I can just shuffle the calls in setup_arch() around, so 
I wanted to hear your opinions first


Thanks!



Re: False positive kmemleak report for dtb properties names on powerpc

2022-02-24 Thread Ariel Marcovitch

Ping :)

On 18/02/2022 21:45, Ariel Marcovitch wrote:

Hello!

I was running a powerpc 32bit kernel (built using 
qemu_ppc_mpc8544ds_defconfig
buildroot config, with enabling DEBUGFS+KMEMLEAK+HIGHMEM in the kernel 
config)
on qemu and invoked the kmemleak scan (twice. for some reason the 
first time wasn't enough).


(Actually the problem will probably reproduce on every ppc kernel with
HIGHMEM enabled, but I only checked this config)

I got 97 leak reports, all similar to the following:

```

unreferenced object 0xc1803840 (size 16):
  comm "swapper", pid 1, jiffies 4294892303 (age 39.320s)
  hex dump (first 16 bytes):
    64 65 76 69 63 65 5f 74 79 70 65 00 00 00 00 00 device_type.
  backtrace:
    [<(ptrval)>] kstrdup+0x40/0x98
    [<(ptrval)>] __of_add_property_sysfs+0xa4/0x10c
    [<(ptrval)>] __of_attach_node_sysfs+0xc0/0x110
    [<(ptrval)>] of_core_init+0xa8/0x15c
    [<(ptrval)>] driver_init+0x24/0x3c
    [<(ptrval)>] kernel_init_freeable+0xb8/0x23c
    [<(ptrval)>] kernel_init+0x24/0x14c
    [<(ptrval)>] ret_from_kernel_thread+0x5c/0x64
```

The objects in the reports are the names of the sysfs files created 
for the dtb

nodes and properties.

These are definitely not leaked, as they are even visible to the user 
as the sysfs file names.


These strings (for dtb properties, in the case of the shown report, 
but the case with dtb nodes is very similar) are created in 
__of_add_property_sysfs() and the pointer to them is stored in 
pp->attr.attr.name (so, actually stored in the memory pointed by pp)


pp is one of the dtb property objects which are allocated in 
early_init_dt_alloc_memory_arch() in of/fdt.c using memblock_alloc. 
This happens very early, in setup_arch()->unflatten_device_tree().


memblock_alloc lets kmemleak know about the allocated memory using 
kmemleak_alloc_phys (in mm/memblock.c:memblock_alloc_range_nid()).


The problem is with the following code (mm/kmemleak.c):

```c

void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int 
min_count,

   gfp_t gfp)
{
    if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
    kmemleak_alloc(__va(phys), size, min_count, gfp);
}

```

When CONFIG_HIGHMEM is enabled, the pfn of the allocated memory is 
checked against max_low_pfn, to make sure it is not in the HIGHMEM zone.


However, when called through unflatten_device_tree(), max_low_pfn is 
not yet initialized in powerpc.


max_low_pfn is initialized (when NUMA is disabled) in 
arch/powerpc/mm/mem.c:mem_topology_setup() which is called only after 
unflatten_device_tree() is called in the same function (setup_arch()).


Because max_low_pfn is global it is 0 before initialization, so as far 
as kmemleak_alloc_phys() is concerned, every memory is HIGHMEM (: and 
the allocated memory is not tracked by kmemleak, causing references to 
objects allocated later with kmalloc() to be ignored and these objects 
are marked as leaked.


I actually tried to find out whether this happen on other arches as 
well, and it seems like arm64 also have this problem when dtb is used 
instead of acpi, although I haven't had the chance to confirm this.


I don't suppose I can just shuffle the calls in setup_arch() around, 
so I wanted to hear your opinions first


Thanks!



Re: False positive kmemleak report for dtb properties names on powerpc

2022-03-18 Thread Ariel Marcovitch

Pinging again :)

On 25/02/2022 0:27, Ariel Marcovitch wrote:

Ping :)

On 18/02/2022 21:45, Ariel Marcovitch wrote:

Hello!

I was running a powerpc 32bit kernel (built using 
qemu_ppc_mpc8544ds_defconfig
buildroot config, with enabling DEBUGFS+KMEMLEAK+HIGHMEM in the 
kernel config)
on qemu and invoked the kmemleak scan (twice. for some reason the 
first time wasn't enough).


(Actually the problem will probably reproduce on every ppc kernel with
HIGHMEM enabled, but I only checked this config)

I got 97 leak reports, all similar to the following:

```

unreferenced object 0xc1803840 (size 16):
  comm "swapper", pid 1, jiffies 4294892303 (age 39.320s)
  hex dump (first 16 bytes):
    64 65 76 69 63 65 5f 74 79 70 65 00 00 00 00 00 device_type.
  backtrace:
    [<(ptrval)>] kstrdup+0x40/0x98
    [<(ptrval)>] __of_add_property_sysfs+0xa4/0x10c
    [<(ptrval)>] __of_attach_node_sysfs+0xc0/0x110
    [<(ptrval)>] of_core_init+0xa8/0x15c
    [<(ptrval)>] driver_init+0x24/0x3c
    [<(ptrval)>] kernel_init_freeable+0xb8/0x23c
    [<(ptrval)>] kernel_init+0x24/0x14c
    [<(ptrval)>] ret_from_kernel_thread+0x5c/0x64
```

The objects in the reports are the names of the sysfs files created 
for the dtb

nodes and properties.

These are definitely not leaked, as they are even visible to the user 
as the sysfs file names.


These strings (for dtb properties, in the case of the shown report, 
but the case with dtb nodes is very similar) are created in 
__of_add_property_sysfs() and the pointer to them is stored in 
pp->attr.attr.name (so, actually stored in the memory pointed by pp)


pp is one of the dtb property objects which are allocated in 
early_init_dt_alloc_memory_arch() in of/fdt.c using memblock_alloc. 
This happens very early, in setup_arch()->unflatten_device_tree().


memblock_alloc lets kmemleak know about the allocated memory using 
kmemleak_alloc_phys (in mm/memblock.c:memblock_alloc_range_nid()).


The problem is with the following code (mm/kmemleak.c):

```c

void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int 
min_count,

   gfp_t gfp)
{
    if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
    kmemleak_alloc(__va(phys), size, min_count, gfp);
}

```

When CONFIG_HIGHMEM is enabled, the pfn of the allocated memory is 
checked against max_low_pfn, to make sure it is not in the HIGHMEM zone.


However, when called through unflatten_device_tree(), max_low_pfn is 
not yet initialized in powerpc.


max_low_pfn is initialized (when NUMA is disabled) in 
arch/powerpc/mm/mem.c:mem_topology_setup() which is called only after 
unflatten_device_tree() is called in the same function (setup_arch()).


Because max_low_pfn is global it is 0 before initialization, so as 
far as kmemleak_alloc_phys() is concerned, every memory is HIGHMEM (: 
and the allocated memory is not tracked by kmemleak, causing 
references to objects allocated later with kmalloc() to be ignored 
and these objects are marked as leaked.


I actually tried to find out whether this happen on other arches as 
well, and it seems like arm64 also have this problem when dtb is used 
instead of acpi, although I haven't had the chance to confirm this.


I don't suppose I can just shuffle the calls in setup_arch() around, 
so I wanted to hear your opinions first


Thanks!



Re: False positive kmemleak report for dtb properties names on powerpc

2022-04-09 Thread Ariel Marcovitch

Hi Christophe, did you get the chance to look at this?

On 23/03/2022 21:06, Mike Rapoport wrote:

Hi Catalin,

On Wed, Mar 23, 2022 at 05:22:38PM +, Catalin Marinas wrote:

Hi Ariel,

On Fri, Feb 18, 2022 at 09:45:51PM +0200, Ariel Marcovitch wrote:

I was running a powerpc 32bit kernel (built using
qemu_ppc_mpc8544ds_defconfig
buildroot config, with enabling DEBUGFS+KMEMLEAK+HIGHMEM in the kernel
config)
on qemu and invoked the kmemleak scan (twice. for some reason the first time
wasn't enough).

[...]

I got 97 leak reports, all similar to the following:

[...]

memblock_alloc lets kmemleak know about the allocated memory using
kmemleak_alloc_phys (in mm/memblock.c:memblock_alloc_range_nid()).

The problem is with the following code (mm/kmemleak.c):

```c

void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count,
    gfp_t gfp)
{
     if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
     kmemleak_alloc(__va(phys), size, min_count, gfp);
}

```

When CONFIG_HIGHMEM is enabled, the pfn of the allocated memory is checked
against max_low_pfn, to make sure it is not in the HIGHMEM zone.

However, when called through unflatten_device_tree(), max_low_pfn is not yet
initialized in powerpc.

max_low_pfn is initialized (when NUMA is disabled) in
arch/powerpc/mm/mem.c:mem_topology_setup() which is called only after
unflatten_device_tree() is called in the same function (setup_arch()).

Because max_low_pfn is global it is 0 before initialization, so as far as
kmemleak_alloc_phys() is concerned, every memory is HIGHMEM (: and the
allocated memory is not tracked by kmemleak, causing references to objects
allocated later with kmalloc() to be ignored and these objects are marked as
leaked.

Thanks for digging into this. It looks like the logic doesn't work (not
sure whether it ever worked).


I actually tried to find out whether this happen on other arches as well,
and it seems like arm64 also have this problem when dtb is used instead of
acpi, although I haven't had the chance to confirm this.

arm64 doesn't enable CONFIG_HIGHMEM, so it's not affected.


I don't suppose I can just shuffle the calls in setup_arch() around, so I
wanted to hear your opinions first

I think it's better if we change the logic than shuffling the calls.
IIUC MEMBLOCK_ALLOC_ACCESSIBLE means that __va() works on the phys
address return by memblock, so something like below (untested):

MEMBLOCK_ALLOC_ACCESSIBLE means "anywhere", see commit e63075a3c937
("memblock: Introduce default allocation limit and use it to replace
explicit ones"), so it won't help to detect high memory.

If I remember correctly, ppc initializes memblock *very* early, so setting
max_low_pfn along with lowmem_end_addr in
arch/powerpc/mm/init_32::MMU_init() makes sense to me.

Maybe ppc folks have other ideas...
I've added Christophe who works on ppc32 these days.
  

-8<--
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 7580baa76af1..f3599e857c13 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1127,8 +1127,7 @@ EXPORT_SYMBOL(kmemleak_no_scan);
  void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count,
   gfp_t gfp)
  {
-   if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn)
-   kmemleak_alloc(__va(phys), size, min_count, gfp);
+   kmemleak_alloc(__va(phys), size, min_count, gfp);
  }
  EXPORT_SYMBOL(kmemleak_alloc_phys);
  
diff --git a/mm/memblock.c b/mm/memblock.c

index b12a364f2766..2515bd4331e8 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1397,7 +1397,7 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t 
size,
 * Skip kmemleak for those places like kasan_init() and
 * early_pgtable_alloc() due to high volume.
 */
-   if (end != MEMBLOCK_ALLOC_NOLEAKTRACE)
+   if (end == MEMBLOCK_ALLOC_ACCESSIBLE)

This change would enable kmemleak for KASAN on arm and arm64 that AFAIR
caused OOM in kmemleak and it also will limit tracking only to allocations
that do not specify 'end' explicitly ;-)


/*
 * The min_count is set to 0 so that memblock allocated
 * blocks are never reported as leaks. This is because many
-8<--

But I'm not sure whether we'd now miss some genuine allocations where
the memblock limit is different from MEMBLOCK_ALLOC_ACCESSIBLE but still
within the lowmem limit. If the above works, we can probably get rid of
some other kmemleak callbacks in the kernel.

Adding Mike for any input on memblock.

--
Catalin


[PATCH] powerpc: fix alignment bug whithin the init sections

2020-12-13 Thread Ariel Marcovitch
This is a bug that can cause early crashes in configurations with a
.exit.text section smaller than a page and a .init.text section that
ends in the beginning of a physical page (this is kinda random, which
might explain why this wasn't really encountered before).

The init sections are ordered like this:
.init.text
.exit.text
.init.data

Currently, these sections aren't page aligned.

Because the init code is mapped read-only at runtime and because the
.init.text section can potentially reside on the same physical page as
.init.data, the beginning of .init.data might be mapped read-only along
with .init.text.

Then when the kernel tries to modify a variable in .init.data (like
kthreadd_done, used in kernel_init()) the kernel panics.

To avoid this, I made these sections page aligned.

Fixes: 060ef9d89d18 ("powerpc32: PAGE_EXEC required for inittext")
Signed-off-by: Ariel Marcovitch 
---
 arch/powerpc/kernel/vmlinux.lds.S | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/powerpc/kernel/vmlinux.lds.S 
b/arch/powerpc/kernel/vmlinux.lds.S
index 326e113d2e45..e3a7c90c03f4 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -179,6 +179,11 @@ SECTIONS
 #endif
} :text
 
+   /* .init.text is made RO and .exit.text is not, so we must
+* ensure these sections reside in separate physical pages.
+*/
+   . = ALIGN(PAGE_SIZE);
+
/* .exit.text is discarded at runtime, not link time,
 * to deal with references from __bug_table
 */
@@ -186,6 +191,8 @@ SECTIONS
EXIT_TEXT
}
 
+   . = ALIGN(PAGE_SIZE);
+
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
INIT_DATA
}

base-commit: 1398820fee515873379809a6415930ad0764b2f6
-- 
2.17.1



Re: [PATCH] powerpc: fix alignment bug whithin the init sections

2020-12-18 Thread ariel marcovitch
On Fri, Dec 18, 2020 at 5:39 PM Christophe Leroy <
christophe.le...@csgroup.eu> wrote:

> It can cause, or it causes ? Did you encounter the issue ?
>
Yes, in configs that result in the section layout I described, the crush is
consistent.

>
> > The init sections are ordered like this:
> >   .init.text
> >   .exit.text
> >   .init.data
> >
> > Currently, these sections aren't page aligned.
> >
> > Because the init code is mapped read-only at runtime and because the
> > .init.text section can potentially reside on the same physical page as
> > .init.data, the beginning of .init.data might be mapped read-only along
> > with .init.text.
>
> init code is mapped PAGE_KERNEL_TEXT.
>
> Whether PAGE_KERNEL_TEXT is read-only or not depends on the selected
> options.
>
You are right, of course. Should I change the commit message to 'might be
mapped' or something?

>
> > Then when the kernel tries to modify a variable in .init.data (like
> > kthreadd_done, used in kernel_init()) the kernel panics.
> >
> > To avoid this, I made these sections page aligned.
>
> Should write this unpersonal, something like "To avoid this, make these
> sections page aligned"
>
Noted, thanks.


>
> >
> > Fixes: 060ef9d89d18 ("powerpc32: PAGE_EXEC required for inittext")
> > Signed-off-by: Ariel Marcovitch 
> > ---
> >   arch/powerpc/kernel/vmlinux.lds.S | 7 +++
> >   1 file changed, 7 insertions(+)
> >
> > diff --git a/arch/powerpc/kernel/vmlinux.lds.S
> b/arch/powerpc/kernel/vmlinux.lds.S
> > index 326e113d2e45..e3a7c90c03f4 100644
> > --- a/arch/powerpc/kernel/vmlinux.lds.S
> > +++ b/arch/powerpc/kernel/vmlinux.lds.S
> > @@ -179,6 +179,11 @@ SECTIONS
> >   #endif
> >   } :text
> >
> > + /* .init.text is made RO and .exit.text is not, so we must
> > +  * ensure these sections reside in separate physical pages.
> > +  */
> > + . = ALIGN(PAGE_SIZE);
> > +
>
> In principle, as it is text, it should be made RO as well. But what
> happens at the begining doesn't
> really matter, anyway .exit.text should never be executed and is discarded
> together with init text.
> So, I think it is OK the live with it as is for the time being.


> Making it page aligned makes sense anyway.
>
> Should we make _einittext page aligned instead, just like _etext ?

Yes, this will probably be better (because when _einittext is not aligned,
the part of the page after _einittext is mapped RO implicitly, and it's
hard to notice from the code). I suppose you mean something like this:
_sinittext = .;
INIT_TEXT
+
+   . = ALIGN(.);
_einittext = .;

>   /* .exit.text is discarded at runtime, not link time,
> >* to deal with references from __bug_table
> >*/
> > @@ -186,6 +191,8 @@ SECTIONS
> >   EXIT_TEXT
> >   }
> >
> > + . = ALIGN(PAGE_SIZE);
> > +
>
> Here for sure, as you explain in the coming log, this needs to be
> separated from init text. So
> making it aligned is a must.


> >   .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
> >   INIT_DATA
> >   }
> >
> > base-commit: 1398820fee515873379809a6415930ad0764b2f6
> >
>
> Christophe
>
Thanks for your time,
Ariel Marcovitch


Re: [PATCH] powerpc: fix alignment bug whithin the init sections

2020-12-18 Thread ariel marcovitch
On Fri, Dec 18, 2020 at 5:39 PM Christophe Leroy <
christophe.le...@csgroup.eu> wrote:

> It can cause, or it causes ? Did you encounter the issue ?
>
Yes, in configs that result in the section layout I described, the crush is
consistent.

>
> > The init sections are ordered like this:
> >   .init.text
> >   .exit.text
> >   .init.data
> >
> > Currently, these sections aren't page aligned.
> >
> > Because the init code is mapped read-only at runtime and because the
> > .init.text section can potentially reside on the same physical page as
> > .init.data, the beginning of .init.data might be mapped read-only along
> > with .init.text.
>
> init code is mapped PAGE_KERNEL_TEXT.
>
> Whether PAGE_KERNEL_TEXT is read-only or not depends on the selected
> options.
>
You are right, of course. Should I change the commit message to 'might be
mapped' or something?

>
> > Then when the kernel tries to modify a variable in .init.data (like
> > kthreadd_done, used in kernel_init()) the kernel panics.
> >
> > To avoid this, I made these sections page aligned.
>
> Should write this unpersonal, something like "To avoid this, make these
> sections page aligned"
>
Noted, thanks.


>
> >
> > Fixes: 060ef9d89d18 ("powerpc32: PAGE_EXEC required for inittext")
> > Signed-off-by: Ariel Marcovitch 
> > ---
> >   arch/powerpc/kernel/vmlinux.lds.S | 7 +++
> >   1 file changed, 7 insertions(+)
> >
> > diff --git a/arch/powerpc/kernel/vmlinux.lds.S
> b/arch/powerpc/kernel/vmlinux.lds.S
> > index 326e113d2e45..e3a7c90c03f4 100644
> > --- a/arch/powerpc/kernel/vmlinux.lds.S
> > +++ b/arch/powerpc/kernel/vmlinux.lds.S
> > @@ -179,6 +179,11 @@ SECTIONS
> >   #endif
> >   } :text
> >
> > + /* .init.text is made RO and .exit.text is not, so we must
> > +  * ensure these sections reside in separate physical pages.
> > +  */
> > + . = ALIGN(PAGE_SIZE);
> > +
>
> In principle, as it is text, it should be made RO as well. But what
> happens at the begining doesn't
> really matter, anyway .exit.text should never be executed and is discarded
> together with init text.
> So, I think it is OK the live with it as is for the time being.


> Making it page aligned makes sense anyway.
>
> Should we make _einittext page aligned instead, just like _etext ?

Yes, this will probably be better (because when _einittext is not aligned,
the part of the page after _einittext is mapped RO implicitly, and it's
hard to notice from the code). I suppose you mean something like this:
_sinittext = .;
INIT_TEXT
+
+   . = ALIGN(.);
_einittext = .;

>   /* .exit.text is discarded at runtime, not link time,
> >* to deal with references from __bug_table
> >*/
> > @@ -186,6 +191,8 @@ SECTIONS
> >   EXIT_TEXT
> >   }
> >
> > + . = ALIGN(PAGE_SIZE);
> > +
>
> Here for sure, as you explain in the coming log, this needs to be
> separated from init text. So
> making it aligned is a must.


> >   .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
> >   INIT_DATA
> >   }
> >
> > base-commit: 1398820fee515873379809a6415930ad0764b2f6
> >
>
> Christophe
>
Thanks for your time,
Ariel Marcovitch


[PATCH v2] powerpc: fix alignment bug whithin the init sections

2021-01-02 Thread Ariel Marcovitch
This is a bug that causes early crashes in builds with a
.exit.text section smaller than a page and a .init.text section that
ends in the beginning of a physical page (this is kinda random, which
might explain why this wasn't really encountered before).

The init sections are ordered like this:
.init.text
.exit.text
.init.data

Currently, these sections aren't page aligned.

Because the init code might become read-only at runtime and because the
.init.text section can potentially reside on the same physical page as
.init.data, the beginning of .init.data might be mapped read-only along
with .init.text.

Then when the kernel tries to modify a variable in .init.data (like
kthreadd_done, used in kernel_init()) the kernel panics.

To avoid this, make _einittext page aligned and also align .exit.text
to make sure .init.data is always seperated from the text segments.

Fixes: 060ef9d89d18 ("powerpc32: PAGE_EXEC required for inittext")
Signed-off-by: Ariel Marcovitch 
---
 arch/powerpc/kernel/vmlinux.lds.S | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/powerpc/kernel/vmlinux.lds.S 
b/arch/powerpc/kernel/vmlinux.lds.S
index 6db90cdf11da..b6c765d8e7ee 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -187,6 +187,11 @@ SECTIONS
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
_sinittext = .;
INIT_TEXT
+
+   /* .init.text might be RO so we must
+   * ensure this section ends in a page boundary.
+   */
+   . = ALIGN(PAGE_SIZE);
_einittext = .;
 #ifdef CONFIG_PPC64
*(.tramp.ftrace.init);
@@ -200,6 +205,8 @@ SECTIONS
EXIT_TEXT
}
 
+   . = ALIGN(PAGE_SIZE);
+
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
INIT_DATA
}

base-commit: 2c85ebc57b3e1817b6ce1a6b703928e113a90442
-- 
2.17.1