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

Revert "netfilter: xtables: compute exact size needed for jumpstack"

This reverts commit 98d1bd802cdbc8f56868fae51edec13e86b59515.

mark_source_chains will not re-visit chains, so

*filter
:INPUT ACCEPT [365:25776]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [217:45832]
:t1 - [0:0]
:t2 - [0:0]
:t3 - [0:0]
:t4 - [0:0]
-A t1 -i lo -j t2
-A t2 -i lo -j t3
-A t3 -i lo -j t4
# -A INPUT -j t4
# -A INPUT -j t3
# -A INPUT -j t2
-A INPUT -j t1
COMMIT

Will compute a chain depth of 2 if the comments are removed.
Revert back to counting the number of chains for the time being.

Reported-by: Cong Wang <cwang@twopensource.com>
Reported-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
98dbbfc3 1b383bf9

+25 -45
+7 -12
net/ipv4/netfilter/arp_tables.c
··· 367 367 368 368 /* Figures out from what hook each rule can be called: returns 0 if 369 369 * there are loops. Puts hook bitmask in comefrom. 370 - * 371 - * Keeps track of largest call depth seen and stores it in newinfo->stacksize. 372 370 */ 373 - static int mark_source_chains(struct xt_table_info *newinfo, 371 + static int mark_source_chains(const struct xt_table_info *newinfo, 374 372 unsigned int valid_hooks, void *entry0) 375 373 { 376 - unsigned int calldepth, max_calldepth = 0; 377 374 unsigned int hook; 378 375 379 376 /* No recursion; use packet counter to save back ptrs (reset ··· 386 389 387 390 /* Set initial back pointer. */ 388 391 e->counters.pcnt = pos; 389 - calldepth = 0; 390 392 391 393 for (;;) { 392 394 const struct xt_standard_target *t ··· 440 444 (entry0 + pos + size); 441 445 e->counters.pcnt = pos; 442 446 pos += size; 443 - if (calldepth > 0) 444 - --calldepth; 445 447 } else { 446 448 int newpos = t->verdict; 447 449 ··· 453 459 newpos); 454 460 return 0; 455 461 } 456 - 457 - if (entry0 + newpos != arpt_next_entry(e) && 458 - ++calldepth > max_calldepth) 459 - max_calldepth = calldepth; 460 462 461 463 /* This a jump; chase it. */ 462 464 duprintf("Jump rule %u -> %u\n", ··· 470 480 next: 471 481 duprintf("Finished chain %u\n", hook); 472 482 } 473 - newinfo->stacksize = max_calldepth; 474 483 return 1; 475 484 } 476 485 ··· 659 670 if (ret != 0) 660 671 break; 661 672 ++i; 673 + if (strcmp(arpt_get_target(iter)->u.user.name, 674 + XT_ERROR_TARGET) == 0) 675 + ++newinfo->stacksize; 662 676 } 663 677 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); 664 678 if (ret != 0) ··· 1434 1442 break; 1435 1443 } 1436 1444 ++i; 1445 + if (strcmp(arpt_get_target(iter1)->u.user.name, 1446 + XT_ERROR_TARGET) == 0) 1447 + ++newinfo->stacksize; 1437 1448 } 1438 1449 if (ret) { 1439 1450 /*
+10 -18
net/ipv4/netfilter/ip_tables.c
··· 443 443 } 444 444 445 445 /* Figures out from what hook each rule can be called: returns 0 if 446 - * there are loops. Puts hook bitmask in comefrom. 447 - * 448 - * Keeps track of largest call depth seen and stores it in newinfo->stacksize. 449 - */ 446 + there are loops. Puts hook bitmask in comefrom. */ 450 447 static int 451 - mark_source_chains(struct xt_table_info *newinfo, 448 + mark_source_chains(const struct xt_table_info *newinfo, 452 449 unsigned int valid_hooks, void *entry0) 453 450 { 454 - unsigned int calldepth, max_calldepth = 0; 455 451 unsigned int hook; 456 452 457 453 /* No recursion; use packet counter to save back ptrs (reset ··· 461 465 462 466 /* Set initial back pointer. */ 463 467 e->counters.pcnt = pos; 464 - calldepth = 0; 465 468 466 469 for (;;) { 467 470 const struct xt_standard_target *t ··· 522 527 (entry0 + pos + size); 523 528 e->counters.pcnt = pos; 524 529 pos += size; 525 - WARN_ON_ONCE(calldepth == 0); 526 - if (calldepth > 0) 527 - --calldepth; 528 530 } else { 529 531 int newpos = t->verdict; 530 532 ··· 535 543 newpos); 536 544 return 0; 537 545 } 538 - if (entry0 + newpos != ipt_next_entry(e) && 539 - !(e->ip.flags & IPT_F_GOTO) && 540 - ++calldepth > max_calldepth) 541 - max_calldepth = calldepth; 542 - 543 546 /* This a jump; chase it. */ 544 - duprintf("Jump rule %u -> %u, calldepth %d\n", 545 - pos, newpos, calldepth); 547 + duprintf("Jump rule %u -> %u\n", 548 + pos, newpos); 546 549 } else { 547 550 /* ... this is a fallthru */ 548 551 newpos = pos + e->next_offset; ··· 551 564 next: 552 565 duprintf("Finished chain %u\n", hook); 553 566 } 554 - newinfo->stacksize = max_calldepth; 555 567 return 1; 556 568 } 557 569 ··· 830 844 if (ret != 0) 831 845 return ret; 832 846 ++i; 847 + if (strcmp(ipt_get_target(iter)->u.user.name, 848 + XT_ERROR_TARGET) == 0) 849 + ++newinfo->stacksize; 833 850 } 834 851 835 852 if (i != repl->num_entries) { ··· 1748 1759 if (ret != 0) 1749 1760 break; 1750 1761 ++i; 1762 + if (strcmp(ipt_get_target(iter1)->u.user.name, 1763 + XT_ERROR_TARGET) == 0) 1764 + ++newinfo->stacksize; 1751 1765 } 1752 1766 if (ret) { 1753 1767 /*
+8 -15
net/ipv6/netfilter/ip6_tables.c
··· 455 455 } 456 456 457 457 /* Figures out from what hook each rule can be called: returns 0 if 458 - * there are loops. Puts hook bitmask in comefrom. 459 - * 460 - * Keeps track of largest call depth seen and stores it in newinfo->stacksize. 461 - */ 458 + there are loops. Puts hook bitmask in comefrom. */ 462 459 static int 463 - mark_source_chains(struct xt_table_info *newinfo, 460 + mark_source_chains(const struct xt_table_info *newinfo, 464 461 unsigned int valid_hooks, void *entry0) 465 462 { 466 - unsigned int calldepth, max_calldepth = 0; 467 463 unsigned int hook; 468 464 469 465 /* No recursion; use packet counter to save back ptrs (reset ··· 473 477 474 478 /* Set initial back pointer. */ 475 479 e->counters.pcnt = pos; 476 - calldepth = 0; 477 480 478 481 for (;;) { 479 482 const struct xt_standard_target *t ··· 534 539 (entry0 + pos + size); 535 540 e->counters.pcnt = pos; 536 541 pos += size; 537 - if (calldepth > 0) 538 - --calldepth; 539 542 } else { 540 543 int newpos = t->verdict; 541 544 ··· 547 554 newpos); 548 555 return 0; 549 556 } 550 - if (entry0 + newpos != ip6t_next_entry(e) && 551 - !(e->ipv6.flags & IP6T_F_GOTO) && 552 - ++calldepth > max_calldepth) 553 - max_calldepth = calldepth; 554 - 555 557 /* This a jump; chase it. */ 556 558 duprintf("Jump rule %u -> %u\n", 557 559 pos, newpos); ··· 563 575 next: 564 576 duprintf("Finished chain %u\n", hook); 565 577 } 566 - newinfo->stacksize = max_calldepth; 567 578 return 1; 568 579 } 569 580 ··· 842 855 if (ret != 0) 843 856 return ret; 844 857 ++i; 858 + if (strcmp(ip6t_get_target(iter)->u.user.name, 859 + XT_ERROR_TARGET) == 0) 860 + ++newinfo->stacksize; 845 861 } 846 862 847 863 if (i != repl->num_entries) { ··· 1757 1767 if (ret != 0) 1758 1768 break; 1759 1769 ++i; 1770 + if (strcmp(ip6t_get_target(iter1)->u.user.name, 1771 + XT_ERROR_TARGET) == 0) 1772 + ++newinfo->stacksize; 1760 1773 } 1761 1774 if (ret) { 1762 1775 /*