diff options
author | Tim Smith <tim@electronghost.co.uk> | 2014-01-26 11:39:28 +0000 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-01-26 11:45:04 +0000 |
commit | 24a9981ee9c7266fa171bbece62062bf78c4d246 (patch) | |
tree | badf59c77568a340dbd80e0b2c781260703cda02 /net | |
parent | 8f22ba61b5d730a870cd6b10d299d23280d060fa (diff) | |
download | op-kernel-dev-24a9981ee9c7266fa171bbece62062bf78c4d246.zip op-kernel-dev-24a9981ee9c7266fa171bbece62062bf78c4d246.tar.gz |
af_rxrpc: Avoid setting up double-free on checksum error
skb_kill_datagram() does not dequeue the skb when MSG_PEEK is unset.
This leaves a free'd skb on the queue, resulting a double-free later.
Without this, the following oops can occur:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
IP: [<ffffffff8154fcf7>] skb_dequeue+0x47/0x70
PGD 0
Oops: 0002 [#1] SMP
Modules linked in: af_rxrpc ...
CPU: 0 PID: 1191 Comm: listen Not tainted 3.12.0+ #4
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
task: ffff8801183536b0 ti: ffff880035c92000 task.ti: ffff880035c92000
RIP: 0010:[<ffffffff8154fcf7>] skb_dequeue+0x47/0x70
RSP: 0018:ffff880035c93db8 EFLAGS: 00010097
RAX: 0000000000000246 RBX: ffff8800d2754b00 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000202 RDI: ffff8800d254c084
RBP: ffff880035c93dd0 R08: ffff880035c93cf0 R09: ffff8800d968f270
R10: 0000000000000000 R11: 0000000000000293 R12: ffff8800d254c070
R13: ffff8800d254c084 R14: ffff8800cd861240 R15: ffff880119b39720
FS: 00007f37a969d740(0000) GS:ffff88011fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000008 CR3: 00000000d4413000 CR4: 00000000000006f0
Stack:
ffff8800d254c000 ffff8800d254c070 ffff8800d254c2c0 ffff880035c93df8
ffffffffa041a5b8 ffff8800cd844c80 ffffffffa04385a0 ffff8800cd844cb0
ffff880035c93e18 ffffffff81546cef ffff8800d45fea00 0000000000000008
Call Trace:
[<ffffffffa041a5b8>] rxrpc_release+0x128/0x2e0 [af_rxrpc]
[<ffffffff81546cef>] sock_release+0x1f/0x80
[<ffffffff81546d62>] sock_close+0x12/0x20
[<ffffffff811aaba1>] __fput+0xe1/0x230
[<ffffffff811aad3e>] ____fput+0xe/0x10
[<ffffffff810862cc>] task_work_run+0xbc/0xe0
[<ffffffff8106a3be>] do_exit+0x2be/0xa10
[<ffffffff8116dc47>] ? do_munmap+0x297/0x3b0
[<ffffffff8106ab8f>] do_group_exit+0x3f/0xa0
[<ffffffff8106ac04>] SyS_exit_group+0x14/0x20
[<ffffffff8166b069>] system_call_fastpath+0x16/0x1b
Signed-off-by: Tim Smith <tim@electronghost.co.uk>
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/rxrpc/ar-recvmsg.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c index 898492a..64cba2e 100644 --- a/net/rxrpc/ar-recvmsg.c +++ b/net/rxrpc/ar-recvmsg.c @@ -353,6 +353,10 @@ csum_copy_error: if (continue_call) rxrpc_put_call(continue_call); rxrpc_kill_skb(skb); + if (!(flags & MSG_PEEK)) { + if (skb_dequeue(&rx->sk.sk_receive_queue) != skb) + BUG(); + } skb_kill_datagram(&rx->sk, skb, flags); rxrpc_put_call(call); return -EAGAIN; |