• Krzysztof Kozlowski's avatar
    swap: fix set_blocksize race during swapon/swapoff · 5b808a23
    Krzysztof Kozlowski authored
    Fix race between swapoff and swapon.  Swapoff used old_block_size from
    swap_info outside of swapon_mutex so it could be overwritten by
    concurrent swapon.
    
    The race has visible effect only if more than one swap block device
    exists with different block sizes (e.g.  /dev/sda1 with block size 4096
    and /dev/sdb1 with 512).  In such case it leads to setting the blocksize
    of swapped off device with wrong blocksize.
    
    The bug can be triggered with multiple concurrent swapoff and swapon:
    0. Swap for some device is on.
    1. swapoff:
    First the swapoff is called on this device and "struct swap_info_struct
    *p" is assigned. This is done under swap_lock however this lock is
    released for the call try_to_unuse().
    
    2. swapon:
    After the assignment above (and before acquiring swapon_mutex &
    swap_lock by swapoff) the swapon is called on the same device.
    The p->old_block_size is assigned to the value of block_size the device.
    This block size should be the same as previous but sometimes it is not.
    The swapon ends successfully.
    
    3. swapoff:
    Swapoff resumes, grabs the locks and mutex and continues to disable this
    swap device. Now it sets the block size to value taken from swap_info
    which was overwritten by swapon in 2.
    Signed-off-by: default avatarKrzysztof Kozlowski <k.kozlowski@samsung.com>
    Reported-by: default avatarWeijie Yang <weijie.yang.kh@gmail.com>
    Cc: Bob Liu <bob.liu@oracle.com>
    Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
    Cc: Shaohua Li <shli@fusionio.com>
    Cc: Minchan Kim <minchan@kernel.org>
    Acked-by: default avatarHugh Dickins <hughd@google.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    5b808a23
swapfile.c 76.5 KB