Skip to content

Commit

Permalink
mm/swap: fix race on swap_info reuse between swapoff and swapon
Browse files Browse the repository at this point in the history
swapoff clear swap_info's SWP_USED flag prematurely and free its
resources after that.  A concurrent swapon will reuse this swap_info
while its previous resources are not cleared completely.

These late freed resources are:
 - p->percpu_cluster
 - swap_cgroup_ctrl[type]
 - block_device setting
 - inode->i_flags &= ~S_SWAPFILE

This patch clears the SWP_USED flag after all its resources are freed,
so that swapon can reuse this swap_info by alloc_swap_info() safely.

[[email protected]: tidy up code comment]
Signed-off-by: Weijie Yang <[email protected]>
Acked-by: Hugh Dickins <[email protected]>
Cc: Krzysztof Kozlowski <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Weijie Yang authored and torvalds committed Feb 6, 2014
1 parent 579f829 commit f893ab4
Showing 1 changed file with 10 additions and 1 deletion.
11 changes: 10 additions & 1 deletion mm/swapfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
p->swap_map = NULL;
cluster_info = p->cluster_info;
p->cluster_info = NULL;
p->flags = 0;
frontswap_map = frontswap_map_get(p);
spin_unlock(&p->lock);
spin_unlock(&swap_lock);
Expand All @@ -1949,6 +1948,16 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
mutex_unlock(&inode->i_mutex);
}
filp_close(swap_file, NULL);

/*
* Clear the SWP_USED flag after all resources are freed so that swapon
* can reuse this swap_info in alloc_swap_info() safely. It is ok to
* not hold p->lock after we cleared its SWP_WRITEOK.
*/
spin_lock(&swap_lock);
p->flags = 0;
spin_unlock(&swap_lock);

err = 0;
atomic_inc(&proc_poll_event);
wake_up_interruptible(&proc_poll_wait);
Expand Down

0 comments on commit f893ab4

Please sign in to comment.