All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
To: Xin Long <lucien.xin@gmail.com>
Cc: network dev <netdev@vger.kernel.org>,
	linux-sctp@vger.kernel.org, davem@davemloft.net,
	Neil Horman <nhorman@tuxdriver.com>,
	Vlad Yasevich <vyasevich@gmail.com>,
	Dmitry Vyukov <dvyukov@google.com>,
	chunwang@redhat.com, syzkaller@googlegroups.com
Subject: Re: [PATCH net] sctp: reset owner sk for data chunks on out queues when migrating a sock
Date: Fri, 27 Oct 2017 21:53:37 +0000	[thread overview]
Message-ID: <20171027215337.GA3675@localhost.localdomain> (raw)
In-Reply-To: <38df739211708b6a1e983809f7e17539111718c7.1509128009.git.lucien.xin@gmail.com>

On Sat, Oct 28, 2017 at 02:13:29AM +0800, Xin Long wrote:
> Now when migrating sock to another one in sctp_sock_migrate(), it only
> resets owner sk for the data in receive queues, not the chunks on out
> queues.
> 
> It would cause that data chunks length on the sock is not consistent
> with sk sk_wmem_alloc. When closing the sock or freeing these chunks,
> the old sk would never be freed, and the new sock may crash due to
> the overflow sk_wmem_alloc.
> 
> syzbot found this issue with this series:
> 
>   r0 = socket$inet_sctp()
>   sendto$inet(r0)
>   listen(r0)
>   accept4(r0)
>   close(r0)
> 
> Although listen() should have returned error when one TCP-style socket
> is in connecting (I may fix this one in another patch), it could also
> be reproduced by peeling off an assoc.
> 
> This issue is there since very beginning.
> 
> This patch is to reset owner sk for the chunks on out queues so that
> sk sk_wmem_alloc has correct value after accept one sock or peeloff
> an assoc to one sock.
> 
> Note that when resetting owner sk for chunks on outqueue, it has to
> sctp_clear_owner_w/skb_orphan chunks before changing assoc->base.sk
> first and then sctp_set_owner_w them after changing assoc->base.sk,
> due to that sctp_wfree and it's callees are using assoc->base.sk.
> 
> Reported-by: Dmitry Vyukov <dvyukov@google.com>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

