Re: [PATCH 2/6] mm: swap: use correct step in loop to wait all clusters in wait_for_allocation()

From: Kairui Song
Date: Sat Feb 22 2025 - 12:33:13 EST


On Sat, Feb 22, 2025 at 3:12 PM Kemeng Shi <shikemeng@xxxxxxxxxxxxxxx> wrote:
>
> Use correct step in loop to wait all clusters in wait_for_allocation().
> If we miss some cluster in wait_for_allocation(), use after free may
> occurs as following:
> shmem_writepage swapoff
> folio_alloc_swap
> get_swap_pages
> scan_swap_map_slots
> cluster_alloc_swap_entry
> alloc_swap_scan_cluster
> cluster_alloc_range
> /* SWP_WRITEOK is valid */
> if (!(si->flags & SWP_WRITEOK))
>
> ...
> del_from_avail_list(p, true);
> ...
> /* miss the cluster in shmem_writepage */
> wait_for_allocation()
> ...
> try_to_unuse()
>
> memset(si->swap_map + start, usage, nr_pages);
> swap_range_alloc(si, nr_pages);
> ci->count += nr_pages;
> /* return a valid entry */
>
> ...
> exit_swap_address_space(p->type);
> ...
>
> ...
> add_to_swap_cache
> /* dereference swap_address_space(entry) which is NULL */
> xas_lock_irq(&xas);
>
> Fixes: e47bd46eab97e ("mm, swap: hold a reference during scan and cleanup flag usage")
> Signed-off-by: Kemeng Shi <shikemeng@xxxxxxxxxxxxxxx>
> ---
> mm/swapfile.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index e5f58ab86329..425126c0a07d 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -2627,7 +2627,6 @@ static void wait_for_allocation(struct swap_info_struct *si)
> for (offset = 0; offset < end; offset += SWAPFILE_CLUSTER) {
> ci = lock_cluster(si, offset);
> unlock_cluster(ci);
> - offset += SWAPFILE_CLUSTER;
> }
> }
>

Thanks, good catch.

Reviewed-by: Kairui Song <kasong@xxxxxxxxxxx>