ctnetlink_alloc_expect() validates CTA_EXPECT_CLASS against the helper specified by CTA_EXPECT_HELP_NAME. However, __nf_ct_expect_check() and nf_ct_expect_insert() later index the expect_policy array using the master conntrack's actual helper. When the supplied helper has a larger expect_class_max than the master's helper, the class passes validation but produces an out-of-bounds read on the master helper's heap-allocated policy array during expectation insertion. Validate the class against the master conntrack's own helper instead, since that is the helper whose policy array will actually be indexed. BUG: KASAN: slab-out-of-bounds in nf_ct_expect_related_report+0x2479/0x27c0 Read of size 4 at addr ffff8880043fe408 by task poc/102 Call Trace: nf_ct_expect_related_report+0x2479/0x27c0 ctnetlink_create_expect+0x22b/0x3b0 ctnetlink_new_expect+0x4bd/0x5c0 nfnetlink_rcv_msg+0x67a/0x950 netlink_rcv_skb+0x120/0x350 Fixes: b8c5e52c13ed ("netfilter: ctnetlink: allow to set expectation class") Signed-off-by: Qi Tang --- net/netfilter/nf_conntrack_netlink.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 3f408f3713bb..c57c665363e0 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -3542,9 +3542,14 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct, if (!help) return ERR_PTR(-EOPNOTSUPP); - if (cda[CTA_EXPECT_CLASS] && helper) { + if (cda[CTA_EXPECT_CLASS]) { + struct nf_conntrack_helper *master_helper; + + master_helper = rcu_dereference(help->helper); + if (!master_helper) + return ERR_PTR(-EOPNOTSUPP); class = ntohl(nla_get_be32(cda[CTA_EXPECT_CLASS])); - if (class > helper->expect_class_max) + if (class > master_helper->expect_class_max) return ERR_PTR(-EINVAL); } exp = nf_ct_expect_alloc(ct); -- 2.43.0