summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-12-04 13:11:24 +0100
committerAdrian Bunk <bunk@stusta.de>2006-12-04 13:11:24 +0100
commitd559dd79b58829f1ebb7996698e6354600e79b14 (patch)
tree1e4f2088a0fbf6875006d618cbad1ad609e2f60d /net
parentb00b3fe3f00962fc9faa7d34c28f5a20074c728b (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> Signed-off-by: Adrian Bunk <bunk@stusta.de>
Diffstat (limited to '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 cbd4020cc84d..a3e23c3c4ae5 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -422,13 +422,17 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
{
+ unsigned int offset = (char *)e - newinfo->entries;
+ size_t left = (limit - base) - offset;
int i;
+ if (left < sizeof(unsigned int))
+ goto Esmall;
+
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
if ((valid_hooks & (1 << i)) == 0)
continue;
- if ( (char *)hook_entries[i] - base ==
- (char *)e - newinfo->entries)
+ if ((char *)hook_entries[i] == base + offset)
break;
}
/* beginning of a new chain
@@ -449,11 +453,8 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
return -EINVAL;
}
/* before we look at the struct, be sure it is not too big */
- if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
- > limit) {
- BUGPRINT("entries_size too small\n");
- return -EINVAL;
- }
+ if (left < sizeof(struct ebt_entries))
+ goto Esmall;
if (((struct ebt_entries *)e)->policy != EBT_DROP &&
((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
/* only RETURN from udc */
@@ -476,6 +477,8 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
return 0;
}
/* a plain old entry, heh */
+ if (left < sizeof(struct ebt_entry))
+ goto Esmall;
if (sizeof(struct ebt_entry) > e->watchers_offset ||
e->watchers_offset > e->target_offset ||
e->target_offset >= e->next_offset) {
@@ -487,10 +490,16 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
BUGPRINT("target size too small\n");
return -EINVAL;
}
+ if (left < e->next_offset)
+ goto Esmall;
(*cnt)++;
(*totalcnt)++;
return 0;
+
+Esmall:
+ BUGPRINT("entries_size too small\n");
+ return -EINVAL;
}
struct ebt_cl_stack