aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-11-30 22:25:21 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:56 -0500
commit14197d5447afc41fce6b11a91592278cad1a09eb (patch)
tree909424a8134221f4a052da21950fc526ef37324c /net/bridge
parent98a0824a0f33d051f31ca8ff59e289755b244ede (diff)
[EBTABLES]: Prevent wraparounds in checks for entry components' sizes.
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.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 46ab9b759269..136ed7d4bd73 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -338,10 +338,11 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
338 const char *name, unsigned int hookmask, unsigned int *cnt) 338 const char *name, unsigned int hookmask, unsigned int *cnt)
339{ 339{
340 struct ebt_match *match; 340 struct ebt_match *match;
341 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
341 int ret; 342 int ret;
342 343
343 if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) > 344 if (left < sizeof(struct ebt_entry_match) ||
344 ((char *)e) + e->watchers_offset) 345 left - sizeof(struct ebt_entry_match) < m->match_size)
345 return -EINVAL; 346 return -EINVAL;
346 match = find_match_lock(m->u.name, &ret, &ebt_mutex); 347 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
347 if (!match) 348 if (!match)
@@ -367,10 +368,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
367 const char *name, unsigned int hookmask, unsigned int *cnt) 368 const char *name, unsigned int hookmask, unsigned int *cnt)
368{ 369{
369 struct ebt_watcher *watcher; 370 struct ebt_watcher *watcher;
371 size_t left = ((char *)e + e->target_offset) - (char *)w;
370 int ret; 372 int ret;
371 373
372 if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) > 374 if (left < sizeof(struct ebt_entry_watcher) ||
373 ((char *)e) + e->target_offset) 375 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
374 return -EINVAL; 376 return -EINVAL;
375 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex); 377 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
376 if (!watcher) 378 if (!watcher)
@@ -573,6 +575,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
573 struct ebt_entry_target *t; 575 struct ebt_entry_target *t;
574 struct ebt_target *target; 576 struct ebt_target *target;
575 unsigned int i, j, hook = 0, hookmask = 0; 577 unsigned int i, j, hook = 0, hookmask = 0;
578 size_t gap = e->next_offset - e->target_offset;
576 int ret; 579 int ret;
577 580
578 /* don't mess with the struct ebt_entries */ 581 /* don't mess with the struct ebt_entries */
@@ -634,8 +637,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
634 637
635 t->u.target = target; 638 t->u.target = target;
636 if (t->u.target == &ebt_standard_target) { 639 if (t->u.target == &ebt_standard_target) {
637 if (e->target_offset + sizeof(struct ebt_standard_target) > 640 if (gap < sizeof(struct ebt_standard_target)) {
638 e->next_offset) {
639 BUGPRINT("Standard target size too big\n"); 641 BUGPRINT("Standard target size too big\n");
640 ret = -EFAULT; 642 ret = -EFAULT;
641 goto cleanup_watchers; 643 goto cleanup_watchers;
@@ -646,8 +648,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
646 ret = -EFAULT; 648 ret = -EFAULT;
647 goto cleanup_watchers; 649 goto cleanup_watchers;
648 } 650 }
649 } else if ((e->target_offset + t->target_size + 651 } else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
650 sizeof(struct ebt_entry_target) > e->next_offset) ||
651 (t->u.target->check && 652 (t->u.target->check &&
652 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){ 653 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
653 module_put(t->u.target->me); 654 module_put(t->u.target->me);