Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ad92ad0 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

udp: fix a race in encap_rcv handling



udp_queue_rcv_skb() has a possible race in encap_rcv handling, since
this pointer can be changed anytime.

We should use ACCESS_ONCE() to close the race.

Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 501e89d3
Loading
Loading
Loading
Loading
+5 −3
Original line number Original line Diff line number Diff line
@@ -1397,6 +1397,8 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
	nf_reset(skb);
	nf_reset(skb);


	if (up->encap_type) {
	if (up->encap_type) {
		int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);

		/*
		/*
		 * This is an encapsulation socket so pass the skb to
		 * This is an encapsulation socket so pass the skb to
		 * the socket's udp_encap_rcv() hook. Otherwise, just
		 * the socket's udp_encap_rcv() hook. Otherwise, just
@@ -1409,11 +1411,11 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
		 */
		 */


		/* if we're overly short, let UDP handle it */
		/* if we're overly short, let UDP handle it */
		if (skb->len > sizeof(struct udphdr) &&
		encap_rcv = ACCESS_ONCE(up->encap_rcv);
		    up->encap_rcv != NULL) {
		if (skb->len > sizeof(struct udphdr) && encap_rcv != NULL) {
			int ret;
			int ret;


			ret = (*up->encap_rcv)(sk, skb);
			ret = encap_rcv(sk, skb);
			if (ret <= 0) {
			if (ret <= 0) {
				UDP_INC_STATS_BH(sock_net(sk),
				UDP_INC_STATS_BH(sock_net(sk),
						 UDP_MIB_INDATAGRAMS,
						 UDP_MIB_INDATAGRAMS,