|
@@ -1136,16 +1136,33 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
|
|
|
ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
|
|
|
ct->status |= IPS_CONFIRMED;
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
+ helper = __nf_ct_helper_find(rtuple);
|
|
|
+ if (helper) {
|
|
|
+ help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
|
|
|
+ if (help == NULL) {
|
|
|
+ rcu_read_unlock();
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ /* not in hash table yet so not strictly necessary */
|
|
|
+ rcu_assign_pointer(help->helper, helper);
|
|
|
+ }
|
|
|
+
|
|
|
if (cda[CTA_STATUS]) {
|
|
|
err = ctnetlink_change_status(ct, cda);
|
|
|
- if (err < 0)
|
|
|
+ if (err < 0) {
|
|
|
+ rcu_read_unlock();
|
|
|
goto err;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (cda[CTA_PROTOINFO]) {
|
|
|
err = ctnetlink_change_protoinfo(ct, cda);
|
|
|
- if (err < 0)
|
|
|
+ if (err < 0) {
|
|
|
+ rcu_read_unlock();
|
|
|
goto err;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
nf_ct_acct_ext_add(ct, GFP_KERNEL);
|
|
@@ -1155,19 +1172,6 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
|
|
|
ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
|
|
|
#endif
|
|
|
|
|
|
- rcu_read_lock();
|
|
|
- helper = __nf_ct_helper_find(rtuple);
|
|
|
- if (helper) {
|
|
|
- help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
|
|
|
- if (help == NULL) {
|
|
|
- rcu_read_unlock();
|
|
|
- err = -ENOMEM;
|
|
|
- goto err;
|
|
|
- }
|
|
|
- /* not in hash table yet so not strictly necessary */
|
|
|
- rcu_assign_pointer(help->helper, helper);
|
|
|
- }
|
|
|
-
|
|
|
/* setup master conntrack: this is a confirmed expectation */
|
|
|
if (master_ct) {
|
|
|
__set_bit(IPS_EXPECTED_BIT, &ct->status);
|