diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2006-11-30 22:22:42 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:31:53 -0500 |
commit | bb2ef25c2c62444b8fdb0346a23658a419803df9 (patch) | |
tree | b16356c4da5e33704db570324380ddf44908ae44 /net/bridge | |
parent | b6332e6cf9c9198c0f3b0fe37c2c57514dafe1b8 (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>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 23 |
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 | |||
479 | Esmall: | ||
480 | BUGPRINT("entries_size too small\n"); | ||
481 | return -EINVAL; | ||
473 | } | 482 | } |
474 | 483 | ||
475 | struct ebt_cl_stack | 484 | struct ebt_cl_stack |