diff options
author | Guillaume Nault <gnault@redhat.com> | 2020-10-31 03:07:25 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2020-11-03 23:55:53 +0300 |
commit | 0992d67bc2bcd723d57c6ee7883bda4524450179 (patch) | |
tree | 903f3d2bf87fd50a0bb247d5297435abfdb651e7 /include/net/dst.h | |
parent | 6d89076e6ef09337a29a7b1ea4fdf2d892be9650 (diff) | |
download | linux-0992d67bc2bcd723d57c6ee7883bda4524450179.tar.xz |
mpls: drop skb's dst in mpls_forward()
Commit 394de110a733 ("net: Added pointer check for
dst->ops->neigh_lookup in dst_neigh_lookup_skb") added a test in
dst_neigh_lookup_skb() to avoid a NULL pointer dereference. The root
cause was the MPLS forwarding code, which doesn't call skb_dst_drop()
on incoming packets. That is, if the packet is received from a
collect_md device, it has a metadata_dst attached to it that doesn't
implement any dst_ops function.
To align the MPLS behaviour with IPv4 and IPv6, let's drop the dst in
mpls_forward(). This way, dst_neigh_lookup_skb() doesn't need to test
->neigh_lookup any more. Let's keep a WARN condition though, to
document the precondition and to ease detection of such problems in the
future.
Signed-off-by: Guillaume Nault <gnault@redhat.com>
Link: https://lore.kernel.org/r/f8c2784c13faa54469a2aac339470b1049ca6b63.1604102750.git.gnault@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'include/net/dst.h')
-rw-r--r-- | include/net/dst.h | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index 8ea8812b0b41..10f0a8399867 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -400,14 +400,12 @@ static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, co static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst, struct sk_buff *skb) { - struct neighbour *n = NULL; + struct neighbour *n; - /* The packets from tunnel devices (eg bareudp) may have only - * metadata in the dst pointer of skb. Hence a pointer check of - * neigh_lookup is needed. - */ - if (dst->ops->neigh_lookup) - n = dst->ops->neigh_lookup(dst, skb, NULL); + if (WARN_ON_ONCE(!dst->ops->neigh_lookup)) + return NULL; + + n = dst->ops->neigh_lookup(dst, skb, NULL); return IS_ERR(n) ? NULL : n; } |