linux/net/rxrpc
David Howells 330bdcfadc rxrpc: Fix the keepalive generator [ver #2]
AF_RXRPC has a keepalive message generator that generates a message for a
peer ~20s after the last transmission to that peer to keep firewall ports
open.  The implementation is incorrect in the following ways:

 (1) It mixes up ktime_t and time64_t types.

 (2) It uses ktime_get_real(), the output of which may jump forward or
     backward due to adjustments to the time of day.

 (3) If the current time jumps forward too much or jumps backwards, the
     generator function will crank the base of the time ring round one slot
     at a time (ie. a 1s period) until it catches up, spewing out VERSION
     packets as it goes.

Fix the problem by:

 (1) Only using time64_t.  There's no need for sub-second resolution.

 (2) Use ktime_get_seconds() rather than ktime_get_real() so that time
     isn't perceived to go backwards.

 (3) Simplifying rxrpc_peer_keepalive_worker() by splitting it into two
     parts:

     (a) The "worker" function that manages the buckets and the timer.

     (b) The "dispatch" function that takes the pending peers and
     	 potentially transmits a keepalive packet before putting them back
     	 in the ring into the slot appropriate to the revised last-Tx time.

 (4) Taking everything that's pending out of the ring and splicing it into
     a temporary collector list for processing.

     In the case that there's been a significant jump forward, the ring
     gets entirely emptied and then the time base can be warped forward
     before the peers are processed.

     The warping can't happen if the ring isn't empty because the slot a
     peer is in is keepalive-time dependent, relative to the base time.

 (5) Limit the number of iterations of the bucket array when scanning it.

 (6) Set the timer to skip any empty slots as there's no point waking up if
     there's nothing to do yet.

This can be triggered by an incoming call from a server after a reboot with
AF_RXRPC and AFS built into the kernel causing a peer record to be set up
before userspace is started.  The system clock is then adjusted by
userspace, thereby potentially causing the keepalive generator to have a
meltdown - which leads to a message like:

	watchdog: BUG: soft lockup - CPU#0 stuck for 23s! [kworker/0:1:23]
	...
	Workqueue: krxrpcd rxrpc_peer_keepalive_worker
	EIP: lock_acquire+0x69/0x80
	...
	Call Trace:
	 ? rxrpc_peer_keepalive_worker+0x5e/0x350
	 ? _raw_spin_lock_bh+0x29/0x60
	 ? rxrpc_peer_keepalive_worker+0x5e/0x350
	 ? rxrpc_peer_keepalive_worker+0x5e/0x350
	 ? __lock_acquire+0x3d3/0x870
	 ? process_one_work+0x110/0x340
	 ? process_one_work+0x166/0x340
	 ? process_one_work+0x110/0x340
	 ? worker_thread+0x39/0x3c0
	 ? kthread+0xdb/0x110
	 ? cancel_delayed_work+0x90/0x90
	 ? kthread_stop+0x70/0x70
	 ? ret_from_fork+0x19/0x24

Fixes: ace45bec6d ("rxrpc: Fix firewall route keepalive")
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-08-08 19:10:26 -07:00
..
af_rxrpc.c Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL 2018-06-28 10:40:47 -07:00
ar-internal.h rxrpc: Fix the keepalive generator [ver #2] 2018-08-08 19:10:26 -07:00
call_accept.c rxrpc: Fix user call ID check in rxrpc_service_prealloc_one 2018-08-01 11:49:49 -07:00
call_event.c rxrpc: Fix handling of call quietly cancelled out on server 2018-06-04 16:06:26 -04:00
call_object.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2018-04-03 14:04:18 -07:00
conn_client.c rxrpc: Fix apparent leak of rxrpc_local objects 2018-03-30 21:05:33 +01:00
conn_event.c rxrpc: Fix the keepalive generator [ver #2] 2018-08-08 19:10:26 -07:00
conn_object.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2018-04-03 14:04:18 -07:00
conn_service.c rxrpc: Fix apparent leak of rxrpc_local objects 2018-03-30 21:05:33 +01:00
input.c rxrpc: Fix handling of call quietly cancelled out on server 2018-06-04 16:06:26 -04:00
insecure.c rxrpc: Trace protocol errors in received packets 2017-04-06 11:09:39 +01:00
Kconfig rxrpc: Add config to inject packet loss 2016-09-17 11:24:04 +01:00
key.c rxrpc: Use correct timestamp from Kerberos 5 ticket 2017-08-29 10:55:06 +01:00
local_event.c rxrpc: Trace UDP transmission failure 2018-05-10 23:26:01 +01:00
local_object.c rxrpc: Fix error reception on AF_INET6 sockets 2018-05-10 23:26:00 +01:00
Makefile License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
misc.c rxrpc: Fix call timeouts 2017-11-24 10:18:41 +00:00
net_ns.c rxrpc: Fix the keepalive generator [ver #2] 2018-08-08 19:10:26 -07:00
output.c rxrpc: Fix the keepalive generator [ver #2] 2018-08-08 19:10:26 -07:00
peer_event.c rxrpc: Fix the keepalive generator [ver #2] 2018-08-08 19:10:26 -07:00
peer_object.c rxrpc: Fix the keepalive generator [ver #2] 2018-08-08 19:10:26 -07:00
proc.c proc: introduce proc_create_net{,_data} 2018-05-16 07:24:30 +02:00
protocol.h rxrpc: Fix undefined packet handling 2018-04-04 11:04:08 -04:00
recvmsg.c rxrpc: remove redundant initialization of variable 'len' 2018-03-16 09:48:39 -04:00
rxkad.c rxrpc: Fix the keepalive generator [ver #2] 2018-08-08 19:10:26 -07:00
security.c rxrpc: remove unused static variables 2018-03-30 21:04:44 +01:00
sendmsg.c rxrpc: Fix missing start of call timeout 2018-05-10 23:26:00 +01:00
skbuff.c net: convert sk_buff.users from atomic_t to refcount_t 2017-07-01 07:39:07 -07:00
sysctl.c rxrpc: Fix call timeouts 2017-11-24 10:18:41 +00:00
utils.c rxrpc: Fix IPv6 support 2017-08-29 10:55:20 +01:00