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

netfilter: ctnetlink: fix filtering for zone 0

previously filtering for the default zone would actually skip the zone
filter and flush all zones.

Fixes: eff3c558bb7e ("netfilter: ctnetlink: support filtering by zone")
Reported-by: Ilya Maximets <i.maximets@ovn.org>
Closes: https://lore.kernel.org/netdev/2032238f-31ac-4106-8f22-522e76df5a12@ovn.org/
Signed-off-by: Felix Huettner <felix.huettner@mail.schwarz>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Felix Huettner and committed by
Pablo Neira Ayuso
fa173a1b 27c5a095

+50 -5
+8 -4
net/netfilter/nf_conntrack_netlink.c
··· 876 876 877 877 struct ctnetlink_filter { 878 878 u8 family; 879 + bool zone_filter; 879 880 880 881 u_int32_t orig_flags; 881 882 u_int32_t reply_flags; ··· 993 992 if (err) 994 993 goto err_filter; 995 994 996 - err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone); 997 - if (err < 0) 998 - goto err_filter; 995 + if (cda[CTA_ZONE]) { 996 + err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone); 997 + if (err < 0) 998 + goto err_filter; 999 + filter->zone_filter = true; 1000 + } 999 1001 1000 1002 if (!cda[CTA_FILTER]) 1001 1003 return filter; ··· 1152 1148 if (filter->family && nf_ct_l3num(ct) != filter->family) 1153 1149 goto ignore_entry; 1154 1150 1155 - if (filter->zone.id != NF_CT_DEFAULT_ZONE_ID && 1151 + if (filter->zone_filter && 1156 1152 !nf_ct_zone_equal_any(ct, &filter->zone)) 1157 1153 goto ignore_entry; 1158 1154
+42 -1
tools/testing/selftests/netfilter/conntrack_dump_flush.c
··· 13 13 #include "../kselftest_harness.h" 14 14 15 15 #define TEST_ZONE_ID 123 16 - #define CTA_FILTER_F_CTA_TUPLE_ZONE (1 << 2) 16 + #define NF_CT_DEFAULT_ZONE_ID 0 17 17 18 18 static int reply_counter; 19 19 ··· 336 336 ret = conntrack_data_generate_v4(self->sock, 0xf4f4f4f4, 0xf5f5f5f5, 337 337 TEST_ZONE_ID + 2); 338 338 EXPECT_EQ(ret, 0); 339 + ret = conntrack_data_generate_v4(self->sock, 0xf6f6f6f6, 0xf7f7f7f7, 340 + NF_CT_DEFAULT_ZONE_ID); 341 + EXPECT_EQ(ret, 0); 339 342 340 343 src = (struct in6_addr) {{ 341 344 .__u6_addr32 = { ··· 398 395 TEST_ZONE_ID + 2); 399 396 EXPECT_EQ(ret, 0); 400 397 398 + src = (struct in6_addr) {{ 399 + .__u6_addr32 = { 400 + 0xb80d0120, 401 + 0x00000000, 402 + 0x00000000, 403 + 0x07000000 404 + } 405 + }}; 406 + dst = (struct in6_addr) {{ 407 + .__u6_addr32 = { 408 + 0xb80d0120, 409 + 0x00000000, 410 + 0x00000000, 411 + 0x08000000 412 + } 413 + }}; 414 + ret = conntrack_data_generate_v6(self->sock, src, dst, 415 + NF_CT_DEFAULT_ZONE_ID); 416 + EXPECT_EQ(ret, 0); 417 + 401 418 ret = conntracK_count_zone(self->sock, TEST_ZONE_ID); 402 419 EXPECT_GE(ret, 2); 403 420 if (ret > 2) ··· 448 425 EXPECT_EQ(ret, 2); 449 426 ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 2); 450 427 EXPECT_EQ(ret, 2); 428 + ret = conntracK_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID); 429 + EXPECT_EQ(ret, 2); 430 + } 431 + 432 + TEST_F(conntrack_dump_flush, test_flush_by_zone_default) 433 + { 434 + int ret; 435 + 436 + ret = conntrack_flush_zone(self->sock, NF_CT_DEFAULT_ZONE_ID); 437 + EXPECT_EQ(ret, 0); 438 + ret = conntracK_count_zone(self->sock, TEST_ZONE_ID); 439 + EXPECT_EQ(ret, 2); 440 + ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 1); 441 + EXPECT_EQ(ret, 2); 442 + ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 2); 443 + EXPECT_EQ(ret, 2); 444 + ret = conntracK_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID); 445 + EXPECT_EQ(ret, 0); 451 446 } 452 447 453 448 TEST_HARNESS_MAIN