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

Configure Feed

Select the types of activity you want to include in your feed.

netfilter: nf_conntrack_expect: use expect->helper

Use expect->helper in ctnetlink and /proc to dump the helper name.
Using nfct_help() without holding a reference to the master conntrack
is unsafe.

Use exp->master->helper in ctnetlink path if userspace does not provide
an explicit helper when creating an expectation to retain the existing
behaviour. The ctnetlink expectation path holds the reference on the
master conntrack and nf_conntrack_expect lock and the nfnetlink glue
path refers to the master ct that is attached to the skb.

Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+13 -21
+1 -1
net/netfilter/nf_conntrack_expect.c
··· 666 666 if (expect->flags & NF_CT_EXPECT_USERSPACE) 667 667 seq_printf(s, "%sUSERSPACE", delim); 668 668 669 - helper = rcu_dereference(nfct_help(expect->master)->helper); 669 + helper = rcu_dereference(expect->helper); 670 670 if (helper) { 671 671 seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name); 672 672 if (helper->expect_policy[expect->class].name[0])
+1 -5
net/netfilter/nf_conntrack_helper.c
··· 395 395 396 396 static bool expect_iter_me(struct nf_conntrack_expect *exp, void *data) 397 397 { 398 - struct nf_conn_help *help = nfct_help(exp->master); 399 398 const struct nf_conntrack_helper *me = data; 400 399 const struct nf_conntrack_helper *this; 401 400 402 - if (rcu_access_pointer(exp->helper) == me) 403 - return true; 404 - 405 - this = rcu_dereference_protected(help->helper, 401 + this = rcu_dereference_protected(exp->helper, 406 402 lockdep_is_held(&nf_conntrack_expect_lock)); 407 403 return this == me; 408 404 }
+10 -14
net/netfilter/nf_conntrack_netlink.c
··· 3012 3012 { 3013 3013 struct nf_conn *master = exp->master; 3014 3014 long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ; 3015 - struct nf_conn_help *help; 3015 + struct nf_conntrack_helper *helper; 3016 3016 #if IS_ENABLED(CONFIG_NF_NAT) 3017 3017 struct nlattr *nest_parms; 3018 3018 struct nf_conntrack_tuple nat_tuple = {}; ··· 3057 3057 nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) || 3058 3058 nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class))) 3059 3059 goto nla_put_failure; 3060 - help = nfct_help(master); 3061 - if (help) { 3062 - struct nf_conntrack_helper *helper; 3063 3060 3064 - helper = rcu_dereference(help->helper); 3065 - if (helper && 3066 - nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name)) 3067 - goto nla_put_failure; 3068 - } 3061 + helper = rcu_dereference(exp->helper); 3062 + if (helper && 3063 + nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name)) 3064 + goto nla_put_failure; 3065 + 3069 3066 expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn); 3070 3067 if (expfn != NULL && 3071 3068 nla_put_string(skb, CTA_EXPECT_FN, expfn->name)) ··· 3391 3394 static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data) 3392 3395 { 3393 3396 struct nf_conntrack_helper *helper; 3394 - const struct nf_conn_help *m_help; 3395 3397 const char *name = data; 3396 3398 3397 - m_help = nfct_help(exp->master); 3398 - 3399 - helper = rcu_dereference(m_help->helper); 3399 + helper = rcu_dereference(exp->helper); 3400 3400 if (!helper) 3401 3401 return false; 3402 3402 ··· 3528 3534 struct nf_conntrack_tuple *tuple, 3529 3535 struct nf_conntrack_tuple *mask) 3530 3536 { 3531 - u_int32_t class = 0; 3532 3537 struct nf_conntrack_expect *exp; 3533 3538 struct nf_conn_help *help; 3539 + u32 class = 0; 3534 3540 int err; 3535 3541 3536 3542 help = nfct_help(ct); ··· 3567 3573 3568 3574 exp->class = class; 3569 3575 exp->master = ct; 3576 + if (!helper) 3577 + helper = rcu_dereference(help->helper); 3570 3578 rcu_assign_pointer(exp->helper, helper); 3571 3579 exp->tuple = *tuple; 3572 3580 exp->mask.src.u3 = mask->src.u3;
+1 -1
net/netfilter/nf_conntrack_sip.c
··· 924 924 exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); 925 925 926 926 if (!exp || exp->master == ct || 927 - nfct_help(exp->master)->helper != nfct_help(ct)->helper || 927 + exp->helper != nfct_help(ct)->helper || 928 928 exp->class != class) 929 929 break; 930 930 #if IS_ENABLED(CONFIG_NF_NAT)