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>