diff options
author | Xin Long <lucien.xin@gmail.com> | 2018-10-29 23:10:29 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-12-01 09:37:27 +0100 |
commit | cd947138e8c31e8cfcd489c12e9b97271beb6e79 (patch) | |
tree | ab5c7b5c400758316557ecd7f6d077f8613e832d /net/sctp | |
parent | 8380cbfe4eab437309da558ceb5404b7be4dfc7a (diff) | |
download | linux-rpi3-cd947138e8c31e8cfcd489c12e9b97271beb6e79.tar.gz linux-rpi3-cd947138e8c31e8cfcd489c12e9b97271beb6e79.tar.bz2 linux-rpi3-cd947138e8c31e8cfcd489c12e9b97271beb6e79.zip |
sctp: clear the transport of some out_chunk_list chunks in sctp_assoc_rm_peer
commit df132eff463873e14e019a07f387b4d577d6d1f9 upstream.
If a transport is removed by asconf but there still are some chunks with
this transport queuing on out_chunk_list, later an use-after-free issue
will be caused when accessing this transport from these chunks in
sctp_outq_flush().
This is an old bug, we fix it by clearing the transport of these chunks
in out_chunk_list when removing a transport in sctp_assoc_rm_peer().
Reported-by: syzbot+56a40ceee5fb35932f4d@syzkaller.appspotmail.com
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index a827a1f562bf..6a28b96e779e 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -499,8 +499,9 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, void sctp_assoc_rm_peer(struct sctp_association *asoc, struct sctp_transport *peer) { - struct list_head *pos; - struct sctp_transport *transport; + struct sctp_transport *transport; + struct list_head *pos; + struct sctp_chunk *ch; pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc, &peer->ipaddr.sa); @@ -564,7 +565,6 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, */ if (!list_empty(&peer->transmitted)) { struct sctp_transport *active = asoc->peer.active_path; - struct sctp_chunk *ch; /* Reset the transport of each chunk on this list */ list_for_each_entry(ch, &peer->transmitted, @@ -586,6 +586,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, sctp_transport_hold(active); } + list_for_each_entry(ch, &asoc->outqueue.out_chunk_list, list) + if (ch->transport == peer) + ch->transport = NULL; + asoc->peer.transport_count--; sctp_transport_free(peer); |