APPLIED: [SRU][F][PATCH 0/1] CVE-2024-26960

Stefan Bader stefan.bader at canonical.com
Fri Sep 6 14:47:23 UTC 2024


On 05.09.24 08:36, Koichiro Den wrote:
> [Impact]
> 
> mm: swap: fix race between free_swap_and_cache() and swapoff()
> 
> There was previously a theoretical window where swapoff() could run and
> teardown a swap_info_struct while a call to free_swap_and_cache() was
> running in another thread.  This could cause, amongst other bad
> possibilities, swap_page_trans_huge_swapped() (called by
> free_swap_and_cache()) to access the freed memory for swap_map.
> 
> This is a theoretical problem and I haven't been able to provoke it from a
> test case.  But there has been agreement based on code review that this is
> possible (see link below).
> 
> Fix it by using get_swap_device()/put_swap_device(), which will stall
> swapoff().  There was an extra check in _swap_info_get() to confirm that
> the swap entry was not free.  This isn't present in get_swap_device()
> because it doesn't make sense in general due to the race between getting
> the reference and swapoff.  So I've added an equivalent check directly in
> free_swap_and_cache().
> 
> Details of how to provoke one possible issue:
> 
> --8<-----
> 
> CPU0                               CPU1
> ----                               ----
> shmem_undo_range
>    shmem_free_swap
>      xa_cmpxchg_irq
>      free_swap_and_cache
>        __swap_entry_free
>        /* swap_count() become 0 */
>                                     swapoff
>                                       try_to_unuse
>                                         shmem_unuse /* cannot find swap entry */
>                                         find_next_to_unuse
>                                         filemap_get_folio
>                                         folio_free_swap
>                                         /* remove swap cache */
>                                         /* free si->swap_map[] */
>        swap_page_trans_huge_swapped <-- access freed si->swap_map !!!
> 
> --8<-----
> 
> [Backport]
> 
> First and foremost, the follow-up v3 patch [1] offered a clearer description
> of the potential race condition and also removed an incorrect comment.
> However, it did not make it to mm-stable, while the v2 patch was merged.
> Later, the comment was revised in [2], which depends on commit
> a95722a04772 ("swap: comments get_swap_device() with usage rule").
> As this is a CVE backport patch, we typically do not merge such comment
> improvements; hence we are merging [1] only.
> 
> Additionally, there were conflicts due to missing commits:
> - commit 33e16272fe98 ("mm/swapfile.c: __swap_entry_free() always free 1 entry")
> - commit a95722a04772 ("swap: comments get_swap_device() with usage rule")
> 
> I resolved these conflicts by adjusting contexts without merging the commits.
> 
> [1] https://lore.kernel.org/all/20240311084426.447164-1-ying.huang@intel.com/
> [2] https://lkml.kernel.org/r/20240407065450.498821-1-ying.huang@intel.com
> 
> [Fix]
> 
> Noble:  fixed via stable
> Jammy:  fixed via stable
> Focal:  Backport - adjusted contexts due to missing commits, see [Backport]
> Bionic: fix sent to esm ML
> Xenial: not affected
> Trusty: not affected
> 
> [Test case]
> 
> Compile and boot tested.
> 
> Additionally, this backport was stress tested by the following procedure
> on my amd64 kvm setup with 8GB RAM. Despite extensive testing, the issue
> could not be reproduced on the kernel without this backport, likely due
> to the narrow race window and the fact that it's hard to make it happen
> so frequently. Still, this proved the robustness of the backport patch.
> 
>    # Create swap file
>    sudo fallocate -l 4G /swapfile
>    sudo chmod 600 /swapfile
>    sudo mkswap /swapfile
>    sudo mount -o remount,size=7G /dev/shm
> 
>    # Test script
>    $ cat ~/test.sh
>    #!/bin/bash
>    sudo swapon /swapfile
>    cat /dev/urandom > /dev/shm/test
>    # trigger shmem_undo_range -> free_swap_and_cache
>    echo > /dev/shm/test &
>    # try to swapoff
>    while ! sudo swapoff /swapfile; do
>      :
>    done
> 
>    # Run
>    $ while :; do ./test.sh; done
> 
> [Where problem could occur]
> 
> This fix affects all architectures and is generic in nature. It
> addresses a potential UAF that could occur if, during final
> free_swap_and_cache() for shm, a swapoff operation subtly slips in and
> frees the swap_map before swap_page_trans_huge_swapped() is invoked.
> 
> Ryan Roberts (1):
>    mm: swap: fix race between free_swap_and_cache() and swapoff()
> 
>   mm/swapfile.c | 8 +++++++-
>   1 file changed, 7 insertions(+), 1 deletion(-)
> 

Applied to focal:linux/master-next. Thanks.

-Stefan

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE8675DEECBEECEA3.asc
Type: application/pgp-keys
Size: 48643 bytes
Desc: OpenPGP public key
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20240906/827ea819/attachment-0001.key>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20240906/827ea819/attachment-0001.sig>


More information about the kernel-team mailing list