aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)