From: Kuniyuki Iwashima <kuniyu@amazon.com>
To: <dmantipov@yandex.ru>
Cc: <dccp@vger.kernel.org>, <kuniyu@amazon.com>,
<netdev@vger.kernel.org>,
<syzbot+554ccde221001ab5479a@syzkaller.appspotmail.com>
Subject: Re: KASAN: use-after-free Read in ccid2_hc_tx_packet_recv
Date: Wed, 23 Oct 2024 10:51:21 -0700 [thread overview]
Message-ID: <20241023175121.36351-1-kuniyu@amazon.com> (raw)
In-Reply-To: <938106e0-269a-4d5a-995f-2314fecedb3a@yandex.ru>
From: Dmitry Antipov <dmantipov@yandex.ru>
Date: Wed, 23 Oct 2024 15:09:59 +0300
> Looking through https://syzkaller.appspot.com/bug?extid=554ccde221001ab5479a,
> I've found the problem which may be illustrated with the following patch:
>
> diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
> index 5926159a6f20..eb551872170c 100644
> --- a/net/dccp/ipv4.c
> +++ b/net/dccp/ipv4.c
> @@ -678,6 +678,7 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
>
> if (sk->sk_state == DCCP_OPEN) { /* Fast path */
> if (dccp_rcv_established(sk, skb, dh, skb->len))
> + /* Go to reset here */
> goto reset;
> return 0;
> }
> @@ -712,6 +713,7 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
>
> reset:
> dccp_v4_ctl_send_reset(sk, skb, SK_RST_REASON_NOT_SPECIFIED);
> + /* Freeing skb may leave dangling pointers in ack vectors */
> kfree_skb(skb);
> return 0;
> }
>
> I'm not an expert with DCCP protocol innards and have no idea whether ack
> vectors still needs to be processed after sending reset. But if it is so,
> the solution might be to copy all of the data from the relevant skbs instead
> of just saving the pointers, e.g.:
>
> diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
> index 1cba001bb4c8..24c6ad06d896 100644
> --- a/net/dccp/ackvec.c
> +++ b/net/dccp/ackvec.c
> @@ -347,17 +347,18 @@ void dccp_ackvec_clear_state(struct dccp_ackvec *av, const u64 ackno)
> }
>
> /*
> - * Routines to keep track of Ack Vectors received in an skb
> + * Routines to keep track of Ack Vectors copied from the received skb
> */
> int dccp_ackvec_parsed_add(struct list_head *head, u8 *vec, u8 len, u8 nonce)
> {
> - struct dccp_ackvec_parsed *new = kmalloc(sizeof(*new), GFP_ATOMIC);
> -
> + struct dccp_ackvec_parsed *new = kmalloc(struct_size(new, vec, len),
> + GFP_ATOMIC);
> if (new == NULL)
> return -ENOBUFS;
> - new->vec = vec;
> - new->len = len;
> +
> + new->len = len;
> new->nonce = nonce;
> + memcpy(new->vec, vec, len);
>
> list_add_tail(&new->node, head);
> return 0;
> diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
> index d2c4220fb377..491fd587de90 100644
> --- a/net/dccp/ackvec.h
> +++ b/net/dccp/ackvec.h
> @@ -117,18 +117,18 @@ static inline bool dccp_ackvec_is_empty(const struct dccp_ackvec *av)
>
> /**
> * struct dccp_ackvec_parsed - Record offsets of Ack Vectors in skb
> - * @vec: start of vector (offset into skb)
> + * @vec: contents of ack vector (copied from skb)
> * @len: length of @vec
> * @nonce: whether @vec had an ECN nonce of 0 or 1
> * @node: FIFO - arranged in descending order of ack_ackno
> *
> - * This structure is used by CCIDs to access Ack Vectors in a received skb.
> + * This structure is used by CCIDs to access Ack Vectors from the received skb.
> */
> struct dccp_ackvec_parsed {
> - u8 *vec,
> - len,
> - nonce:1;
> struct list_head node;
> + u8 len;
> + u8 nonce:1;
> + u8 vec[] __counted_by(len);
> };
>
> int dccp_ackvec_parsed_add(struct list_head *head, u8 *vec, u8 len, u8 nonce);
> diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
> index d6b30700af67..a1f2da3c4fa9 100644
> --- a/net/dccp/ccids/ccid2.c
> +++ b/net/dccp/ccids/ccid2.c
> @@ -589,14 +589,15 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
> /* go through all ack vectors */
> list_for_each_entry(avp, &hc->tx_av_chunks, node) {
> /* go through this ack vector */
> - for (; avp->len--; avp->vec++) {
> + u8 *v;
> + for (v = avp->vec; v < avp->vec + avp->len--; v++) {
> u64 ackno_end_rl = SUB48(ackno,
> - dccp_ackvec_runlen(avp->vec));
> + dccp_ackvec_runlen(v));
>
> ccid2_pr_debug("ackvec %llu |%u,%u|\n",
> (unsigned long long)ackno,
> - dccp_ackvec_state(avp->vec) >> 6,
> - dccp_ackvec_runlen(avp->vec));
> + dccp_ackvec_state(v) >> 6,
> + dccp_ackvec_runlen(v));
> /* if the seqno we are analyzing is larger than the
> * current ackno, then move towards the tail of our
> * seqnos.
> @@ -615,7 +616,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
> * run length
> */
> while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
> - const u8 state = dccp_ackvec_state(avp->vec);
> + const u8 state = dccp_ackvec_state(v);
>
> /* new packet received or marked */
> if (state != DCCPAV_NOT_RECEIVED &&
>
> Comments are highly appreciated.
I wouldn't touch DCCP anymore unless the change is required for TCP.
(see b144fcaf46d43)
next prev parent reply other threads:[~2024-10-23 17:51 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-23 12:09 KASAN: use-after-free Read in ccid2_hc_tx_packet_recv Dmitry Antipov
2024-10-23 17:51 ` Kuniyuki Iwashima [this message]
-- strict thread matches above, loose matches on Subject: below --
2018-04-02 9:20 syzbot
2018-05-25 13:52 ` syzbot
2019-11-28 10:30 ` syzbot
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=20241023175121.36351-1-kuniyu@amazon.com \
--to=kuniyu@amazon.com \
--cc=dccp@vger.kernel.org \
--cc=dmantipov@yandex.ru \
--cc=netdev@vger.kernel.org \
--cc=syzbot+554ccde221001ab5479a@syzkaller.appspotmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).