Skip to content

Commit 3848e96

Browse files
neilbrownTrond Myklebust
authored andcommitted
SUNRPC: avoid race between mod_timer() and del_timer_sync()
xprt_destory() claims XPRT_LOCKED and then calls del_timer_sync(). Both xprt_unlock_connect() and xprt_release() call ->release_xprt() which drops XPRT_LOCKED and *then* xprt_schedule_autodisconnect() which calls mod_timer(). This may result in mod_timer() being called *after* del_timer_sync(). When this happens, the timer may fire long after the xprt has been freed, and run_timer_softirq() will probably crash. The pairing of ->release_xprt() and xprt_schedule_autodisconnect() is always called under ->transport_lock. So if we take ->transport_lock to call del_timer_sync(), we can be sure that mod_timer() will run first (if it runs at all). Cc: stable@vger.kernel.org Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent a245832 commit 3848e96

1 file changed

Lines changed: 7 additions & 0 deletions

File tree

net/sunrpc/xprt.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,7 +2104,14 @@ static void xprt_destroy(struct rpc_xprt *xprt)
21042104
*/
21052105
wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);
21062106

2107+
/*
2108+
* xprt_schedule_autodisconnect() can run after XPRT_LOCKED
2109+
* is cleared. We use ->transport_lock to ensure the mod_timer()
2110+
* can only run *before* del_time_sync(), never after.
2111+
*/
2112+
spin_lock(&xprt->transport_lock);
21072113
del_timer_sync(&xprt->timer);
2114+
spin_unlock(&xprt->transport_lock);
21082115

21092116
/*
21102117
* Destroy sockets etc from the system workqueue so they can

0 commit comments

Comments
 (0)