aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-08-19 00:30:55 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-19 00:30:55 -0400
commit1575e7ea018fec992b94a12a1a491ce693ae9eac (patch)
tree5a93c71ea8ac0cb1ad0703c0ee03cd52aa268707 /net
parent46faec9858e8943226464dac50e205bf210d9174 (diff)
netfilter: ctnetlink: fix double helper assignation for NAT'ed conntracks
If we create a conntrack that has NAT handlings and a helper, the helper is assigned twice. This happens because nf_nat_setup_info() - via nf_conntrack_alter_reply() - sets the helper before ctnetlink, which indeed does not check if the conntrack already has a helper as it thinks that it is a brand new conntrack. The fix moves the helper assignation before the set of the status flags. This avoids a bogus assertion in __nf_ct_ext_add (if netfilter assertions are enabled) which checks that the conntrack must not be confirmed. This problem was introduced in 2.6.23 with the netfilter extension infrastructure. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_netlink.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 105a616c5c78..d1fb2f8555e8 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1136,16 +1136,33 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
1136 ct->timeout.expires = jiffies + ct->timeout.expires * HZ; 1136 ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
1137 ct->status |= IPS_CONFIRMED; 1137 ct->status |= IPS_CONFIRMED;
1138 1138
1139 rcu_read_lock();
1140 helper = __nf_ct_helper_find(rtuple);
1141 if (helper) {
1142 help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
1143 if (help == NULL) {
1144 rcu_read_unlock();
1145 err = -ENOMEM;
1146 goto err;
1147 }
1148 /* not in hash table yet so not strictly necessary */
1149 rcu_assign_pointer(help->helper, helper);
1150 }
1151
1139 if (cda[CTA_STATUS]) { 1152 if (cda[CTA_STATUS]) {
1140 err = ctnetlink_change_status(ct, cda); 1153 err = ctnetlink_change_status(ct, cda);
1141 if (err < 0) 1154 if (err < 0) {
1155 rcu_read_unlock();
1142 goto err; 1156 goto err;
1157 }
1143 } 1158 }
1144 1159
1145 if (cda[CTA_PROTOINFO]) { 1160 if (cda[CTA_PROTOINFO]) {
1146 err = ctnetlink_change_protoinfo(ct, cda); 1161 err = ctnetlink_change_protoinfo(ct, cda);
1147 if (err < 0) 1162 if (err < 0) {
1163 rcu_read_unlock();
1148 goto err; 1164 goto err;
1165 }
1149 } 1166 }
1150 1167
1151 nf_ct_acct_ext_add(ct, GFP_KERNEL); 1168 nf_ct_acct_ext_add(ct, GFP_KERNEL);
@@ -1155,19 +1172,6 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
1155 ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); 1172 ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
1156#endif 1173#endif
1157 1174
1158 rcu_read_lock();
1159 helper = __nf_ct_helper_find(rtuple);
1160 if (helper) {
1161 help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
1162 if (help == NULL) {
1163 rcu_read_unlock();
1164 err = -ENOMEM;
1165 goto err;
1166 }
1167 /* not in hash table yet so not strictly necessary */
1168 rcu_assign_pointer(help->helper, helper);
1169 }
1170
1171 /* setup master conntrack: this is a confirmed expectation */ 1175 /* setup master conntrack: this is a confirmed expectation */
1172 if (master_ct) { 1176 if (master_ct) {
1173 __set_bit(IPS_EXPECTED_BIT, &ct->status); 1177 __set_bit(IPS_EXPECTED_BIT, &ct->status);