> ---
>  net/sctp/socket.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 17841ab..6f45d17 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -170,6 +170,36 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
>  	sk_mem_charge(sk, chunk->skb->truesize);
>  }
>  
> +static void sctp_clear_owner_w(struct sctp_chunk *chunk)
> +{
> +	skb_orphan(chunk->skb);
> +}
> +
> +static void sctp_for_each_tx_datachunk(struct sctp_association *asoc,
> +				       void (*cb)(struct sctp_chunk *))
> +
> +{
> +	struct sctp_outq *q = &asoc->outqueue;
> +	struct sctp_transport *t;
> +	struct sctp_chunk *chunk;
> +
> +	list_for_each_entry(t, &asoc->peer.transport_addr_list, transports)
> +		list_for_each_entry(chunk, &t->transmitted, transmitted_list)
> +			cb(chunk);
> +
> +	list_for_each_entry(chunk, &q->retransmit, list)
> +		cb(chunk);
> +
> +	list_for_each_entry(chunk, &q->sacked, list)
> +		cb(chunk);
> +
> +	list_for_each_entry(chunk, &q->abandoned, list)
> +		cb(chunk);
> +
> +	list_for_each_entry(chunk, &q->out_chunk_list, list)
> +		cb(chunk);
> +}
> +
>  /* Verify that this is a valid address. */
>  static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
>  				   int len)
> @@ -8212,7 +8242,9 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
>  	 * paths won't try to lock it and then oldsk.
>  	 */
>  	lock_sock_nested(newsk, SINGLE_DEPTH_NESTING);
> +	sctp_for_each_tx_datachunk(assoc, sctp_clear_owner_w);
>  	sctp_assoc_migrate(assoc, newsk);
> +	sctp_for_each_tx_datachunk(assoc, sctp_set_owner_w);
>  
>  	/* If the association on the newsk is already closed before accept()
>  	 * is called, set RCV_SHUTDOWN flag.
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

WARNING: multiple messages have this Message-ID (diff)
From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
To: Xin Long <lucien.xin@gmail.com>
Cc: network dev <netdev@vger.kernel.org>,
	linux-sctp@vger.kernel.org, davem@davemloft.net,
	Neil Horman <nhorman@tuxdriver.com>,
	Vlad Yasevich <vyasevich@gmail.com>,
	Dmitry Vyukov <dvyukov@google.com>,
	chunwang@redhat.com, syzkaller@googlegroups.com
Subject: Re: [PATCH net] sctp: reset owner sk for data chunks on out queues when migrating a sock
Date: Fri, 27 Oct 2017 19:53:37 -0200	[thread overview]
Message-ID: <20171027215337.GA3675@localhost.localdomain> (raw)
In-Reply-To: <38df739211708b6a1e983809f7e17539111718c7.1509128009.git.lucien.xin@gmail.com>

On Sat, Oct 28, 2017 at 02:13:29AM +0800, Xin Long wrote:
> Now when migrating sock to another one in sctp_sock_migrate(), it only
> resets owner sk for the data in receive queues, not the chunks on out
> queues.
> 
> It would cause that data chunks length on the sock is not consistent
> with sk sk_wmem_alloc. When closing the sock or freeing these chunks,
> the old sk would never be freed, and the new sock may crash due to
> the overflow sk_wmem_alloc.
> 
> syzbot found this issue with this series:
> 
>   r0 = socket$inet_sctp()
>   sendto$inet(r0)
>   listen(r0)
>   accept4(r0)
>   close(r0)
> 
> Although listen() should have returned error when one TCP-style socket
> is in connecting (I may fix this one in another patch), it could also
> be reproduced by peeling off an assoc.
> 
> This issue is there since very beginning.
> 
> This patch is to reset owner sk for the chunks on out queues so that
> sk sk_wmem_alloc has correct value after accept one sock or peeloff
> an assoc to one sock.
> 
> Note that when resetting owner sk for chunks on outqueue, it has to
> sctp_clear_owner_w/skb_orphan chunks before changing assoc->base.sk
> first and then sctp_set_owner_w them after changing assoc->base.sk,
> due to that sctp_wfree and it's callees are using assoc->base.sk.
> 
> Reported-by: Dmitry Vyukov <dvyukov@google.com>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

> ---
>  net/sctp/socket.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 17841ab..6f45d17 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -170,6 +170,36 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
>  	sk_mem_charge(sk, chunk->skb->truesize);
>  }
>  
> +static void sctp_clear_owner_w(struct sctp_chunk *chunk)
> +{
> +	skb_orphan(chunk->skb);
> +}
> +
> +static void sctp_for_each_tx_datachunk(struct sctp_association *asoc,
> +				       void (*cb)(struct sctp_chunk *))
> +
> +{
> +	struct sctp_outq *q = &asoc->outqueue;
> +	struct sctp_transport *t;
> +	struct sctp_chunk *chunk;
> +
> +	list_for_each_entry(t, &asoc->peer.transport_addr_list, transports)
> +		list_for_each_entry(chunk, &t->transmitted, transmitted_list)
> +			cb(chunk);
> +
> +	list_for_each_entry(chunk, &q->retransmit, list)
> +		cb(chunk);
> +
> +	list_for_each_entry(chunk, &q->sacked, list)
> +		cb(chunk);
> +
> +	list_for_each_entry(chunk, &q->abandoned, list)
> +		cb(chunk);
> +
> +	list_for_each_entry(chunk, &q->out_chunk_list, list)
> +		cb(chunk);
> +}
> +
>  /* Verify that this is a valid address. */
>  static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
>  				   int len)
> @@ -8212,7 +8242,9 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
>  	 * paths won't try to lock it and then oldsk.
>  	 */
>  	lock_sock_nested(newsk, SINGLE_DEPTH_NESTING);
> +	sctp_for_each_tx_datachunk(assoc, sctp_clear_owner_w);
>  	sctp_assoc_migrate(assoc, newsk);
> +	sctp_for_each_tx_datachunk(assoc, sctp_set_owner_w);
>  
>  	/* If the association on the newsk is already closed before accept()
>  	 * is called, set RCV_SHUTDOWN flag.
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

  reply	other threads:[~2017-10-27 21:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-27 18:13 [PATCH net] sctp: reset owner sk for data chunks on out queues when migrating a sock Xin Long
2017-10-27 18:13 ` Xin Long
2017-10-27 21:53 ` Marcelo Ricardo Leitner [this message]
2017-10-27 21:53   ` Marcelo Ricardo Leitner
2017-10-29  3:07 ` David Miller
2017-10-29  3:07   ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171027215337.GA3675@localhost.localdomain \
    --to=marcelo.leitner@gmail.com \
    --cc=chunwang@redhat.com \
    --cc=davem@davemloft.net \
    --cc=dvyukov@google.com \
    --cc=linux-sctp@vger.kernel.org \
    --cc=lucien.xin@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=nhorman@tuxdriver.com \
    --cc=syzkaller@googlegroups.com \
    --cc=vyasevich@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.