+++ /dev/null
-From foo@baz Fri 26 Jul 2019 12:22:46 PM CEST
-From: Florian Westphal <fw@strlen.de>
-Date: Wed, 26 Jun 2019 20:40:45 +0200
-Subject: net: make skb_dst_force return true when dst is refcounted
-
-From: Florian Westphal <fw@strlen.de>
-
-[ Upstream commit b60a77386b1d4868f72f6353d35dabe5fbe981f2 ]
-
-netfilter did not expect that skb_dst_force() can cause skb to lose its
-dst entry.
-
-I got a bug report with a skb->dst NULL dereference in netfilter
-output path. The backtrace contains nf_reinject(), so the dst might have
-been cleared when skb got queued to userspace.
-
-Other users were fixed via
-if (skb_dst(skb)) {
- skb_dst_force(skb);
- if (!skb_dst(skb))
- goto handle_err;
-}
-
-But I think its preferable to make the 'dst might be cleared' part
-of the function explicit.
-
-In netfilter case, skb with a null dst is expected when queueing in
-prerouting hook, so drop skb for the other hooks.
-
-v2:
- v1 of this patch returned true in case skb had no dst entry.
- Eric said:
- Say if we have two skb_dst_force() calls for some reason
- on the same skb, only the first one will return false.
-
- This now returns false even when skb had no dst, as per Erics
- suggestion, so callers might need to check skb_dst() first before
- skb_dst_force().
-
-Signed-off-by: Florian Westphal <fw@strlen.de>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- include/net/dst.h | 5 ++++-
- net/netfilter/nf_queue.c | 6 +++++-
- 2 files changed, 9 insertions(+), 2 deletions(-)
-
---- a/include/net/dst.h
-+++ b/include/net/dst.h
-@@ -318,14 +318,17 @@ static inline void skb_dst_copy(struct s
- * @skb: buffer
- *
- * If dst is not yet refcounted, let's do it
-+ * Returns true if dst is refcounted.
- */
--static inline void skb_dst_force(struct sk_buff *skb)
-+static inline bool skb_dst_force(struct sk_buff *skb)
- {
- if (skb_dst_is_noref(skb)) {
- WARN_ON(!rcu_read_lock_held());
- skb->_skb_refdst &= ~SKB_DST_NOREF;
- dst_clone(skb_dst(skb));
- }
-+
-+ return skb->_skb_refdst != 0UL;
- }
-
- /**
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -139,6 +139,11 @@ int nf_queue(struct sk_buff *skb,
- goto err;
- }
-
-+ if (!skb_dst_force(skb) && state->hook != NF_INET_PRE_ROUTING) {
-+ status = -ENETDOWN;
-+ goto err;
-+ }
-+
- *entry = (struct nf_queue_entry) {
- .skb = skb,
- .elem = elem,
-@@ -147,7 +152,6 @@ int nf_queue(struct sk_buff *skb,
- };
-
- nf_queue_entry_get_refs(entry);
-- skb_dst_force(skb);
- afinfo->saveroute(skb, entry);
- status = qh->outfn(entry, queuenum);
-
netrom-fix-a-memory-leak-in-nr_rx_frame.patch
netrom-hold-sock-when-setting-skb-destructor.patch
tcp-reset-bytes_acked-and-bytes_received-when-disconnecting.patch
-net-make-skb_dst_force-return-true-when-dst-is-refcounted.patch
bonding-validate-ip-header-before-check-ipproto_igmp.patch
net-bridge-mcast-fix-stale-nsrcs-pointer-in-igmp3-mld2-report-handling.patch
net-bridge-mcast-fix-stale-ipv6-hdr-pointer-when-handling-v6-query.patch
+++ /dev/null
-From foo@baz Fri 26 Jul 2019 12:22:46 PM CEST
-From: Florian Westphal <fw@strlen.de>
-Date: Wed, 26 Jun 2019 20:40:45 +0200
-Subject: net: make skb_dst_force return true when dst is refcounted
-
-From: Florian Westphal <fw@strlen.de>
-
-[ Upstream commit b60a77386b1d4868f72f6353d35dabe5fbe981f2 ]
-
-netfilter did not expect that skb_dst_force() can cause skb to lose its
-dst entry.
-
-I got a bug report with a skb->dst NULL dereference in netfilter
-output path. The backtrace contains nf_reinject(), so the dst might have
-been cleared when skb got queued to userspace.
-
-Other users were fixed via
-if (skb_dst(skb)) {
- skb_dst_force(skb);
- if (!skb_dst(skb))
- goto handle_err;
-}
-
-But I think its preferable to make the 'dst might be cleared' part
-of the function explicit.
-
-In netfilter case, skb with a null dst is expected when queueing in
-prerouting hook, so drop skb for the other hooks.
-
-v2:
- v1 of this patch returned true in case skb had no dst entry.
- Eric said:
- Say if we have two skb_dst_force() calls for some reason
- on the same skb, only the first one will return false.
-
- This now returns false even when skb had no dst, as per Erics
- suggestion, so callers might need to check skb_dst() first before
- skb_dst_force().
-
-Signed-off-by: Florian Westphal <fw@strlen.de>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- include/net/dst.h | 5 ++++-
- net/netfilter/nf_queue.c | 6 +++++-
- 2 files changed, 9 insertions(+), 2 deletions(-)
-
---- a/include/net/dst.h
-+++ b/include/net/dst.h
-@@ -315,14 +315,17 @@ static inline void skb_dst_copy(struct s
- * @skb: buffer
- *
- * If dst is not yet refcounted, let's do it
-+ * Returns true if dst is refcounted.
- */
--static inline void skb_dst_force(struct sk_buff *skb)
-+static inline bool skb_dst_force(struct sk_buff *skb)
- {
- if (skb_dst_is_noref(skb)) {
- WARN_ON(!rcu_read_lock_held());
- skb->_skb_refdst &= ~SKB_DST_NOREF;
- dst_clone(skb_dst(skb));
- }
-+
-+ return skb->_skb_refdst != 0UL;
- }
-
- /**
---- a/net/netfilter/nf_queue.c
-+++ b/net/netfilter/nf_queue.c
-@@ -133,6 +133,11 @@ static int __nf_queue(struct sk_buff *sk
- goto err;
- }
-
-+ if (!skb_dst_force(skb) && state->hook != NF_INET_PRE_ROUTING) {
-+ status = -ENETDOWN;
-+ goto err;
-+ }
-+
- *entry = (struct nf_queue_entry) {
- .skb = skb,
- .state = *state,
-@@ -140,7 +145,6 @@ static int __nf_queue(struct sk_buff *sk
- };
-
- nf_queue_entry_get_refs(entry);
-- skb_dst_force(skb);
- afinfo->saveroute(skb, entry);
- status = qh->outfn(entry, queuenum);
-
netrom-fix-a-memory-leak-in-nr_rx_frame.patch
netrom-hold-sock-when-setting-skb-destructor.patch
bonding-validate-ip-header-before-check-ipproto_igmp.patch
-net-make-skb_dst_force-return-true-when-dst-is-refcounted.patch
tcp-reset-bytes_acked-and-bytes_received-when-disconnecting.patch
net-bridge-mcast-fix-stale-nsrcs-pointer-in-igmp3-mld2-report-handling.patch
net-bridge-mcast-fix-stale-ipv6-hdr-pointer-when-handling-v6-query.patch