Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[NETFILTER]: don't use nested attributes for conntrack_expect

We used to use nested nfattr structures for ip_conntrack_expect. This is
bogus, since ip_conntrack and ip_conntrack_expect are communicated in
different netlink message types. both should be encoded at the top level
attributes, no extra nesting required. This patch addresses the issue.

Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Harald Welte and committed by
David S. Miller
1444fc55 a42827b7

+41 -47
+39 -46
net/ipv4/netfilter/ip_conntrack_netlink.c
··· 1100 1100 ctnetlink_exp_dump_expect(struct sk_buff *skb, 1101 1101 const struct ip_conntrack_expect *exp) 1102 1102 { 1103 + struct ip_conntrack *master = exp->master; 1103 1104 u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ); 1104 1105 u_int32_t id = htonl(exp->id); 1105 - struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT); 1106 1106 1107 1107 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) 1108 1108 goto nfattr_failure; 1109 1109 if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0) 1110 1110 goto nfattr_failure; 1111 + if (ctnetlink_exp_dump_tuple(skb, 1112 + &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, 1113 + CTA_EXPECT_MASTER) < 0) 1114 + goto nfattr_failure; 1111 1115 1112 1116 NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout); 1113 1117 NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id); 1114 - NFA_NEST_END(skb, nest_parms); 1115 1118 1116 1119 return 0; 1117 1120 ··· 1262 1259 return 0; 1263 1260 } 1264 1261 1265 - if (cda[CTA_TUPLE_ORIG-1]) 1266 - err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG); 1267 - else if (cda[CTA_TUPLE_REPLY-1]) 1268 - err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY); 1262 + if (cda[CTA_EXPECT_MASTER-1]) 1263 + err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER); 1269 1264 else 1270 1265 return -EINVAL; 1271 1266 ··· 1311 1310 struct ip_conntrack_helper *h; 1312 1311 int err; 1313 1312 1314 - /* delete by tuple needs either orig or reply tuple */ 1315 - if (cda[CTA_TUPLE_ORIG-1]) 1316 - err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG); 1317 - else if (cda[CTA_TUPLE_REPLY-1]) 1318 - err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY); 1319 - else if (cda[CTA_HELP_NAME-1]) { 1320 - char *name = NFA_DATA(cda[CTA_HELP_NAME-1]); 1313 + if (cda[CTA_EXPECT_TUPLE-1]) { 1314 + /* delete a single expect by tuple */ 1315 + err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); 1316 + if (err < 0) 1317 + return err; 1318 + 1319 + /* bump usage count to 2 */ 1320 + exp = ip_conntrack_expect_find_get(&tuple); 1321 + if (!exp) 1322 + return -ENOENT; 1323 + 1324 + if (cda[CTA_EXPECT_ID-1]) { 1325 + u_int32_t id = 1326 + *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]); 1327 + if (exp->id != ntohl(id)) { 1328 + ip_conntrack_expect_put(exp); 1329 + return -ENOENT; 1330 + } 1331 + } 1332 + 1333 + /* after list removal, usage count == 1 */ 1334 + ip_conntrack_unexpect_related(exp); 1335 + /* have to put what we 'get' above. 1336 + * after this line usage count == 0 */ 1337 + ip_conntrack_expect_put(exp); 1338 + } else if (cda[CTA_EXPECT_HELP_NAME-1]) { 1339 + char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]); 1321 1340 1322 1341 /* delete all expectations for this helper */ 1323 1342 write_lock_bh(&ip_conntrack_lock); ··· 1353 1332 __ip_ct_expect_unlink_destroy(exp); 1354 1333 } 1355 1334 write_unlock(&ip_conntrack_lock); 1356 - return 0; 1357 1335 } else { 1358 1336 /* This basically means we have to flush everything*/ 1359 1337 write_lock_bh(&ip_conntrack_lock); ··· 1362 1342 __ip_ct_expect_unlink_destroy(exp); 1363 1343 } 1364 1344 write_unlock_bh(&ip_conntrack_lock); 1365 - return 0; 1366 1345 } 1367 - 1368 - if (err < 0) 1369 - return err; 1370 - 1371 - /* bump usage count to 2 */ 1372 - exp = ip_conntrack_expect_find_get(&tuple); 1373 - if (!exp) 1374 - return -ENOENT; 1375 - 1376 - if (cda[CTA_EXPECT_ID-1]) { 1377 - u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]); 1378 - if (exp->id != ntohl(id)) { 1379 - ip_conntrack_expect_put(exp); 1380 - return -ENOENT; 1381 - } 1382 - } 1383 - 1384 - /* after list removal, usage count == 1 */ 1385 - ip_conntrack_unexpect_related(exp); 1386 - /* have to put what we 'get' above. after this line usage count == 0 */ 1387 - ip_conntrack_expect_put(exp); 1388 1346 1389 1347 return 0; 1390 1348 } ··· 1383 1385 1384 1386 DEBUGP("entered %s\n", __FUNCTION__); 1385 1387 1388 + /* caller guarantees that those three CTA_EXPECT_* exist */ 1386 1389 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); 1387 1390 if (err < 0) 1388 1391 return err; 1389 1392 err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK); 1390 1393 if (err < 0) 1391 1394 return err; 1392 - 1393 - if (cda[CTA_TUPLE_ORIG-1]) 1394 - err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_TUPLE_ORIG); 1395 - else if (cda[CTA_TUPLE_REPLY-1]) 1396 - err = ctnetlink_parse_tuple(cda, &master_tuple, 1397 - CTA_TUPLE_REPLY); 1398 - else 1399 - return -EINVAL; 1400 - 1395 + err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER); 1401 1396 if (err < 0) 1402 1397 return err; 1403 1398 ··· 1435 1444 1436 1445 DEBUGP("entered %s\n", __FUNCTION__); 1437 1446 1438 - if (!cda[CTA_EXPECT_TUPLE-1] || !cda[CTA_EXPECT_MASK-1]) 1447 + if (!cda[CTA_EXPECT_TUPLE-1] 1448 + || !cda[CTA_EXPECT_MASK-1] 1449 + || !cda[CTA_EXPECT_MASTER-1]) 1439 1450 return -EINVAL; 1440 1451 1441 1452 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);