core_kernel_text() considers that until system_state in at least
SYSTEM_RUNNING, init memory is valid.
But init memory is freed a few lines before setting SYSTEM_RUNNING,
so we have a small period of time when core_kernel_text() is wrong.
Create an intermediate system state called SYSTEM_FREEING_INIT that
is set before starting freeing init memory, and use it in
core_kernel_text() to report init memory invalid earlier.
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Kefeng Wang <redacted>
Signed-off-by: Christophe Leroy <redacted>
---
v3: No change
v2: New
---
include/linux/kernel.h | 1 +
init/main.c | 2 ++
kernel/extable.c | 2 +-
3 files changed, 4 insertions(+), 1 deletion(-)
@@ -1505,6 +1505,8 @@ static int __ref kernel_init(void *unused)kernel_init_freeable();/* need to finish all async __init code before freeing the memory */async_synchronize_full();++system_state=SYSTEM_FREEING_INITMEM;kprobe_free_init_mem();ftrace_free_init_mem();kgdb_free_init_mem();
@@ -76,7 +76,7 @@ int notrace core_kernel_text(unsigned long addr)addr<(unsignedlong)_etext)return1;-if(system_state<SYSTEM_RUNNING&&+if(system_state<SYSTEM_FREEING_INITMEM&&init_kernel_text(addr))return1;return0;
Generic version of arch_is_kernel_initmem_freed() now does the same
as powerpc version.
Remove the powerpc version.
Cc: Kefeng Wang <redacted>
Signed-off-by: Christophe Leroy <redacted>
---
v3: No change
v2: No change
---
arch/powerpc/include/asm/sections.h | 13 -------------
1 file changed, 13 deletions(-)
Commit 7a5da02de8d6 ("locking/lockdep: check for freed initmem in
static_obj()") added arch_is_kernel_initmem_freed() which is supposed
to report whether an object is part of already freed init memory.
For the time being, the generic version of arch_is_kernel_initmem_freed()
always reports 'false', allthough free_initmem() is generically called
on all architectures.
Therefore, change the generic version of arch_is_kernel_initmem_freed()
to check whether free_initmem() has been called. If so, then check
if a given address falls into init memory.
To ease the use of system_state, move it out of line into its only
caller which is lockdep.c
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Kefeng Wang <redacted>
Signed-off-by: Christophe Leroy <redacted>
---
v3: Move it out of sections.h into lockdep.c and fix the comment.
v2: Change to using the new SYSTEM_FREEING_INITMEM state
Signed-off-by: Christophe Leroy <redacted>
---
include/asm-generic/sections.h | 14 --------------
kernel/locking/lockdep.c | 15 +++++++++++++++
2 files changed, 15 insertions(+), 14 deletions(-)
From: Daniel Axtens <hidden> Date: 2021-10-01 07:14:48
#ifdef __KERNEL__
+/*
+ * Check if an address is part of freed initmem. After initmem is freed,
+ * memory can be allocated from it, and such allocations would then have
+ * addresses within the range [_stext, _end].
+ */
+#ifndef arch_is_kernel_initmem_freed
+static int arch_is_kernel_initmem_freed(unsigned long addr)
+{
+ if (system_state < SYSTEM_FREEING_INITMEM)
+ return 0;
+
+ return init_section_contains((void *)addr, 1);
Is init_section_contains sufficient here?
include/asm-generic/sections.h says:
* [__init_begin, __init_end]: contains .init.* sections, but .init.text.*
* may be out of this range on some architectures.
* [_sinittext, _einittext]: contains .init.text.* sections
init_section_contains only checks __init_*:
static inline bool init_section_contains(void *virt, size_t size)
{
return memory_contains(__init_begin, __init_end, virt, size);
}
Do we need to check against _sinittext and _einittext?
Your proposed generic code will work for powerpc and s390 because those
archs only test against __init_* anyway. I don't know if any platform
actually does place .init.text outside of __init_begin=>__init_end, but
the comment seems to suggest that they could.
Kind regards,
Daniel
From: Andrew Morton <akpm@linux-foundation.org> Date: 2021-11-04 21:44:49
On Fri, 01 Oct 2021 17:14:41 +1000 Daniel Axtens [off-list ref] wrote:
quoted
#ifdef __KERNEL__
+/*
+ * Check if an address is part of freed initmem. After initmem is freed,
+ * memory can be allocated from it, and such allocations would then have
+ * addresses within the range [_stext, _end].
+ */
+#ifndef arch_is_kernel_initmem_freed
+static int arch_is_kernel_initmem_freed(unsigned long addr)
+{
+ if (system_state < SYSTEM_FREEING_INITMEM)
+ return 0;
+
+ return init_section_contains((void *)addr, 1);
Is init_section_contains sufficient here?
include/asm-generic/sections.h says:
* [__init_begin, __init_end]: contains .init.* sections, but .init.text.*
* may be out of this range on some architectures.
* [_sinittext, _einittext]: contains .init.text.* sections
init_section_contains only checks __init_*:
static inline bool init_section_contains(void *virt, size_t size)
{
return memory_contains(__init_begin, __init_end, virt, size);
}
Do we need to check against _sinittext and _einittext?
Your proposed generic code will work for powerpc and s390 because those
archs only test against __init_* anyway. I don't know if any platform
actually does place .init.text outside of __init_begin=>__init_end, but
the comment seems to suggest that they could.
On Fri, 01 Oct 2021 17:14:41 +1000 Daniel Axtens [off-list ref] wrote:
quoted
quoted
#ifdef __KERNEL__
+/*
+ * Check if an address is part of freed initmem. After initmem is freed,
+ * memory can be allocated from it, and such allocations would then have
+ * addresses within the range [_stext, _end].
+ */
+#ifndef arch_is_kernel_initmem_freed
+static int arch_is_kernel_initmem_freed(unsigned long addr)
+{
+ if (system_state < SYSTEM_FREEING_INITMEM)
+ return 0;
+
+ return init_section_contains((void *)addr, 1);
Is init_section_contains sufficient here?
include/asm-generic/sections.h says:
* [__init_begin, __init_end]: contains .init.* sections, but .init.text.*
* may be out of this range on some architectures.
* [_sinittext, _einittext]: contains .init.text.* sections
init_section_contains only checks __init_*:
static inline bool init_section_contains(void *virt, size_t size)
{
return memory_contains(__init_begin, __init_end, virt, size);
}
Do we need to check against _sinittext and _einittext?
Your proposed generic code will work for powerpc and s390 because those
archs only test against __init_* anyway. I don't know if any platform
actually does place .init.text outside of __init_begin=>__init_end, but
the comment seems to suggest that they could.
Christophe?
Sorry for answering late.
I've been thorugh free_initmem() in each architecture. The only sections
involved in the freeing actions are [__init_begin, __init_end], so I
think checking against __init_being, __init_end is enough.
If some architecture has init text outside of this section, then it is
not freed hence not necessary to check.
Christophe
Generic version of arch_is_kernel_initmem_freed() now does the same
as s390 version.
Remove the s390 version.
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Kefeng Wang <redacted>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Christophe Leroy <redacted>
---
v3: No change
v2: No change
---
arch/s390/include/asm/sections.h | 12 ------------
arch/s390/mm/init.c | 3 ---
2 files changed, 15 deletions(-)