[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)
|
const char *name, unsigned int hookmask, unsigned int *cnt)
|
||||||
{
|
{
|
||||||
struct ebt_match *match;
|
struct ebt_match *match;
|
||||||
|
size_t left = ((char *)e + e->watchers_offset) - (char *)m;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) >
|
if (left < sizeof(struct ebt_entry_match) ||
|
||||||
((char *)e) + e->watchers_offset)
|
left - sizeof(struct ebt_entry_match) < m->match_size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
match = find_match_lock(m->u.name, &ret, &ebt_mutex);
|
match = find_match_lock(m->u.name, &ret, &ebt_mutex);
|
||||||
if (!match)
|
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)
|
const char *name, unsigned int hookmask, unsigned int *cnt)
|
||||||
{
|
{
|
||||||
struct ebt_watcher *watcher;
|
struct ebt_watcher *watcher;
|
||||||
|
size_t left = ((char *)e + e->target_offset) - (char *)w;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) >
|
if (left < sizeof(struct ebt_entry_watcher) ||
|
||||||
((char *)e) + e->target_offset)
|
left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
|
watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
|
||||||
if (!watcher)
|
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_entry_target *t;
|
||||||
struct ebt_target *target;
|
struct ebt_target *target;
|
||||||
unsigned int i, j, hook = 0, hookmask = 0;
|
unsigned int i, j, hook = 0, hookmask = 0;
|
||||||
|
size_t gap = e->next_offset - e->target_offset;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* don't mess with the struct ebt_entries */
|
/* 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;
|
t->u.target = target;
|
||||||
if (t->u.target == &ebt_standard_target) {
|
if (t->u.target == &ebt_standard_target) {
|
||||||
if (e->target_offset + sizeof(struct ebt_standard_target) >
|
if (gap < sizeof(struct ebt_standard_target)) {
|
||||||
e->next_offset) {
|
|
||||||
BUGPRINT("Standard target size too big\n");
|
BUGPRINT("Standard target size too big\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto cleanup_watchers;
|
goto cleanup_watchers;
|
||||||
|
@ -646,8 +648,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto cleanup_watchers;
|
goto cleanup_watchers;
|
||||||
}
|
}
|
||||||
} else if ((e->target_offset + t->target_size +
|
} else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
|
||||||
sizeof(struct ebt_entry_target) > e->next_offset) ||
|
|
||||||
(t->u.target->check &&
|
(t->u.target->check &&
|
||||||
t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
|
t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
|
||||||
module_put(t->u.target->me);
|
module_put(t->u.target->me);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче