aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-11-30 22:22:42 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:53 -0500
commitbb2ef25c2c62444b8fdb0346a23658a419803df9 (patch)
treeb16356c4da5e33704db570324380ddf44908ae44
parentb6332e6cf9c9198c0f3b0fe37c2c57514dafe1b8 (diff)
[EBTABLES]: Fix wraparounds in ebt_entries verification.
We need to verify that a) we are not too close to the end of buffer to dereference b) next entry we'll be checking won't be _before_ our While we are at it, don't subtract unrelated pointers... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/bridge/netfilter/ebtables.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 9f85666f29f7..0dcebf20d6ce 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -401,13 +401,17 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
401 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt, 401 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
402 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks) 402 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
403{ 403{
404 unsigned int offset = (char *)e - newinfo->entries;
405 size_t left = (limit - base) - offset;
404 int i; 406 int i;
405 407
408 if (left < sizeof(unsigned int))
409 goto Esmall;
410
406 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 411 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
407 if ((valid_hooks & (1 << i)) == 0) 412 if ((valid_hooks & (1 << i)) == 0)
408 continue; 413 continue;
409 if ( (char *)hook_entries[i] - base == 414 if ((char *)hook_entries[i] == base + offset)
410 (char *)e - newinfo->entries)
411 break; 415 break;
412 } 416 }
413 /* beginning of a new chain 417 /* beginning of a new chain
@@ -428,11 +432,8 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
428 return -EINVAL; 432 return -EINVAL;
429 } 433 }
430 /* before we look at the struct, be sure it is not too big */ 434 /* before we look at the struct, be sure it is not too big */
431 if ((char *)hook_entries[i] + sizeof(struct ebt_entries) 435 if (left < sizeof(struct ebt_entries))
432 > limit) { 436 goto Esmall;
433 BUGPRINT("entries_size too small\n");
434 return -EINVAL;
435 }
436 if (((struct ebt_entries *)e)->policy != EBT_DROP && 437 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
437 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) { 438 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
438 /* only RETURN from udc */ 439 /* only RETURN from udc */
@@ -455,6 +456,8 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
455 return 0; 456 return 0;
456 } 457 }
457 /* a plain old entry, heh */ 458 /* a plain old entry, heh */
459 if (left < sizeof(struct ebt_entry))
460 goto Esmall;
458 if (sizeof(struct ebt_entry) > e->watchers_offset || 461 if (sizeof(struct ebt_entry) > e->watchers_offset ||
459 e->watchers_offset > e->target_offset || 462 e->watchers_offset > e->target_offset ||
460 e->target_offset >= e->next_offset) { 463 e->target_offset >= e->next_offset) {
@@ -466,10 +469,16 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
466 BUGPRINT("target size too small\n"); 469 BUGPRINT("target size too small\n");
467 return -EINVAL; 470 return -EINVAL;
468 } 471 }
472 if (left < e->next_offset)
473 goto Esmall;
469 474
470 (*cnt)++; 475 (*cnt)++;
471 (*totalcnt)++; 476 (*totalcnt)++;
472 return 0; 477 return 0;
478
479Esmall:
480 BUGPRINT("entries_size too small\n");
481 return -EINVAL;
473} 482}
474 483
475struct ebt_cl_stack 484struct ebt_cl_stack