Skip to content

Commit 9782988

Browse files
committed
Merge branch 'udp-add-missing-check-on-edumx-rx-path'
Paolo Abeni says: ==================== udp: add missing check on edumx rx path The early demux RX path for the UDP protocol is currently missing some checks. Both ipv4 and ipv6 implementations lack checksum conversion and the ipv6 implementation additionally lack the zero checksum validation. The first patch takes care of UDPv4 and the second one of UDPv6 ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents edf2ef7 + eb63f29 commit 9782988

File tree

2 files changed

+63
-51
lines changed

2 files changed

+63
-51
lines changed

net/ipv4/udp.c

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,28 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
21242124
inet_compute_pseudo);
21252125
}
21262126

2127+
/* wrapper for udp_queue_rcv_skb tacking care of csum conversion and
2128+
* return code conversion for ip layer consumption
2129+
*/
2130+
static int udp_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
2131+
struct udphdr *uh)
2132+
{
2133+
int ret;
2134+
2135+
if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk))
2136+
skb_checksum_try_convert(skb, IPPROTO_UDP, uh->check,
2137+
inet_compute_pseudo);
2138+
2139+
ret = udp_queue_rcv_skb(sk, skb);
2140+
2141+
/* a return value > 0 means to resubmit the input, but
2142+
* it wants the return to be -protocol, or 0
2143+
*/
2144+
if (ret > 0)
2145+
return -ret;
2146+
return 0;
2147+
}
2148+
21272149
/*
21282150
* All we need to do is get the socket, and then do a checksum.
21292151
*/
@@ -2170,37 +2192,18 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
21702192
if (unlikely(sk->sk_rx_dst != dst))
21712193
udp_sk_rx_dst_set(sk, dst);
21722194

2173-
ret = udp_queue_rcv_skb(sk, skb);
2195+
ret = udp_unicast_rcv_skb(sk, skb, uh);
21742196
sock_put(sk);
2175-
/* a return value > 0 means to resubmit the input, but
2176-
* it wants the return to be -protocol, or 0
2177-
*/
2178-
if (ret > 0)
2179-
return -ret;
2180-
return 0;
2197+
return ret;
21812198
}
21822199

21832200
if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
21842201
return __udp4_lib_mcast_deliver(net, skb, uh,
21852202
saddr, daddr, udptable, proto);
21862203

21872204
sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
2188-
if (sk) {
2189-
int ret;
2190-
2191-
if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk))
2192-
skb_checksum_try_convert(skb, IPPROTO_UDP, uh->check,
2193-
inet_compute_pseudo);
2194-
2195-
ret = udp_queue_rcv_skb(sk, skb);
2196-
2197-
/* a return value > 0 means to resubmit the input, but
2198-
* it wants the return to be -protocol, or 0
2199-
*/
2200-
if (ret > 0)
2201-
return -ret;
2202-
return 0;
2203-
}
2205+
if (sk)
2206+
return udp_unicast_rcv_skb(sk, skb, uh);
22042207

22052208
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
22062209
goto drop;

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)