From: Asbjørn Sloth Tønnesen ast@fiberby.net
[ Upstream commit 9f9581ba74a931843c6d807ecfeaff9fb8c1b731 ]
While updating the binary min-len implementation, I noticed that the only user, should AFAICT be using exact-len instead.
In net/ipv4/fou_core.c FOU_ATTR_LOCAL_V6 and FOU_ATTR_PEER_V6 are only used for singular IPv6 addresses, and there are AFAICT no known implementations trying to send more, it therefore appears safe to change it to an exact-len policy.
This patch therefore changes the local-v6/peer-v6 attributes to use an exact-len check, instead of a min-len check.
Signed-off-by: Asbjørn Sloth Tønnesen ast@fiberby.net Reviewed-by: Donald Hunter donald.hunter@gmail.com Link: https://patch.msgid.link/20250902154640.759815-2-ast@fiberby.net Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES
- What changed: The fou netlink spec and generated policy now enforce exact 16‑byte lengths for IPv6 address attributes instead of allowing any payload ≥16 bytes. - Documentation change: `Documentation/netlink/specs/fou.yaml:55` and `Documentation/netlink/specs/fou.yaml:63` switch `checks` from `min- len: 16` to `exact-len: 16`. - Generated policy change: `net/ipv4/fou_nl.c:21` and `net/ipv4/fou_nl.c:23` switch from a plain length to `NLA_POLICY_EXACT_LEN(16)` for `FOU_ATTR_LOCAL_V6` and `FOU_ATTR_PEER_V6`.
- Why it matters: Fou only ever uses a single IPv6 address for these attributes; there is no valid case for longer payloads. The parser reads exactly one IPv6 address with `nla_get_in6_addr()`: - Read paths: `net/ipv4/fou_core.c:716` (LOCAL_V6) and `net/ipv4/fou_core.c:722` (PEER_V6) copy exactly 16 bytes. - Reply paths also emit exactly 16 bytes with `nla_put_in6_addr()` (`net/ipv4/fou_core.c:801`, `net/ipv4/fou_core.c:805`), confirming the intent is a fixed-size IPv6 address.
- Bug fixed: With a min-length check, malformed attributes longer than 16 bytes are accepted and silently truncated by `nla_get_in6_addr()`. This change correctly rejects such input at policy time, aligning validation with actual usage and preventing garbage/trailing data from slipping through.
- Scope and risk: - Small and contained: Only touches fou’s netlink policy and its spec; no broader architectural or behavioral changes. - ABI correctness: Tightens validation to the actual fixed-size ABI already assumed by the code and reply side. - Compatibility: Legitimate userspace already sends 16‑byte IPv6 addresses; the commit message notes no known implementations rely on larger lengths. Any breakage would only affect incorrect/malformed senders, which is desired. - Consistency: Matches common practice elsewhere for IPv6 attributes (e.g., other generated policies using `NLA_POLICY_EXACT_LEN(16)`).
- Stable backport criteria: - Fixes a real validation/robustness bug that could affect users (acceptance of malformed attributes). - Minimal risk of regression and no architectural changes. - Confined to a specific subsystem (fou netlink family). - Clear, small change with direct correspondence between spec and code.
Given the above, this is a low-risk, correctness/robustness fix that should be backported.
Documentation/netlink/specs/fou.yaml | 4 ++-- net/ipv4/fou_nl.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Documentation/netlink/specs/fou.yaml b/Documentation/netlink/specs/fou.yaml index 57735726262ec..8e7974ec453fc 100644 --- a/Documentation/netlink/specs/fou.yaml +++ b/Documentation/netlink/specs/fou.yaml @@ -52,7 +52,7 @@ attribute-sets: name: local-v6 type: binary checks: - min-len: 16 + exact-len: 16 - name: peer-v4 type: u32 @@ -60,7 +60,7 @@ attribute-sets: name: peer-v6 type: binary checks: - min-len: 16 + exact-len: 16 - name: peer-port type: u16 diff --git a/net/ipv4/fou_nl.c b/net/ipv4/fou_nl.c index 3d9614609b2d3..506260b4a4dc2 100644 --- a/net/ipv4/fou_nl.c +++ b/net/ipv4/fou_nl.c @@ -18,9 +18,9 @@ const struct nla_policy fou_nl_policy[FOU_ATTR_IFINDEX + 1] = { [FOU_ATTR_TYPE] = { .type = NLA_U8, }, [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, }, [FOU_ATTR_LOCAL_V4] = { .type = NLA_U32, }, - [FOU_ATTR_LOCAL_V6] = { .len = 16, }, + [FOU_ATTR_LOCAL_V6] = NLA_POLICY_EXACT_LEN(16), [FOU_ATTR_PEER_V4] = { .type = NLA_U32, }, - [FOU_ATTR_PEER_V6] = { .len = 16, }, + [FOU_ATTR_PEER_V6] = NLA_POLICY_EXACT_LEN(16), [FOU_ATTR_PEER_PORT] = { .type = NLA_BE16, }, [FOU_ATTR_IFINDEX] = { .type = NLA_S32, }, };