From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Pablo Neira Ayuso <pablo@netfilter.org>,
Sasha Levin <sashal@kernel.org>,
fw@strlen.de, davem@davemloft.net, edumazet@kernel.org,
kuba@kernel.org, pabeni@redhat.com,
netfilter-devel@vger.kernel.org, coreteam@netfilter.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.18-5.10] netfilter: nf_tables: call skb_valid_dst() before skb_dst()
Date: Mon, 19 Oct 2026 09:51:36 -0400 [thread overview]
Message-ID: <20261019135441.1420968-405-sashal@kernel.org> (raw)
In-Reply-To: <20261019135441.1420968-1-sashal@kernel.org>
From: Pablo Neira Ayuso <pablo@netfilter.org>
[ Upstream commit 689db98e535bf8efb5bc9c36f4fd3de3bd715eb6 ]
When fetching the dst_entry from the skb, check if it valid, ie. this is
not a template dst, for extensions that can be used from the netdev
ingress and egress chains.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The evaluation target is **pending-6.6 (Linux 6.6.157)**. The live
checkout later moved to mainline v7.3-rc4; all 6.6 findings below are
from `refs/heads/pending-6.6` (`p-6.6-3-g04810563abb71`).
Original commit: `689db98e535bf8efb5bc9c36f4fd3de3bd715eb6` (Pablo Neira
Ayuso, 2026-07-31). It is **not** an ancestor of pending-6.6.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Record: **[netfilter/nf_tables] [call/check] [require a real routing
dst, not a metadata template, before using skb_dst()]**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- Record:
- **Fixes:** none (expected for this review)
- **Reported-by / Tested-by / Reviewed-by / Acked-by:** none
- **Link:** none in the commit; mailing list found separately
- **Cc: stable:** none (expected)
- **Signed-off-by:** Pablo Neira Ayuso (netfilter maintainer). Ignore
Sasha Levin SOB if present in a candidate wrapper.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Record:
- **Bug:** `skb_dst()` is used as if it were a real
`rtable`/`rt6_info`. Packets on netdev/inet ingress/egress often
carry a **DST_METADATA** template (tunnels, TC) instead.
- **Symptom:** nft `rt` / `meta rtclassid` / `xfrm` evaluate a
template dst; `nf_send_reset`/`nf_send_unreach` skip filling a real
route and treat the template as an `rtable`.
- **Version info:** none in the message. Buggy pattern is old; 6.6
still has it.
- **Root cause (author):** template dst is not a valid routing dst;
must use `skb_valid_dst()` first.
**Step 1.4: DETECT HIDDEN BUG FIXES**
- Record: **Not hidden.** It is a real validity check. “Call X before Y”
is a missing-check fix, not cleanup.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
- Record:
- `net/ipv4/netfilter/nf_reject_ipv4.c` (+4/−2)
- `net/ipv6/netfilter/nf_reject_ipv6.c` (+6/−2)
- `net/netfilter/nft_meta.c` (+4/−2)
- `net/netfilter/nft_rt.c` (+4/−2)
- `net/netfilter/nft_xfrm.c` (+8/−1)
- **~26 insertions, 9 deletions, 5 files**
- Functions: `nf_reject_fill_skb_dst`, `nf_send_reset`,
`nf_send_unreach`, `nf_reject6_fill_skb_dst`, `nf_send_reset6`,
`nf_send_unreach6`, `nft_meta_get_eval_rtclassid`,
`nft_rt_get_eval`, `nft_xfrm_get_eval_out`
- **Scope:** small, same-subsystem, surgical
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
- Record:
- **Reject fill:** `skb_dst_set()` over a possible existing template →
`skb_dst_drop()` then `skb_dst_set()` of a real route.
- **Reject send:** `if (!skb_dst()) fill` → `if (!skb_valid_dst())
fill`. Template dst no longer counts as “already routed.”
- **nft_meta / nft_rt / nft_xfrm:** `skb_dst()` then NULL check →
`skb_valid_dst()` then `skb_dst()`. Template dst is treated as
missing.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
- Record:
- **Category:** logic/correctness + type confusion (metadata dst used
as `rtable`/`xfrm_dst`).
- **Mechanism:** `skb_valid_dst()` is `dst && !(dst->flags &
DST_METADATA)`. Metadata dst is initialized with `dst_blackhole_ops`
and **`dev == NULL`**. Using it as `skb_rtable()` reads
`rt_flags`/`rt_gw*` from the metadata union; `nft_xfrm` would walk
`((xfrm_dst *)dst)->child` if `dst->xfrm` were set.
**Step 2.4: ASSESS THE FIX QUALITY**
- Record:
- **Quality:** obviously correct; same helper already used in
`ip_input`, `ip_tunnel`, wireguard, xfrm.
- **Minimal:** yes. Include of `net/dst_metadata.h` is required for
the helper.
- **Regression risk:** low. `meta rtclassid` on a metadata dst
currently succeeds with `tclassid == 0`; after the fix it fails
closed (`NFT_BREAK`). That is stricter and correct.
- **No API/feature additions.**
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Record:
- Reject `!skb_dst() && fill`: `a0a3ace2a5788` (Florian Westphal,
2025-08-20) already **in 6.6** — “don’t leak dst refcount for
loopback packets.” That made “any dst present” skip fill, including
metadata dst.
- `nft_rt_get_eval` `skb_dst` check: `2fa841938c648` (2016), present
since nft_rt was added.
- **Bug is in 6.6, not new mainline-only code.**
**Step 3.2: FOLLOW THE FIXES TAG**
- Record: **No Fixes: tag.** Not applicable. Introducer of the reject
skip-fill logic **is** in this tree (`a0a3ace2a5788`).
**Step 3.3: CHECK FILE HISTORY**
- Record: Related 6.6 history includes `a0a3ace2a5788` (reject dst leak)
and `e64a48c50a1ff` (`nf_conntrack_sip`: validate `skb_dst()` for
tc/OVS). Same class of bug already accepted into 6.6. This commit is
standalone, not patch 2/N of a required series (it was 8/9 of an nf-
next pull, but the diff does not depend on patches 1–7).
**Step 3.4: CHECK THE AUTHOR**
- Record: **Pablo Neira Ayuso is the netfilter maintainer.** Nearby work
is normal nf-next flowtable/conncount material; this hunk is
independent.
**Step 3.5: DEPENDENT/PREREQUISITE COMMITS**
- Record:
- `skb_valid_dst()` exists in 6.6 `include/net/dst_metadata.h`.
- No new helpers required.
- **Can apply standalone** with minor context (see Phase 6).
- No follow-ups on origin/master after `689db98e535bf`.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
- Record:
- `b4 dig -c 689db98e535bf`: **failed** (lore.kernel.org 503).
- Fallback: [PATCH net-next 8/9]
https://lists.openwall.net/netdev/2026/07/31/304
- Cover: [PATCH net-next 0/9]
https://lists.openwall.net/netdev/2026/07/31/319
- Submitted to **nf-next / net-next**, not `net` (fixes). Cover: “Call
skb_valid_dst() before accessing skb_dst() to ensure dst_entry is
not a template.”
- Syzbot CI on the nf-next posting: **passed**
(https://ci.syzbot.org/series/250b78fc-95ac-4f6f-8746-9f8d8777688b).
Not a syzbot crash report.
- No NAK found. No reviewer “Cc: stable” found.
**Step 4.2: CHECK WHO REVIEWED**
- Record: To/Cc: netfilter-devel, davem, kuba, pabeni, edumazet,
fw@strlen.de, horms. **Florian Westphal (nf core) was CC’d.** Applied
by Pablo himself. No extra Reviewed-by on the commit.
**Step 4.3: SEARCH FOR THE BUG REPORT**
- Record: **No user/syzbot/bugzilla report.** Author-driven correctness
fix.
**Step 4.4: RELATED PATCHES AND SERIES**
- Record: Series 1–7 is flowtable/`fill_forward_path` work; patch 9 is
conntrack TCP timeout. **This patch does not depend on them.** Same-
class SIP helper fix already in 6.6.
**Step 4.5: STABLE MAILING LIST HISTORY**
- Record: lore.kernel.org/stable fetch returned **403**. **UNVERIFIED**
whether stable@ discussed this SHA. No evidence it was rejected for
stable.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: KEY FUNCTIONS**
- Record: listed in 2.1.
**Step 5.2: TRACE CALLERS**
- Record (6.6):
- `nf_send_unreach` / `nf_send_reset`: `nft_reject_ipv4_eval`,
`nft_reject_inet_eval`, `ipt_REJECT`.
- IPv6 equivalents: nft reject ipv6/inet, ip6t_REJECT.
- **netdev reject does not use these**; it uses `nf_reject_skb_v4_*` /
`nf_reject_skb_v6_*` (unchanged).
- `nft_rt_get_eval`: packet path for the `rt` expression; **family
limited to ipv4/ipv6/inet** (not netdev).
- `nft_xfrm_get_eval_out`: ipv4/ipv6/inet, OUT hooks only.
- `nft_meta_get_eval_rtclassid`: **allowed on netdev** (no hook
restriction for this key).
**Step 5.3: TRACE CALLEES**
- Record: `skb_valid_dst`, `skb_dst_drop`/`skb_dst_set`,
`nf_ip_route`/`nf_ip6_route`, `skb_rtable`, `icmp_send`/`icmpv6_send`,
`ip_route_me_harder`.
**Step 5.4: FOLLOW THE CALL CHAIN**
- Record: Reachable from nftables/iptables **REJECT** and from
`rt`/`xfrm`/`meta rtclassid` eval. Userspace (`nft`/`iptables`)
installs the rules. Overlay tunnels (VXLAN/GENEVE collect-md, TC
tunnel_key) attach metadata dst, then the inner packet hits **inet
ingress / PRE_ROUTING**. **Yes, reachable.**
**Step 5.5: SIMILAR PATTERNS**
- Record: Same `skb_valid_dst` pattern in `net/ipv4/ip_input.c`,
`ip_tunnel.c`, `xfrm_input.c`. 6.6 already has `nf_conntrack_sip` dst
validation for tc/OVS.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE (6.6.157)
**Step 6.1: DOES THE BUGGY CODE EXIST?**
- Record: **Yes.**
- `nf_reject_ipv4.c`: `if (!skb_dst(oldskb) &&
nf_reject_fill_skb_dst...)` and no `skb_dst_drop` before
`skb_dst_set`.
- Same for IPv6 reject.
- `nft_rt.c`: `dst = skb_dst(skb); if (!dst) goto err;`
- `nft_meta.c`: `const struct dst_entry *dst = skb_dst(skb); if (!dst)
return false;`
- `nft_xfrm.c`: `const struct dst_entry *dst = skb_dst(pkt->skb);`
then walk `dst->xfrm`.
- 6.6 **has** netdev **ingress and egress**
(`nft_chain_filter_netdev`), **NF_INET_INGRESS** (inet reject
validates it), and `skb_valid_dst()`.
**Step 6.2: BACKPORT COMPLICATIONS**
- Record: **Minor context, not rework.**
- 6.6 `nft_rt` uses `(const struct rtable *)dst` not `dst_rtable()`
(unchanged context).
- 6.6 `nf_send_reset6` uses `skb_dst(oldskb)->dev` not `skb_dst_dev()`
(unchanged context). `skb_dst_dev()` exists in 6.6
`include/net/dst.h` but is not used in this file.
- Functional hunks match 6.6.
**Step 6.3: RELATED FIXES ALREADY HERE**
- Record: `a0a3ace2a5788` (reject dst leak) and `e64a48c50a1ff` (SIP
skb_dst). **This metadata-vs-real-dst check is not already applied.**
`git merge-base --is-ancestor 689db98e535bf pending-6.6` → not
ancestor.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: SUBSYSTEM AND CRITICALITY**
- Record: **netfilter / nf_tables + IPv4/IPv6 reject.** **IMPORTANT**
(firewall/NAT on almost every server/router/container host). Not core
mm/scheduler, but production-critical networking.
**Step 7.2: SUBSYSTEM ACTIVITY**
- Record: Mature and actively fixed. nft_rt dates to 2016; reject-at-
prerouting to 2020 (`f53b9b0bdc59`). Long-lived code.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: WHO IS AFFECTED**
- Record: **Config/driver-specific but common:** `nftables`/`iptables`
REJECT, `rt`, `meta rtclassid`, `xfrm`, plus overlay/TC metadata dst
(Kubernetes, OVN, VXLAN/GENEVE collect-md).
**Step 8.2: TRIGGER CONDITIONS**
- Record: Packet carries DST_METADATA **and** hits reject or those
expressions. Common on inet ingress/PRE_ROUTING of collect-md tunnels.
Unprivileged users cannot install nft rules (CAP_NET_ADMIN); they
**can** send traffic that hits existing rules. Timing race: no.
**Step 8.3: FAILURE MODE SEVERITY**
- Record:
- **Verified:** type confusion (`skb_rtable()` on metadata dst);
`rt_flags`/`nexthop` taken from the metadata union; reject may skip
`nf_reject_fill_skb_dst` and feed `icmp_send`/`ip_route_me_harder` a
template dst.
- **6.6 `__icmp_send`:** `if (!rt) return` is **not** enough (template
is non-NULL); `rt->dst.dev` NULL is handled, then `rt->rt_flags` is
still type-confused.
- **Not a proven KASAN UAF.** Metadata dst uses `dst_blackhole_ops`,
so `ops->mtu` is not NULL. `dst->xfrm` is NULL on metadata dst, so
the xfrm walk typically does not follow a garbage `child`.
- **Severity: HIGH for firewall correctness** (wrong `rt`/`meta`
match; REJECT may not emit RST/ICMP). **MEDIUM as a crash**
(plausible UB/type confusion, not a demonstrated oops). Still a real
bug in a hot firewall path.
**Step 8.4: RISK-BENEFIT**
- Record:
- **Benefit:** high for nft/iptables + overlay users; restores
intended “no real route → lookup or fail closed.”
- **Risk:** low (26 lines, existing helper, fail closed).
- **Ratio:** favorable.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: EVIDENCE**
**FOR:**
- Real bug: template dst treated as a route.
- Present in 6.6; `skb_valid_dst()` already exists.
- Reject skip-fill was introduced/worsened by a commit **already in
6.6**.
- Small, maintainer-authored, obviously correct.
- Same class as SIP `skb_dst` validation already in 6.6 stable.
- Realistic trigger: collect-md tunnels + nft/iptables at
ingress/prerouting.
- No follow-up reverting or rewriting this change.
**AGAINST:**
- Posted as net-next 8/9, not `net`.
- No Fixes/Cc: stable, no crash report.
- netdev-family `reject` does not call `nf_send_*`; `nft_rt`/`nft_xfrm`
cannot be used on netdev family even in mainline.
- Crash is not as hard as a NULL `ops` deref (blackhole ops).
**UNRESOLVED:**
- lore.kernel.org was 503/403; no full review thread beyond Openwall. No
stable@ discussion verified.
**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — helper semantics are clear;
syzbot CI passed; in mainline since 2026-07.
2. Fixes a real bug that affects users? **PASS** — metadata dst on
ingress/tunnel paths is real; expressions/reject mishandle it.
3. Important (crash/security/corruption/deadlock)? **PASS** — firewall
mis-eval and failed REJECT replies on overlay/ingress; type-confused
`rtable` use. Not a proven panic, but important networking
correctness.
4. Small and contained? **PASS** — 26/9 lines, five netfilter files.
5. No new features or APIs? **PASS**
6. Can apply to this tree? **PASS** — minor context (`dst_rtable` /
`skb_dst_dev` in unchanged lines only).
**Step 9.3: EXCEPTION CATEGORIES**
- Record: none (not a device ID/quirk/DT/build/docs exception).
Qualifies as a normal bugfix.
**Step 9.4: DECISION**
This is a small, correct check that 6.6 needs. The tree has the buggy
`!skb_dst()` reject path, nft `rt`/`meta`/`xfrm` eval, inet ingress, and
netdev ingress/egress. Benefit outweighs risk.
---
### What the commit solves for 6.6 users
Packets with a **metadata/template dst** (VXLAN/GENEVE collect-md, TC)
make `skb_dst()` non-NULL, so reject never installs a real route and
`rt`/`meta rtclassid`/`xfrm` inspect a non-route. Users see wrong nft
matches and missing TCP RST / ICMP unreachable. The fix uses the
existing `skb_valid_dst()` helper and drops any template dst before
attaching a real one.
### Risk vs benefit
Low risk, high correctness value on firewall + overlay hosts. Apply may
need a one-line context tweak in `nft_rt.c` and `nf_reject_ipv6.c`.
### Verification
- **[Phase 1]** Parsed subject/body; tags: only Pablo SOB; no
Fixes/Reported-by/stable.
- **[Phase 2]** Diff: 5 files, +26/−9; `skb_valid_dst` + `skb_dst_drop`
before `skb_dst_set`.
- **[Phase 3]** `git describe` of pending-6.6: `p-6.6-3-g04810563abb71`,
Makefile 6.6.157.
- **[Phase 3]** `git merge-base --is-ancestor 689db98e535bf pending-6.6`
→ not present.
- **[Phase 3]** Blame: reject condition `a0a3ace2a5788` (in 6.6); nft_rt
`2fa841938c648` (2016).
- **[Phase 3]** `git show pending-6.6:include/net/dst_metadata.h`:
`skb_valid_dst()` present.
- **[Phase 4]** `b4 dig -c 689db98e535bf`: lore 503, no match.
- **[Phase 4]** Openwall: net-next 8/9 and 0/9 cover; no NAK.
- **[Phase 4]** Syzbot CI series passed; not a syzbot bug report.
- **[Phase 4]** lore.kernel.org/stable: 403, UNVERIFIED.
- **[Phase 5]** Callers verified via `git grep` on pending-6.6:
ipt_REJECT, nft_reject_ipv4/inet; netdev reject uses `nf_reject_skb_*`
(not this path).
- **[Phase 5]** `nft_rt_validate` / `nft_xfrm_validate` reject
NFPROTO_NETDEV in both 6.6 and mainline.
- **[Phase 6]** Buggy `!skb_dst()` / raw `skb_dst()` still in
pending-6.6 sources.
- **[Phase 6]** Context drift: `dst_rtable` and `skb_dst_dev` not used
in 6.6 versions of those unchanged lines.
- **[Phase 7]** nf_tables + reject; important.
- **[Phase 8]** `__icmp_send` in 6.6 handles NULL `dst->dev` but still
reads `rt->rt_flags` from a metadata object.
- **[Phase 8]** Metadata dst: `dst_init(..., NULL, ...)` +
`DST_METADATA` + `dst_blackhole_ops`; `xfrm == NULL`.
- **UNVERIFIED:** full lore review replies (503); stable@ archive (403).
**YES**
net/ipv4/netfilter/nf_reject_ipv4.c | 6 ++++--
net/ipv6/netfilter/nf_reject_ipv6.c | 8 ++++++--
net/netfilter/nft_meta.c | 6 ++++--
net/netfilter/nft_rt.c | 6 ++++--
net/netfilter/nft_xfrm.c | 9 ++++++++-
5 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
index 4626dc46808f3..59ec465a9df98 100644
--- a/net/ipv4/netfilter/nf_reject_ipv4.c
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -8,6 +8,7 @@
#include <net/tcp.h>
#include <net/route.h>
#include <net/dst.h>
+#include <net/dst_metadata.h>
#include <net/netfilter/ipv4/nf_reject.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_bridge.h>
@@ -263,6 +264,7 @@ static int nf_reject_fill_skb_dst(struct sk_buff *skb_in)
if (!dst)
return -1;
+ skb_dst_drop(skb_in);
skb_dst_set(skb_in, dst);
return 0;
}
@@ -279,7 +281,7 @@ void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,
if (!oth)
return;
- if (!skb_dst(oldskb) && nf_reject_fill_skb_dst(oldskb) < 0)
+ if (!skb_valid_dst(oldskb) && nf_reject_fill_skb_dst(oldskb) < 0)
return;
if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
@@ -352,7 +354,7 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook)
if (iph->frag_off & htons(IP_OFFSET))
return;
- if (!skb_dst(skb_in) && nf_reject_fill_skb_dst(skb_in) < 0)
+ if (!skb_valid_dst(skb_in) && nf_reject_fill_skb_dst(skb_in) < 0)
return;
if (skb_csum_unnecessary(skb_in) ||
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
index ef5b7e85cffa8..07cdaa10da0d0 100644
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -8,6 +8,7 @@
#include <net/ip6_route.h>
#include <net/ip6_fib.h>
#include <net/ip6_checksum.h>
+#include <net/dst_metadata.h>
#include <net/netfilter/ipv6/nf_reject.h>
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter_bridge.h>
@@ -304,6 +305,7 @@ static int nf_reject6_fill_skb_dst(struct sk_buff *skb_in)
if (!dst)
return -1;
+ skb_dst_drop(skb_in);
skb_dst_set(skb_in, dst);
return 0;
}
@@ -336,10 +338,12 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
fl6.fl6_sport = otcph->dest;
fl6.fl6_dport = otcph->source;
- if (!skb_dst(oldskb)) {
+ if (!skb_valid_dst(oldskb)) {
nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false);
if (!dst)
return;
+
+ skb_dst_drop(oldskb);
skb_dst_set(oldskb, dst);
}
@@ -440,7 +444,7 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in,
if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
skb_in->dev = net->loopback_dev;
- if (!skb_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0)
+ if (!skb_valid_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0)
return;
icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 19e6d1c2436af..f3c7b7edb10c0 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -20,6 +20,7 @@
#include <net/dst.h>
#include <net/ip.h>
#include <net/sock.h>
+#include <net/dst_metadata.h>
#include <net/tcp_states.h> /* for TCP_TIME_WAIT */
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
@@ -274,11 +275,12 @@ static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
static noinline bool
nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
{
- const struct dst_entry *dst = skb_dst(skb);
+ const struct dst_entry *dst;
- if (!dst)
+ if (!skb_valid_dst(skb))
return false;
+ dst = skb_dst(skb);
*dest = dst->tclassid;
return true;
}
diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c
index ad527f3596c03..cb7dff336bbdc 100644
--- a/net/netfilter/nft_rt.c
+++ b/net/netfilter/nft_rt.c
@@ -8,6 +8,7 @@
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <net/dst.h>
+#include <net/dst_metadata.h>
#include <net/ip6_route.h>
#include <net/route.h>
#include <net/netfilter/nf_tables.h>
@@ -59,10 +60,11 @@ void nft_rt_get_eval(const struct nft_expr *expr,
u32 *dest = ®s->data[priv->dreg];
const struct dst_entry *dst;
- dst = skb_dst(skb);
- if (!dst)
+ if (!skb_valid_dst(skb))
goto err;
+ dst = skb_dst(skb);
+
switch (priv->key) {
#ifdef CONFIG_IP_ROUTE_CLASSID
case NFT_RT_CLASSID:
diff --git a/net/netfilter/nft_xfrm.c b/net/netfilter/nft_xfrm.c
index 7ffe6a2690d13..9c9ac27122ad9 100644
--- a/net/netfilter/nft_xfrm.c
+++ b/net/netfilter/nft_xfrm.c
@@ -12,6 +12,7 @@
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>
+#include <net/dst_metadata.h>
#include <linux/in.h>
#include <net/xfrm.h>
@@ -177,9 +178,15 @@ static void nft_xfrm_get_eval_out(const struct nft_xfrm *priv,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
- const struct dst_entry *dst = skb_dst(pkt->skb);
+ const struct dst_entry *dst;
int i;
+ if (!skb_valid_dst(pkt->skb)) {
+ regs->verdict.code = NFT_BREAK;
+ return;
+ }
+
+ dst = skb_dst(pkt->skb);
for (i = 0; dst && dst->xfrm;
dst = ((const struct xfrm_dst *)dst)->child, i++) {
if (i < priv->spnum)
--
2.53.0
next prev parent reply other threads:[~2026-10-19 14:04 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-5.10] net/rds: don't use unpin_user_pages_dirty_lock() from atomic context Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] selftests: net: reuseport_bpf_numa: consider cpuless numa node Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] net: stmmac: fix device node reference leaks in stmmac_mtl_setup() Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] netfilter: conntrack: tcp: use UNACK timeout for non-closing RST packets Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] net: usb: qmi_wwan: add Rolling Wireless RN947R Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] net: usb: rtl8150: handle link status read failures Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.1] net: prestera: ignore duplicate RIF destruction events Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] net: dsa: mt7530: error out on failed PHY_IAC command writes Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.6] tap: fix incorrect variable used for USO check in set_offload() Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check bus->read() error in core_rmw() Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] net/rds: unpin MR pages with unpin_user_pages_dirty_lock() Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18] netpoll: do not warn when the best-effort pool refill fails Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18] net: libwx: disable TX VLAN offload for packets with >2 VLAN tags Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-6.6] net: sfp: add quirk for HORACO copper SFP+ module Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.15] net: usb: cdc_ether: add quirk for AMI BMC stale link events Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] sctp: auth: propagate HMAC calculation errors to callers Sasha Levin
2026-10-19 17:28 ` Eric Biggers
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] net/rds: fix rds_message leak in the rds_send_xmit() drop path Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] selftests/net: fin_ack_lat: fix latency threshold typo Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] netfilter: ebtables: bound num_counters like nentries in do_replace() Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-6.6] xsk: account ring allocations to memcg Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] net: mvneta_bm: add suspend/resume support to prevent crash after resume Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] net: stmmac: use dma_addr_t for DMA addresses Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-6.12] gre: fix ERSPAN o_flags race/corruption in xmit and fill_info Sasha Levin
2026-10-19 13:51 ` Sasha Levin [this message]
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.15] net: stmmac: raise TX completion interrupt at the end of an xmit burst Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-6.6] net: pcs: mtk-lynxi: check regmap reads in mtk_pcs_lynxi_get_state() Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] net/rds: hold the socket while an rds_mr references it Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] sfc: add X4D PF support Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.1] netfilter: tproxy: use DEBUG_NET_WARN_ON_ONCE for protocol fallbacks Sasha Levin
2026-10-19 13:53 ` [PATCH AUTOSEL 6.18-6.12] net: ethernet: mtk_wed: increase WED v2 WDMA RESV_BUFF to 0x80 Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261019135441.1420968-405-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=coreteam@netfilter.org \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=fw@strlen.de \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pablo@netfilter.org \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox