[EBTABLES]: Split ebt_check_entry_size_and_hooks

Split ebt_check_entry_size_and_hooks() in two parts - one that does
sanity checks on pointers (basically, checks that we can safely
use iterator from now on) and the rest of it (looking into details
of entry).

The loop applying ebt_check_entry_size_and_hooks() is split in two.

Populating newinfo->hook_entry[] is done in the first part.

Unused arguments killed.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Al Viro 2006-11-30 19:25:51 -08:00 коммит произвёл David S. Miller
Родитель 14197d5447
Коммит 22b440bf9e
1 изменённых файлов: 49 добавлений и 24 удалений

Просмотреть файл

@ -393,15 +393,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
return 0;
}
/*
* this one is very careful, as it is the first function
* to parse the userspace data
*/
static inline int
ebt_check_entry_size_and_hooks(struct ebt_entry *e,
__ebt_verify_pointers(struct ebt_entry *e,
struct ebt_table_info *newinfo, char *base, char *limit,
struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
struct ebt_entries **hook_entries,
unsigned int valid_hooks)
{
unsigned int offset = (char *)e - newinfo->entries;
size_t left = (limit - base) - offset;
@ -416,8 +412,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
if ((char *)hook_entries[i] == base + offset)
break;
}
/* beginning of a new chain
if i == NF_BR_NUMHOOKS it must be a user defined chain */
if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
if (e->bitmask != 0) {
/* we make userspace set this right,
@ -426,6 +420,45 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
"in distinguisher\n");
return -EINVAL;
}
if (left < sizeof(struct ebt_entries))
goto Esmall;
if (i != NF_BR_NUMHOOKS)
newinfo->hook_entry[i] = (struct ebt_entries *)e;
return 0;
}
if (left < sizeof(struct ebt_entry))
goto Esmall;
if (left < e->next_offset)
goto Esmall;
return 0;
Esmall:
BUGPRINT("entries_size too small\n");
return -EINVAL;
}
/*
* this one is very careful, as it is the first function
* to parse the userspace data
*/
static inline int
ebt_check_entry_size_and_hooks(struct ebt_entry *e,
struct ebt_table_info *newinfo, char *base,
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;
int i;
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
if ((valid_hooks & (1 << i)) == 0)
continue;
if ((char *)hook_entries[i] == base + offset)
break;
}
/* beginning of a new chain
if i == NF_BR_NUMHOOKS it must be a user defined chain */
if (i != NF_BR_NUMHOOKS || !e->bitmask) {
/* this checks if the previous chain has as many entries
as it said it has */
if (*n != *cnt) {
@ -433,9 +466,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
"in the chain\n");
return -EINVAL;
}
/* before we look at the struct, be sure it is not too big */
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 */
@ -447,8 +477,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
}
if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
(*udc_cnt)++;
else
newinfo->hook_entry[i] = (struct ebt_entries *)e;
if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
BUGPRINT("counter_offset != totalcnt");
return -EINVAL;
@ -458,8 +486,6 @@ 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) {
@ -471,16 +497,9 @@ 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
@ -776,6 +795,12 @@ static int translate_table(struct ebt_replace *repl,
newinfo->entries_size = repl->entries_size;
newinfo->nentries = repl->nentries;
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
__ebt_verify_pointers, newinfo, repl->entries,
repl->entries + repl->entries_size, repl->hook_entry, repl->valid_hooks);
if (ret != 0)
return ret;
/* do some early checkings and initialize some things */
i = 0; /* holds the expected nr. of entries for the chain */
j = 0; /* holds the up to now counted entries for the chain */
@ -784,7 +809,7 @@ static int translate_table(struct ebt_replace *repl,
udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_check_entry_size_and_hooks, newinfo, repl->entries,
repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
repl->hook_entry, &i, &j, &k,
&udc_cnt, repl->valid_hooks);
if (ret != 0)