From: Eric Dumazet <eduma...@google.com> dccp_parse_options() improperly parses 12 or 16 bytes in excess, because it forgets to subtract DCCP header len.
This causes various issues, since these 12/16 bytes are part of the payload and this might not even be present in skb->head, as dccp_invalid_packet() only pulled everything but payload. KASAN complains since we might access uninitialized data. Strangely enough, net/netfilter/xt_dccp.c got this right. Signed-off-by: Eric Dumazet <eduma...@google.com> Reported-by: Andrey Konovalov <andreyk...@google.com> Cc: Gerrit Renker <ger...@erg.abdn.ac.uk> --- net/dccp/options.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/dccp/options.c b/net/dccp/options.c index 74d29c56c36709fd4e31f0e63a1f8b1aa38a32cd..41bd4bc4026f97b155e12a3a37095653836ce7fc 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -54,10 +54,9 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, struct dccp_sock *dp = dccp_sk(sk); const struct dccp_hdr *dh = dccp_hdr(skb); const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; - unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); - unsigned char *opt_ptr = options; - const unsigned char *opt_end = (unsigned char *)dh + - (dh->dccph_doff * 4); + unsigned char *opt_ptr = (unsigned char *)dh + __dccp_hdr_len(dh); + unsigned int optlen = dh->dccph_doff * 4 - __dccp_hdr_len(dh); + const unsigned char *opt_end = opt_ptr + optlen; struct dccp_options_received *opt_recv = &dp->dccps_options_received; unsigned char opt, len; unsigned char *uninitialized_var(value);