aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-11-30 22:25:51 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:56 -0500
commit22b440bf9e717226d0fbaf4f29357cbdd5279de5 (patch)
tree60ed5c4e78c0e539745ba79e75719de1cd6af59c /net/bridge
parent14197d5447afc41fce6b11a91592278cad1a09eb (diff)
[EBTABLES]: Split ebt_check_entry_size_and_hooks
Split ebt_check_entry_size_and_hooks() in two parts - one that does sanity checks on pointers (basically, checks that we can safely use iterator from now on) and the rest of it (looking into details of entry). The loop applying ebt_check_entry_size_and_hooks() is split in two. Populating newinfo->hook_entry[] is done in the first part. Unused arguments killed. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/netfilter/ebtables.c73
1 files changed, 49 insertions, 24 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 136ed7d4bd73..e79c0fbd9e89 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -393,15 +393,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
393 return 0; 393 return 0;
394} 394}
395 395
396/*
397 * this one is very careful, as it is the first function
398 * to parse the userspace data
399 */
400static inline int 396static inline int
401ebt_check_entry_size_and_hooks(struct ebt_entry *e, 397__ebt_verify_pointers(struct ebt_entry *e,
402 struct ebt_table_info *newinfo, char *base, char *limit, 398 struct ebt_table_info *newinfo, char *base, char *limit,
403 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt, 399 struct ebt_entries **hook_entries,
404 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks) 400 unsigned int valid_hooks)
405{ 401{
406 unsigned int offset = (char *)e - newinfo->entries; 402 unsigned int offset = (char *)e - newinfo->entries;
407 size_t left = (limit - base) - offset; 403 size_t left = (limit - base) - offset;
@@ -416,8 +412,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
416 if ((char *)hook_entries[i] == base + offset) 412 if ((char *)hook_entries[i] == base + offset)
417 break; 413 break;
418 } 414 }
419 /* beginning of a new chain
420 if i == NF_BR_NUMHOOKS it must be a user defined chain */
421 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { 415 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
422 if (e->bitmask != 0) { 416 if (e->bitmask != 0) {
423 /* we make userspace set this right, 417 /* we make userspace set this right,
@@ -426,6 +420,45 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
426 "in distinguisher\n"); 420 "in distinguisher\n");
427 return -EINVAL; 421 return -EINVAL;
428 } 422 }
423 if (left < sizeof(struct ebt_entries))
424 goto Esmall;
425 if (i != NF_BR_NUMHOOKS)
426 newinfo->hook_entry[i] = (struct ebt_entries *)e;
427 return 0;
428 }
429 if (left < sizeof(struct ebt_entry))
430 goto Esmall;
431 if (left < e->next_offset)
432 goto Esmall;
433 return 0;
434
435Esmall:
436 BUGPRINT("entries_size too small\n");
437 return -EINVAL;
438}
439
440/*
441 * this one is very careful, as it is the first function
442 * to parse the userspace data
443 */
444static inline int
445ebt_check_entry_size_and_hooks(struct ebt_entry *e,
446 struct ebt_table_info *newinfo, char *base,
447 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
448 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
449{
450 unsigned int offset = (char *)e - newinfo->entries;
451 int i;
452
453 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
454 if ((valid_hooks & (1 << i)) == 0)
455 continue;
456 if ((char *)hook_entries[i] == base + offset)
457 break;
458 }
459 /* beginning of a new chain
460 if i == NF_BR_NUMHOOKS it must be a user defined chain */
461 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
429 /* this checks if the previous chain has as many entries 462 /* this checks if the previous chain has as many entries
430 as it said it has */ 463 as it said it has */
431 if (*n != *cnt) { 464 if (*n != *cnt) {
@@ -433,9 +466,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
433 "in the chain\n"); 466 "in the chain\n");
434 return -EINVAL; 467 return -EINVAL;
435 } 468 }
436 /* before we look at the struct, be sure it is not too big */
437 if (left < sizeof(struct ebt_entries))
438 goto Esmall;
439 if (((struct ebt_entries *)e)->policy != EBT_DROP && 469 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
440 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) { 470 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
441 /* only RETURN from udc */ 471 /* only RETURN from udc */
@@ -447,8 +477,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
447 } 477 }
448 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */ 478 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
449 (*udc_cnt)++; 479 (*udc_cnt)++;
450 else
451 newinfo->hook_entry[i] = (struct ebt_entries *)e;
452 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) { 480 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
453 BUGPRINT("counter_offset != totalcnt"); 481 BUGPRINT("counter_offset != totalcnt");
454 return -EINVAL; 482 return -EINVAL;
@@ -458,8 +486,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
458 return 0; 486 return 0;
459 } 487 }
460 /* a plain old entry, heh */ 488 /* a plain old entry, heh */
461 if (left < sizeof(struct ebt_entry))
462 goto Esmall;
463 if (sizeof(struct ebt_entry) > e->watchers_offset || 489 if (sizeof(struct ebt_entry) > e->watchers_offset ||
464 e->watchers_offset > e->target_offset || 490 e->watchers_offset > e->target_offset ||
465 e->target_offset >= e->next_offset) { 491 e->target_offset >= e->next_offset) {
@@ -471,16 +497,9 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
471 BUGPRINT("target size too small\n"); 497 BUGPRINT("target size too small\n");
472 return -EINVAL; 498 return -EINVAL;
473 } 499 }
474 if (left < e->next_offset)
475 goto Esmall;
476
477 (*cnt)++; 500 (*cnt)++;
478 (*totalcnt)++; 501 (*totalcnt)++;
479 return 0; 502 return 0;
480
481Esmall:
482 BUGPRINT("entries_size too small\n");
483 return -EINVAL;
484} 503}
485 504
486struct ebt_cl_stack 505struct ebt_cl_stack
@@ -776,6 +795,12 @@ static int translate_table(struct ebt_replace *repl,
776 newinfo->entries_size = repl->entries_size; 795 newinfo->entries_size = repl->entries_size;
777 newinfo->nentries = repl->nentries; 796 newinfo->nentries = repl->nentries;
778 797
798 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
799 __ebt_verify_pointers, newinfo, repl->entries,
800 repl->entries + repl->entries_size, repl->hook_entry, repl->valid_hooks);
801 if (ret != 0)
802 return ret;
803
779 /* do some early checkings and initialize some things */ 804 /* do some early checkings and initialize some things */
780 i = 0; /* holds the expected nr. of entries for the chain */ 805 i = 0; /* holds the expected nr. of entries for the chain */
781 j = 0; /* holds the up to now counted entries for the chain */ 806 j = 0; /* holds the up to now counted entries for the chain */
@@ -784,7 +809,7 @@ static int translate_table(struct ebt_replace *repl,
784 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */ 809 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
785 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 810 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
786 ebt_check_entry_size_and_hooks, newinfo, repl->entries, 811 ebt_check_entry_size_and_hooks, newinfo, repl->entries,
787 repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k, 812 repl->hook_entry, &i, &j, &k,
788 &udc_cnt, repl->valid_hooks); 813 &udc_cnt, repl->valid_hooks);
789 814
790 if (ret != 0) 815 if (ret != 0)