aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/netfilter/arp_tables.c')
-rw-r--r--net/ipv4/netfilter/arp_tables.c57
1 files changed, 31 insertions, 26 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 6e3e0e8b1ce3..4cfcc22f7430 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -367,23 +367,12 @@ static inline bool unconditional(const struct arpt_entry *e)
367 memcmp(&e->arp, &uncond, sizeof(uncond)) == 0; 367 memcmp(&e->arp, &uncond, sizeof(uncond)) == 0;
368} 368}
369 369
370static bool find_jump_target(const struct xt_table_info *t,
371 const struct arpt_entry *target)
372{
373 struct arpt_entry *iter;
374
375 xt_entry_foreach(iter, t->entries, t->size) {
376 if (iter == target)
377 return true;
378 }
379 return false;
380}
381
382/* Figures out from what hook each rule can be called: returns 0 if 370/* Figures out from what hook each rule can be called: returns 0 if
383 * there are loops. Puts hook bitmask in comefrom. 371 * there are loops. Puts hook bitmask in comefrom.
384 */ 372 */
385static int mark_source_chains(const struct xt_table_info *newinfo, 373static int mark_source_chains(const struct xt_table_info *newinfo,
386 unsigned int valid_hooks, void *entry0) 374 unsigned int valid_hooks, void *entry0,
375 unsigned int *offsets)
387{ 376{
388 unsigned int hook; 377 unsigned int hook;
389 378
@@ -472,10 +461,11 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
472 /* This a jump; chase it. */ 461 /* This a jump; chase it. */
473 duprintf("Jump rule %u -> %u\n", 462 duprintf("Jump rule %u -> %u\n",
474 pos, newpos); 463 pos, newpos);
464 if (!xt_find_jump_offset(offsets, newpos,
465 newinfo->number))
466 return 0;
475 e = (struct arpt_entry *) 467 e = (struct arpt_entry *)
476 (entry0 + newpos); 468 (entry0 + newpos);
477 if (!find_jump_target(newinfo, e))
478 return 0;
479 } else { 469 } else {
480 /* ... this is a fallthru */ 470 /* ... this is a fallthru */
481 newpos = pos + e->next_offset; 471 newpos = pos + e->next_offset;
@@ -521,11 +511,13 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
521{ 511{
522 struct xt_entry_target *t; 512 struct xt_entry_target *t;
523 struct xt_target *target; 513 struct xt_target *target;
514 unsigned long pcnt;
524 int ret; 515 int ret;
525 516
526 e->counters.pcnt = xt_percpu_counter_alloc(); 517 pcnt = xt_percpu_counter_alloc();
527 if (IS_ERR_VALUE(e->counters.pcnt)) 518 if (IS_ERR_VALUE(pcnt))
528 return -ENOMEM; 519 return -ENOMEM;
520 e->counters.pcnt = pcnt;
529 521
530 t = arpt_get_target(e); 522 t = arpt_get_target(e);
531 target = xt_request_find_target(NFPROTO_ARP, t->u.user.name, 523 target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,
@@ -642,6 +634,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
642 const struct arpt_replace *repl) 634 const struct arpt_replace *repl)
643{ 635{
644 struct arpt_entry *iter; 636 struct arpt_entry *iter;
637 unsigned int *offsets;
645 unsigned int i; 638 unsigned int i;
646 int ret = 0; 639 int ret = 0;
647 640
@@ -655,6 +648,9 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
655 } 648 }
656 649
657 duprintf("translate_table: size %u\n", newinfo->size); 650 duprintf("translate_table: size %u\n", newinfo->size);
651 offsets = xt_alloc_entry_offsets(newinfo->number);
652 if (!offsets)
653 return -ENOMEM;
658 i = 0; 654 i = 0;
659 655
660 /* Walk through entries, checking offsets. */ 656 /* Walk through entries, checking offsets. */
@@ -665,7 +661,9 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
665 repl->underflow, 661 repl->underflow,
666 repl->valid_hooks); 662 repl->valid_hooks);
667 if (ret != 0) 663 if (ret != 0)
668 break; 664 goto out_free;
665 if (i < repl->num_entries)
666 offsets[i] = (void *)iter - entry0;
669 ++i; 667 ++i;
670 if (strcmp(arpt_get_target(iter)->u.user.name, 668 if (strcmp(arpt_get_target(iter)->u.user.name,
671 XT_ERROR_TARGET) == 0) 669 XT_ERROR_TARGET) == 0)
@@ -673,12 +671,13 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
673 } 671 }
674 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); 672 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret);
675 if (ret != 0) 673 if (ret != 0)
676 return ret; 674 goto out_free;
677 675
676 ret = -EINVAL;
678 if (i != repl->num_entries) { 677 if (i != repl->num_entries) {
679 duprintf("translate_table: %u not %u entries\n", 678 duprintf("translate_table: %u not %u entries\n",
680 i, repl->num_entries); 679 i, repl->num_entries);
681 return -EINVAL; 680 goto out_free;
682 } 681 }
683 682
684 /* Check hooks all assigned */ 683 /* Check hooks all assigned */
@@ -689,17 +688,20 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
689 if (newinfo->hook_entry[i] == 0xFFFFFFFF) { 688 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
690 duprintf("Invalid hook entry %u %u\n", 689 duprintf("Invalid hook entry %u %u\n",
691 i, repl->hook_entry[i]); 690 i, repl->hook_entry[i]);
692 return -EINVAL; 691 goto out_free;
693 } 692 }
694 if (newinfo->underflow[i] == 0xFFFFFFFF) { 693 if (newinfo->underflow[i] == 0xFFFFFFFF) {
695 duprintf("Invalid underflow %u %u\n", 694 duprintf("Invalid underflow %u %u\n",
696 i, repl->underflow[i]); 695 i, repl->underflow[i]);
697 return -EINVAL; 696 goto out_free;
698 } 697 }
699 } 698 }
700 699
701 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) 700 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) {
702 return -ELOOP; 701 ret = -ELOOP;
702 goto out_free;
703 }
704 kvfree(offsets);
703 705
704 /* Finally, each sanity check must pass */ 706 /* Finally, each sanity check must pass */
705 i = 0; 707 i = 0;
@@ -720,6 +722,9 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
720 } 722 }
721 723
722 return ret; 724 return ret;
725 out_free:
726 kvfree(offsets);
727 return ret;
723} 728}
724 729
725static void get_counters(const struct xt_table_info *t, 730static void get_counters(const struct xt_table_info *t,
@@ -1336,8 +1341,8 @@ static int translate_compat_table(struct xt_table_info **pinfo,
1336 1341
1337 newinfo->number = compatr->num_entries; 1342 newinfo->number = compatr->num_entries;
1338 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 1343 for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
1339 newinfo->hook_entry[i] = info->hook_entry[i]; 1344 newinfo->hook_entry[i] = compatr->hook_entry[i];
1340 newinfo->underflow[i] = info->underflow[i]; 1345 newinfo->underflow[i] = compatr->underflow[i];
1341 } 1346 }
1342 entry1 = newinfo->entries; 1347 entry1 = newinfo->entries;
1343 pos = entry1; 1348 pos = entry1;