diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 8b05f364b2f2c18415bbc26ac0bbcecf5425b8ea..2b2af631d2b870d3c9f4f81146833fd4a93f2cf9 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1077,9 +1077,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) /* need to zero data of old helper */ memset(&help->help, 0, sizeof(help->help)); } else { - help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); - if (help == NULL) - return -ENOMEM; + /* we cannot set a helper for an existing conntrack */ + return -EOPNOTSUPP; } rcu_assign_pointer(help->helper, helper); @@ -1263,7 +1262,6 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, ct->timeout.expires = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); ct->timeout.expires = jiffies + ct->timeout.expires * HZ; - ct->status |= IPS_CONFIRMED; rcu_read_lock(); if (cda[CTA_HELP]) { @@ -1314,14 +1312,19 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, goto err2; } - if (cda[CTA_STATUS]) { - err = ctnetlink_change_status(ct, cda); + if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { + err = ctnetlink_change_nat(ct, cda); if (err < 0) goto err2; } - if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { - err = ctnetlink_change_nat(ct, cda); + nf_ct_acct_ext_add(ct, GFP_ATOMIC); + nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); + /* we must add conntrack extensions before confirmation. */ + ct->status |= IPS_CONFIRMED; + + if (cda[CTA_STATUS]) { + err = ctnetlink_change_status(ct, cda); if (err < 0) goto err2; } @@ -1340,9 +1343,6 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, goto err2; } - nf_ct_acct_ext_add(ct, GFP_ATOMIC); - nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); - #if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK]) ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));