[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>
This commit is contained in:
Родитель
98a0824a0f
Коммит
14197d5447
|
@ -338,10 +338,11 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
|
|||
const char *name, unsigned int hookmask, unsigned int *cnt)
|
||||
{
|
||||
struct ebt_match *match;
|
||||
size_t left = ((char *)e + e->watchers_offset) - (char *)m;
|
||||
int ret;
|
||||
|
||||
if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) >
|
||||
((char *)e) + e->watchers_offset)
|
||||
if (left < sizeof(struct ebt_entry_match) ||
|
||||
left - sizeof(struct ebt_entry_match) < m->match_size)
|
||||
return -EINVAL;
|
||||
match = find_match_lock(m->u.name, &ret, &ebt_mutex);
|
||||
if (!match)
|
||||
|
@ -367,10 +368,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
|
|||
const char *name, unsigned int hookmask, unsigned int *cnt)
|
||||
{
|
||||
struct ebt_watcher *watcher;
|
||||
size_t left = ((char *)e + e->target_offset) - (char *)w;
|
||||
int ret;
|
||||
|
||||
if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) >
|
||||
((char *)e) + e->target_offset)
|
||||
if (left < sizeof(struct ebt_entry_watcher) ||
|
||||
left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
|
||||
return -EINVAL;
|
||||
watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
|
||||
if (!watcher)
|
||||
|
@ -573,6 +575,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
|||
struct ebt_entry_target *t;
|
||||
struct ebt_target *target;
|
||||
unsigned int i, j, hook = 0, hookmask = 0;
|
||||
size_t gap = e->next_offset - e->target_offset;
|
||||
int ret;
|
||||
|
||||
/* don't mess with the struct ebt_entries */
|
||||
|
@ -634,8 +637,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
|||
|
||||
t->u.target = target;
|
||||
if (t->u.target == &ebt_standard_target) {
|
||||
if (e->target_offset + sizeof(struct ebt_standard_target) >
|
||||
e->next_offset) {
|
||||
if (gap < sizeof(struct ebt_standard_target)) {
|
||||
BUGPRINT("Standard target size too big\n");
|
||||
ret = -EFAULT;
|
||||
goto cleanup_watchers;
|
||||
|
@ -646,8 +648,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
|||
ret = -EFAULT;
|
||||
goto cleanup_watchers;
|
||||
}
|
||||
} else if ((e->target_offset + t->target_size +
|
||||
sizeof(struct ebt_entry_target) > e->next_offset) ||
|
||||
} else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
|
||||
(t->u.target->check &&
|
||||
t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
|
||||
module_put(t->u.target->me);
|
||||
|
|
Загрузка…
Ссылка в новой задаче