Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ctnetlink: use netlink policy range checks

Replace manual range and mask validations with netlink policy
annotations in ctnetlink code paths, so that the netlink core rejects
invalid values early and can generate extack errors.

- CTA_PROTOINFO_TCP_STATE: reject values > TCP_CONNTRACK_SYN_SENT2 at
policy level, removing the manual >= TCP_CONNTRACK_MAX check.
- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL/REPLY: reject values > TCP_MAX_WSCALE
(14). The normal TCP option parsing path already clamps to this value,
but the ctnetlink path accepted 0-255, causing undefined behavior when
used as a u32 shift count.
- CTA_FILTER_ORIG_FLAGS/REPLY_FLAGS: use NLA_POLICY_MASK with
CTA_FILTER_F_ALL, removing the manual mask checks.
- CTA_EXPECT_FLAGS: use NLA_POLICY_MASK with NF_CT_EXPECT_MASK, adding
a new mask define grouping all valid expect flags.

Extracted from a broader nf-next patch by Florian Westphal, scoped to
ctnetlink for the fixes tree.

Fixes: c8e2078cfe41 ("[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling")
Signed-off-by: David Carlier <devnexen@gmail.com>
Co-developed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

David Carlier and committed by
Pablo Neira Ayuso
8f15b507 6a2b7244

+12 -18
+4
include/uapi/linux/netfilter/nf_conntrack_common.h
··· 159 159 #define NF_CT_EXPECT_INACTIVE 0x2 160 160 #define NF_CT_EXPECT_USERSPACE 0x4 161 161 162 + #ifdef __KERNEL__ 163 + #define NF_CT_EXPECT_MASK (NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE | \ 164 + NF_CT_EXPECT_USERSPACE) 165 + #endif 162 166 163 167 #endif /* _UAPI_NF_CONNTRACK_COMMON_H */
+5 -11
net/netfilter/nf_conntrack_netlink.c
··· 910 910 }; 911 911 912 912 static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { 913 - [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, 914 - [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, 913 + [CTA_FILTER_ORIG_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), 914 + [CTA_FILTER_REPLY_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), 915 915 }; 916 916 917 917 static int ctnetlink_parse_filter(const struct nlattr *attr, ··· 925 925 if (ret) 926 926 return ret; 927 927 928 - if (tb[CTA_FILTER_ORIG_FLAGS]) { 928 + if (tb[CTA_FILTER_ORIG_FLAGS]) 929 929 filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); 930 - if (filter->orig_flags & ~CTA_FILTER_F_ALL) 931 - return -EOPNOTSUPP; 932 - } 933 930 934 - if (tb[CTA_FILTER_REPLY_FLAGS]) { 931 + if (tb[CTA_FILTER_REPLY_FLAGS]) 935 932 filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); 936 - if (filter->reply_flags & ~CTA_FILTER_F_ALL) 937 - return -EOPNOTSUPP; 938 - } 939 933 940 934 return 0; 941 935 } ··· 2628 2634 [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, 2629 2635 .len = NF_CT_HELPER_NAME_LEN - 1 }, 2630 2636 [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, 2631 - [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, 2637 + [CTA_EXPECT_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NF_CT_EXPECT_MASK), 2632 2638 [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, 2633 2639 [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, 2634 2640 [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING },
+3 -7
net/netfilter/nf_conntrack_proto_tcp.c
··· 1385 1385 } 1386 1386 1387 1387 static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { 1388 - [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, 1389 - [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, 1390 - [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, 1388 + [CTA_PROTOINFO_TCP_STATE] = NLA_POLICY_MAX(NLA_U8, TCP_CONNTRACK_SYN_SENT2), 1389 + [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), 1390 + [CTA_PROTOINFO_TCP_WSCALE_REPLY] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), 1391 1391 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, 1392 1392 [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, 1393 1393 }; ··· 1413 1413 tcp_nla_policy, NULL); 1414 1414 if (err < 0) 1415 1415 return err; 1416 - 1417 - if (tb[CTA_PROTOINFO_TCP_STATE] && 1418 - nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) 1419 - return -EINVAL; 1420 1416 1421 1417 spin_lock_bh(&ct->lock); 1422 1418 if (tb[CTA_PROTOINFO_TCP_STATE])