Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c78676c authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan
Browse files

inet: Always increment refcount in inet_twsk_schedule



The following warning was seen after while repeatedly running a
stress test involving creation of multiple time_wait sockets.

[  287.547631] ODEBUG: free active (active state 0) object
type: timer_list hint: tw_timer_handler+0x0/0x68

This is because an active timer object is being freed. This leads to a
RCU stall coming from net stack which eventually results into BUG
softlockup.

Here is the list of events which lead to the free of the time_wait socket.

inet_twsk_alloc() tw->tw_refcnt 0 tw ffffffc03f3d0000 sk ffffffc0233f4c80
__inet_twsk_hashdance() tw->tw_refcnt 3 tw ffffffc03f3d0000
tcp_time_wait() inet_twsk_put tw->tw_refcnt 4 tw ffffffc03f3d0000
inet_twsk_put() tw->tw_refcnt 4 tw ffffffc03f3d0000
tcp_timewait_state_process() inet_twsk_schedule tw->tw_refcnt 3
tw ffffffc03f3d0000 skb ffffffc083124e00
TCP: tcp_v4_timewait_ack()  inet_twsk_put tw->tw_refcnt 3
tw ffffffc03f3d0000
inet_twsk_put() tw->tw_refcnt 3 tw ffffffc03f3d0000
tcp_timewait_state_process() inet_twsk_schedule tw->tw_refcnt 2
tw ffffffc03f3d0000 skb ffffffc0abc53c00
TCP: tcp_v4_timewait_ack()  inet_twsk_put tw->tw_refcnt 2
tw ffffffc03f3d0000
inet_twsk_put() tw->tw_refcnt 2 tw ffffffc03f3d0000
tcp_timewait_state_process() inet_twsk_schedule tw->tw_refcnt 1
tw ffffffc03f3d0000 skb ffffffc083124f00
TCP: tcp_timewait_state_processtcp_timewait_state_process() inet_twsk_put
tw->tw_refcnt 1 tw ffffffc03f3d0000
inet_twsk_put() tw->tw_refcnt 1 tw ffffffc03f3d0000
inet_twsk_put() tw->tw_refcnt 0 tw ffffffc03f3d0000

There seems to be a inet_twsk_put() following every schedule, so after the
stack receives 3 packets in time_wait state, the socket is destroyed even
if there is an active timer.

Fix this by incrementing the time_wait refcount in inet_twsk_schedule.
There should be no effective change in refcount after this since
inet_twsk_schedule is always followed by inet_twsk_put.

CRs-Fixed: 872281
Change-Id: Idce3f11df3b81019e73d5e375e166fda46109637
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
parent f9f5f0d7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -246,9 +246,9 @@ void inet_twsk_schedule(struct inet_timewait_sock *tw, const int timeo)

	tw->tw_kill = timeo <= 4*HZ;
	if (!mod_timer_pinned(&tw->tw_timer, jiffies + timeo)) {
		atomic_inc(&tw->tw_refcnt);
		atomic_inc(&tw->tw_dr->tw_count);
	}
	atomic_inc(&tw->tw_refcnt);
}
EXPORT_SYMBOL_GPL(inet_twsk_schedule);