Skip to content

Commit

Permalink
kernel/power: allow hibernation with page_poison sanity checking
Browse files Browse the repository at this point in the history
Page poisoning used to be incompatible with hibernation, as the state of
poisoned pages was lost after resume, thus enabling CONFIG_HIBERNATION
forces CONFIG_PAGE_POISONING_NO_SANITY.  For the same reason, the
poisoning with zeroes variant CONFIG_PAGE_POISONING_ZERO used to disable
hibernation.  The latter restriction was removed by commit 1ad1410
("PM / Hibernate: allow hibernation with PAGE_POISONING_ZERO") and
similarly for init_on_free by commit 18451f9 ("PM: hibernate: fix
crashes with init_on_free=1") by making sure free pages are cleared after
resume.

We can use the same mechanism to instead poison free pages with
PAGE_POISON after resume.  This covers both zero and 0xAA patterns.  Thus
we can remove the Kconfig restriction that disables page poison sanity
checking when hibernation is enabled.

Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Vlastimil Babka <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]>	[hibernation]
Reviewed-by: David Hildenbrand <[email protected]>
Cc: Mike Rapoport <[email protected]>
Cc: Alexander Potapenko <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Laura Abbott <[email protected]>
Cc: Mateusz Nosek <[email protected]>
Cc: Michal Hocko <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
tehcaster authored and torvalds committed Dec 15, 2020
1 parent 8db26a3 commit 03b6c9a
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 6 deletions.
1 change: 1 addition & 0 deletions include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2903,6 +2903,7 @@ static inline void kernel_unpoison_pages(struct page *page, int numpages)
#else
static inline bool page_poisoning_enabled(void) { return false; }
static inline bool page_poisoning_enabled_static(void) { return false; }
static inline void __kernel_poison_pages(struct page *page, int nunmpages) { }
static inline void kernel_poison_pages(struct page *page, int numpages) { }
static inline void kernel_unpoison_pages(struct page *page, int numpages) { }
#endif
Expand Down
2 changes: 1 addition & 1 deletion kernel/power/hibernate.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ static int create_image(int platform_mode)

if (!in_suspend) {
events_check_enabled = false;
clear_free_pages();
clear_or_poison_free_pages();
}

platform_leave(platform_mode);
Expand Down
2 changes: 1 addition & 1 deletion kernel/power/power.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ extern int create_basic_memory_bitmaps(void);
extern void free_basic_memory_bitmaps(void);
extern int hibernate_preallocate_memory(void);

extern void clear_free_pages(void);
extern void clear_or_poison_free_pages(void);

/**
* Auxiliary structure used for reading the snapshot image data and
Expand Down
14 changes: 11 additions & 3 deletions kernel/power/snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1178,20 +1178,28 @@ void free_basic_memory_bitmaps(void)
pr_debug("Basic memory bitmaps freed\n");
}

void clear_free_pages(void)
static void clear_or_poison_free_page(struct page *page)
{
if (page_poisoning_enabled_static())
__kernel_poison_pages(page, 1);
else if (want_init_on_free())
clear_highpage(page);
}

void clear_or_poison_free_pages(void)
{
struct memory_bitmap *bm = free_pages_map;
unsigned long pfn;

if (WARN_ON(!(free_pages_map)))
return;

if (IS_ENABLED(CONFIG_PAGE_POISONING_ZERO) || want_init_on_free()) {
if (page_poisoning_enabled() || want_init_on_free()) {
memory_bm_position_reset(bm);
pfn = memory_bm_next_pfn(bm);
while (pfn != BM_END_OF_MAP) {
if (pfn_valid(pfn))
clear_highpage(pfn_to_page(pfn));
clear_or_poison_free_page(pfn_to_page(pfn));

pfn = memory_bm_next_pfn(bm);
}
Expand Down
1 change: 0 additions & 1 deletion mm/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ config PAGE_OWNER

config PAGE_POISONING
bool "Poison pages after freeing"
select PAGE_POISONING_NO_SANITY if HIBERNATION
help
Fill the pages with poison patterns after free_pages() and verify
the patterns before alloc_pages. The filling of the memory helps
Expand Down

0 comments on commit 03b6c9a

Please sign in to comment.