History

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.

Paolo Abeni committed 7 years ago

Commit 424a7cd1 parent 5de362d1 file · +6 −4Browse files

Unified · Split

net/ipv6/udp.c+6−4
@@ -420,17 +420,19 @@ EXPORT_SYMBOL(udpv6_encap_enable); · 419 unmodified lines
420 */420 */
421static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb,421static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb,
422 struct inet6_skb_parm *opt,422 struct inet6_skb_parm *opt,
423 u8 type, u8 code, int offset, u32 info)423 u8 type, u8 code, int offset, __be32 info)
424{424{
425 int i;425 int i;
426 426
427 for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) {427 for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) {
428 int (*handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,428 int (*handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
429 u8 type, u8 code, int offset, u32 info);429 u8 type, u8 code, int offset, __be32 info);
430 const struct ip6_tnl_encap_ops *encap;
430 431
431 if (!ip6tun_encaps[i])432 encap = rcu_dereference(ip6tun_encaps[i]);
433 if (!encap)
432 continue;434 continue;
433 handler = rcu_dereference(ip6tun_encaps[i]->err_handler);435 handler = encap->err_handler;
434 if (handler && !handler(skb, opt, type, code, offset, info))436 if (handler && !handler(skb, opt, type, code, offset, info))
435 return 0;437 return 0;
436 }438 }