rxrpc: Use skb_unshare() rather than skb_cow_data()
authorDavid Howells <dhowells@redhat.com>
Tue, 27 Aug 2019 09:13:46 +0000 (10:13 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 27 Aug 2019 09:13:46 +0000 (10:13 +0100)
commitd0d5c0cd1e711c98703f3544c1e6fc1372898de5
treee4070af80e16dca846e4734574270ff08ec65e74
parent987db9f7cd1e77e611b770a569068c43949aa6fd
rxrpc: Use skb_unshare() rather than skb_cow_data()

The in-place decryption routines in AF_RXRPC's rxkad security module
currently call skb_cow_data() to make sure the data isn't shared and that
the skb can be written over.  This has a problem, however, as the softirq
handler may be still holding a ref or the Rx ring may be holding multiple
refs when skb_cow_data() is called in rxkad_verify_packet() - and so
skb_shared() returns true and __pskb_pull_tail() dislikes that.  If this
occurs, something like the following report will be generated.

kernel BUG at net/core/skbuff.c:1463!
...
RIP: 0010:pskb_expand_head+0x253/0x2b0
...
Call Trace:
 __pskb_pull_tail+0x49/0x460
 skb_cow_data+0x6f/0x300
 rxkad_verify_packet+0x18b/0xb10 [rxrpc]
 rxrpc_recvmsg_data.isra.11+0x4a8/0xa10 [rxrpc]
 rxrpc_kernel_recv_data+0x126/0x240 [rxrpc]
 afs_extract_data+0x51/0x2d0 [kafs]
 afs_deliver_fs_fetch_data+0x188/0x400 [kafs]
 afs_deliver_to_call+0xac/0x430 [kafs]
 afs_wait_for_call_to_complete+0x22f/0x3d0 [kafs]
 afs_make_call+0x282/0x3f0 [kafs]
 afs_fs_fetch_data+0x164/0x300 [kafs]
 afs_fetch_data+0x54/0x130 [kafs]
 afs_readpages+0x20d/0x340 [kafs]
 read_pages+0x66/0x180
 __do_page_cache_readahead+0x188/0x1a0
 ondemand_readahead+0x17d/0x2e0
 generic_file_read_iter+0x740/0xc10
 __vfs_read+0x145/0x1a0
 vfs_read+0x8c/0x140
 ksys_read+0x4a/0xb0
 do_syscall_64+0x43/0xf0
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Fix this by using skb_unshare() instead in the input path for DATA packets
that have a security index != 0.  Non-DATA packets don't need in-place
encryption and neither do unencrypted DATA packets.

Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
Reported-by: Julian Wollrath <jwollrath@web.de>
Signed-off-by: David Howells <dhowells@redhat.com>
include/trace/events/rxrpc.h
net/rxrpc/ar-internal.h
net/rxrpc/input.c
net/rxrpc/rxkad.c
net/rxrpc/skbuff.c