netfilter: ctnetlink: fix rcu context imbalance

Introduced by 7ec47496 (netfilter: ctnetlink: cleanup master conntrack assignation):

net/netfilter/nf_conntrack_netlink.c:1275:2: warning: context imbalance in 'ctnetlink_create_conntrack' - different lock contexts for basic block

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2009-03-18 17:36:40 +01:00
parent 711d60a9e7
commit 0f5b3e85a3
1 changed files with 23 additions and 34 deletions

View File

@ -1146,7 +1146,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (!cda[CTA_TIMEOUT]) if (!cda[CTA_TIMEOUT])
goto err; goto err1;
ct->timeout.expires = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); ct->timeout.expires = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
ct->timeout.expires = jiffies + ct->timeout.expires * HZ; ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
@ -1157,10 +1157,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
char *helpname; char *helpname;
err = ctnetlink_parse_help(cda[CTA_HELP], &helpname); err = ctnetlink_parse_help(cda[CTA_HELP], &helpname);
if (err < 0) { if (err < 0)
rcu_read_unlock(); goto err2;
goto err;
}
helper = __nf_conntrack_helper_find_byname(helpname); helper = __nf_conntrack_helper_find_byname(helpname);
if (helper == NULL) { if (helper == NULL) {
@ -1168,28 +1166,26 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
if (request_module("nfct-helper-%s", helpname) < 0) { if (request_module("nfct-helper-%s", helpname) < 0) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto err; goto err1;
} }
rcu_read_lock(); rcu_read_lock();
helper = __nf_conntrack_helper_find_byname(helpname); helper = __nf_conntrack_helper_find_byname(helpname);
if (helper) { if (helper) {
rcu_read_unlock();
err = -EAGAIN; err = -EAGAIN;
goto err; goto err2;
} }
rcu_read_unlock(); rcu_read_unlock();
#endif #endif
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto err; goto err1;
} else { } else {
struct nf_conn_help *help; struct nf_conn_help *help;
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
if (help == NULL) { if (help == NULL) {
rcu_read_unlock();
err = -ENOMEM; err = -ENOMEM;
goto err; goto err2;
} }
/* not in hash table yet so not strictly necessary */ /* not in hash table yet so not strictly necessary */
@ -1198,44 +1194,34 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
} else { } else {
/* try an implicit helper assignation */ /* try an implicit helper assignation */
err = __nf_ct_try_assign_helper(ct, GFP_ATOMIC); err = __nf_ct_try_assign_helper(ct, GFP_ATOMIC);
if (err < 0) { if (err < 0)
rcu_read_unlock(); goto err2;
goto err;
}
} }
if (cda[CTA_STATUS]) { if (cda[CTA_STATUS]) {
err = ctnetlink_change_status(ct, cda); err = ctnetlink_change_status(ct, cda);
if (err < 0) { if (err < 0)
rcu_read_unlock(); goto err2;
goto err;
}
} }
if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
err = ctnetlink_change_nat(ct, cda); err = ctnetlink_change_nat(ct, cda);
if (err < 0) { if (err < 0)
rcu_read_unlock(); goto err2;
goto err;
}
} }
#ifdef CONFIG_NF_NAT_NEEDED #ifdef CONFIG_NF_NAT_NEEDED
if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) { if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) {
err = ctnetlink_change_nat_seq_adj(ct, cda); err = ctnetlink_change_nat_seq_adj(ct, cda);
if (err < 0) { if (err < 0)
rcu_read_unlock(); goto err2;
goto err;
}
} }
#endif #endif
if (cda[CTA_PROTOINFO]) { if (cda[CTA_PROTOINFO]) {
err = ctnetlink_change_protoinfo(ct, cda); err = ctnetlink_change_protoinfo(ct, cda);
if (err < 0) { if (err < 0)
rcu_read_unlock(); goto err2;
goto err;
}
} }
nf_ct_acct_ext_add(ct, GFP_ATOMIC); nf_ct_acct_ext_add(ct, GFP_ATOMIC);
@ -1253,12 +1239,12 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER, u3); err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER, u3);
if (err < 0) if (err < 0)
goto err; goto err2;
master_h = __nf_conntrack_find(&init_net, &master); master_h = __nf_conntrack_find(&init_net, &master);
if (master_h == NULL) { if (master_h == NULL) {
err = -ENOENT; err = -ENOENT;
goto err; goto err2;
} }
master_ct = nf_ct_tuplehash_to_ctrack(master_h); master_ct = nf_ct_tuplehash_to_ctrack(master_h);
nf_conntrack_get(&master_ct->ct_general); nf_conntrack_get(&master_ct->ct_general);
@ -1271,7 +1257,10 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
rcu_read_unlock(); rcu_read_unlock();
return ct; return ct;
err:
err2:
rcu_read_unlock();
err1:
nf_conntrack_free(ct); nf_conntrack_free(ct);
return ERR_PTR(err); return ERR_PTR(err);
} }