udpv6: fix possible user after free in error handler [Linux 5.0]

This Linux kernel change "udpv6: fix possible user after free in error handler" is included in the Linux 5.0 release. This change is authored by Paolo Abeni <pabeni [at] redhat.com> on Thu Feb 21 17:43:59 2019 +0100. The commit for this change in Linux stable tree is 424a7cd (patch).

udpv6: fix possible user after free in error handler

Before derefencing the encap pointer, commit e7cc082455cb ("udp: Support
for error handlers of tunnels with arbitrary destination port") checks
for a NULL value, but the two fetch operation can race with removal.
Fix the above using a single access.
Also fix a couple of type annotations, to make sparse happy.

Fixes: e7cc082455cb ("udp: Support for error handlers of tunnels with arbitrary destination port")
Signed-off-by: Paolo Abeni <[email protected]>
Acked-by: Stefano Brivio <[email protected]>
Signed-off-by: David S. Miller <[email protected]>

There are 10 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 net/ipv6/udp.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e6c52c2..b444483 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -420,17 +420,19 @@ void udpv6_encap_enable(void)
  */
 static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb,
                      struct inet6_skb_parm *opt,
-                     u8 type, u8 code, int offset, u32 info)
+                     u8 type, u8 code, int offset, __be32 info)
 {
    int i;

    for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) {
        int (*handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
-                  u8 type, u8 code, int offset, u32 info);
+                  u8 type, u8 code, int offset, __be32 info);
+       const struct ip6_tnl_encap_ops *encap;

-       if (!ip6tun_encaps[i])
+       encap = rcu_dereference(ip6tun_encaps[i]);
+       if (!encap)
            continue;
-       handler = rcu_dereference(ip6tun_encaps[i]->err_handler);
+       handler = encap->err_handler;
        if (handler && !handler(skb, opt, type, code, offset, info))
            return 0;
    }

Leave a Reply

Your email address will not be published. Required fields are marked *