Skip to content

Commit eb63f29

Browse files
Paolo Abenidavem330
authored andcommitted
udp6: add missing checks on edumux packet processing
Currently the UDPv6 early demux rx code path lacks some mandatory checks, already implemented into the normal RX code path - namely the checksum conversion and no_check6_rx check. Similar to the previous commit, we move the common processing to an UDPv6 specific helper and call it from both edemux code path and normal code path. In respect to the UDPv4, we need to add an explicit check for non zero csum according to no_check6_rx value. Reported-by: Jianlin Shi <jishi@redhat.com> Suggested-by: Xin Long <lucien.xin@gmail.com> Fixes: c9f2c1a ("udp6: fix socket leak on early demux") Fixes: 2abb7cd ("udp: Add support for doing checksum unnecessary conversion") Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2b5a921 commit eb63f29

File tree

1 file changed

+37
-28
lines changed

1 file changed

+37
-28
lines changed

net/ipv6/udp.c

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,28 @@ static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
752752
}
753753
}
754754

755+
/* wrapper for udp_queue_rcv_skb tacking care of csum conversion and
756+
* return code conversion for ip layer consumption
757+
*/
758+
static int udp6_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
759+
struct udphdr *uh)
760+
{
761+
int ret;
762+
763+
if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk))
764+
skb_checksum_try_convert(skb, IPPROTO_UDP, uh->check,
765+
ip6_compute_pseudo);
766+
767+
ret = udpv6_queue_rcv_skb(sk, skb);
768+
769+
/* a return value > 0 means to resubmit the input, but
770+
* it wants the return to be -protocol, or 0
771+
*/
772+
if (ret > 0)
773+
return -ret;
774+
return 0;
775+
}
776+
755777
int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
756778
int proto)
757779
{
@@ -803,13 +825,14 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
803825
if (unlikely(sk->sk_rx_dst != dst))
804826
udp6_sk_rx_dst_set(sk, dst);
805827

806-
ret = udpv6_queue_rcv_skb(sk, skb);
807-
sock_put(sk);
828+
if (!uh->check && !udp_sk(sk)->no_check6_rx) {
829+
sock_put(sk);
830+
goto report_csum_error;
831+
}
808832

809-
/* a return value > 0 means to resubmit the input */
810-
if (ret > 0)
811-
return ret;
812-
return 0;
833+
ret = udp6_unicast_rcv_skb(sk, skb, uh);
834+
sock_put(sk);
835+
return ret;
813836
}
814837

815838
/*
@@ -822,30 +845,13 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
822845
/* Unicast */
823846
sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
824847
if (sk) {
825-
int ret;
826-
827-
if (!uh->check && !udp_sk(sk)->no_check6_rx) {
828-
udp6_csum_zero_error(skb);
829-
goto csum_error;
830-
}
831-
832-
if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk))
833-
skb_checksum_try_convert(skb, IPPROTO_UDP, uh->check,
834-
ip6_compute_pseudo);
835-
836-
ret = udpv6_queue_rcv_skb(sk, skb);
837-
838-
/* a return value > 0 means to resubmit the input */
839-
if (ret > 0)
840-
return ret;
841-
842-
return 0;
848+
if (!uh->check && !udp_sk(sk)->no_check6_rx)
849+
goto report_csum_error;
850+
return udp6_unicast_rcv_skb(sk, skb, uh);
843851
}
844852

845-
if (!uh->check) {
846-
udp6_csum_zero_error(skb);
847-
goto csum_error;
848-
}
853+
if (!uh->check)
854+
goto report_csum_error;
849855

850856
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
851857
goto discard;
@@ -866,6 +872,9 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
866872
ulen, skb->len,
867873
daddr, ntohs(uh->dest));
868874
goto discard;
875+
876+
report_csum_error:
877+
udp6_csum_zero_error(skb);
869878
csum_error:
870879
__UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
871880
discard:

0 commit comments

Comments
 (0)