mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
netfilter: nfnetlink_cthelper: use {READ,WRITE}_ONCE for accessing helper flags
Conntrack helper flags are accessed from packet and netlink dump path.
Concurrent update of userspace helper flags is not possible, because the
nfnl_mutex in held on updates. These flags are only used by userspace
helpers. Use {READ,WRITE}_ONCE() to access this flags from lockless
paths.
Fixes: 12f7a50533 ("netfilter: add user-space connection tracking helper infrastructure")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
a625c94144
commit
f8bf5edf71
|
|
@ -2213,6 +2213,7 @@ static int nf_confirm_cthelper(struct sk_buff *skb, struct nf_conn *ct,
|
|||
{
|
||||
const struct nf_conntrack_helper *helper;
|
||||
const struct nf_conn_help *help;
|
||||
unsigned int helper_flags;
|
||||
int protoff;
|
||||
|
||||
help = nfct_help(ct);
|
||||
|
|
@ -2223,7 +2224,8 @@ static int nf_confirm_cthelper(struct sk_buff *skb, struct nf_conn *ct,
|
|||
if (!helper)
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (!(helper->flags & NF_CT_HELPER_F_USERSPACE))
|
||||
helper_flags = READ_ONCE(helper->flags);
|
||||
if (!(helper_flags & NF_CT_HELPER_F_USERSPACE))
|
||||
return NF_ACCEPT;
|
||||
|
||||
switch (nf_ct_l3num(ct)) {
|
||||
|
|
|
|||
|
|
@ -41,8 +41,9 @@ static int
|
|||
nfnl_userspace_cthelper(struct sk_buff *skb, unsigned int protoff,
|
||||
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
|
||||
{
|
||||
const struct nf_conn_help *help;
|
||||
struct nf_conntrack_helper *helper;
|
||||
const struct nf_conn_help *help;
|
||||
unsigned int helper_flags;
|
||||
|
||||
help = nfct_help(ct);
|
||||
if (help == NULL)
|
||||
|
|
@ -53,8 +54,10 @@ nfnl_userspace_cthelper(struct sk_buff *skb, unsigned int protoff,
|
|||
if (helper == NULL)
|
||||
return NF_DROP;
|
||||
|
||||
helper_flags = READ_ONCE(helper->flags);
|
||||
|
||||
/* This is a user-space helper not yet configured, skip. */
|
||||
if ((helper->flags &
|
||||
if ((helper_flags &
|
||||
(NF_CT_HELPER_F_USERSPACE | NF_CT_HELPER_F_CONFIGURED)) ==
|
||||
NF_CT_HELPER_F_USERSPACE)
|
||||
return NF_ACCEPT;
|
||||
|
|
@ -404,10 +407,10 @@ nfnl_cthelper_update(const struct nlattr * const tb[],
|
|||
|
||||
switch(status) {
|
||||
case NFCT_HELPER_STATUS_ENABLED:
|
||||
helper->flags |= NF_CT_HELPER_F_CONFIGURED;
|
||||
WRITE_ONCE(helper->flags, helper->flags | NF_CT_HELPER_F_CONFIGURED);
|
||||
break;
|
||||
case NFCT_HELPER_STATUS_DISABLED:
|
||||
helper->flags &= ~NF_CT_HELPER_F_CONFIGURED;
|
||||
WRITE_ONCE(helper->flags, helper->flags & ~NF_CT_HELPER_F_CONFIGURED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -529,8 +532,8 @@ static int
|
|||
nfnl_cthelper_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
int event, struct nf_conntrack_helper *helper)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0;
|
||||
struct nlmsghdr *nlh;
|
||||
int status;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTHELPER, event);
|
||||
|
|
@ -554,7 +557,7 @@ nfnl_cthelper_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
|||
if (nla_put_be32(skb, NFCTH_PRIV_DATA_LEN, htonl(helper->data_len)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (helper->flags & NF_CT_HELPER_F_CONFIGURED)
|
||||
if (READ_ONCE(helper->flags) & NF_CT_HELPER_F_CONFIGURED)
|
||||
status = NFCT_HELPER_STATUS_ENABLED;
|
||||
else
|
||||
status = NFCT_HELPER_STATUS_DISABLED;
|
||||
|
|
@ -575,6 +578,7 @@ static int
|
|||
nfnl_cthelper_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct nf_conntrack_helper *cur, *last;
|
||||
unsigned int helper_flags;
|
||||
|
||||
rcu_read_lock();
|
||||
last = (struct nf_conntrack_helper *)cb->args[1];
|
||||
|
|
@ -583,8 +587,10 @@ nfnl_cthelper_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
hlist_for_each_entry_rcu(cur,
|
||||
&nf_ct_helper_hash[cb->args[0]], hnode) {
|
||||
|
||||
helper_flags = READ_ONCE(cur->flags);
|
||||
|
||||
/* skip non-userspace conntrack helpers. */
|
||||
if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
|
||||
if (!(helper_flags & NF_CT_HELPER_F_USERSPACE))
|
||||
continue;
|
||||
|
||||
if (cb->args[1]) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user