Re: [PATCH] mm/migrate: fix page state accounting type conversion underflow

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jul 22, 2021 at 03:48:40PM +1000, Nicholas Piggin wrote:
> Similarly to commit 2da9f6305f306 ("mm/vmscan: fix NR_ISOLATED_FILE
> corruption on 64-bit"), fix -ve int -> unsigned int -> long bug.
> 
> Reported-by: Alexey Kardashevskiy <aik@xxxxxxxxx>
> Fixes: c5fc5c3ae0c84 ("mm: migrate: account THP NUMA migration counters correctly")
> Signed-off-by: Nicholas Piggin <npiggin@xxxxxxxxx>
> ---
>  mm/migrate.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/mm/migrate.c b/mm/migrate.c
> index 34a9ad3e0a4f..7e240437e7d9 100644
> --- a/mm/migrate.c
> +++ b/mm/migrate.c
> @@ -2068,7 +2068,7 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
>  	LIST_HEAD(migratepages);
>  	new_page_t *new;
>  	bool compound;
> -	unsigned int nr_pages = thp_nr_pages(page);
> +	int nr_pages = thp_nr_pages(page);

This has prompted me to go off and look through the folio work.  There
are a number of similar problems.  It's sad that gcc doesn't have a
warning that catched this (although Clang does!)  I've filed

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101645

In the meantime, I'm going to change:

 - folio_nr_pages() now returns 'long' instead of 'unsigned long'.
 - Everywhere that assigns it to a variable changes its type from 'int'
   or 'unsigned int' or 'unsigned long' to 'long'.

The only place this looks a little dodgy is:

+static inline bool folio_contains(struct folio *folio, pgoff_t index)
+{
+       /* HugeTLBfs indexes the page cache in units of hpage_size */
+       if (folio_test_hugetlb(folio))
+               return folio->index == index;
+       return index - folio_index(folio) < folio_nr_pages(folio);
+}

but i'm pretty sure that's OK because index & folio_index are
both unsigned long, and by my reading of the C spec, that
promotes long to unsigned long, and so we do an unsigned comparison
(meaning that index 3, folio_index() 4 will wrap around to ULONG_MAX
and the comparison will return false, as expected.

I also intend to change update_lru_size() to take a long.

This patch is insufficient ... mem_cgroup_move_account() has the same bug.
I'm not quite sure how to handle this patch -- I'm going to replace all
this in 5.15, but this should be backported to earlier kernels.




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux