Commit 70fe9af4 authored by Al Viro's avatar Al Viro Committed by David S. Miller

[EBTABLES]: Pull the loop doing __ebt_verify_pointers() into a separate function.

It's easier to expand the iterator here *and* we'll be able to move all
uses of ebt_replace from translate_table() into this one.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 22b440bf
...@@ -393,48 +393,54 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, ...@@ -393,48 +393,54 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
return 0; return 0;
} }
static inline int static int ebt_verify_pointers(struct ebt_replace *repl,
__ebt_verify_pointers(struct ebt_entry *e, struct ebt_table_info *newinfo)
struct ebt_table_info *newinfo, char *base, char *limit,
struct ebt_entries **hook_entries,
unsigned int valid_hooks)
{ {
unsigned int offset = (char *)e - newinfo->entries; unsigned int limit = repl->entries_size;
size_t left = (limit - base) - offset; unsigned int valid_hooks = repl->valid_hooks;
unsigned int offset = 0;
int i; int i;
if (left < sizeof(unsigned int)) while (offset < limit) {
goto Esmall; size_t left = limit - offset;
struct ebt_entry *e = (void *)newinfo->entries + offset;
for (i = 0; i < NF_BR_NUMHOOKS; i++) { if (left < sizeof(unsigned int))
if ((valid_hooks & (1 << i)) == 0)
continue;
if ((char *)hook_entries[i] == base + offset)
break; break;
}
if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { for (i = 0; i < NF_BR_NUMHOOKS; i++) {
if (e->bitmask != 0) { if ((valid_hooks & (1 << i)) == 0)
/* we make userspace set this right, continue;
so there is no misunderstanding */ if ((char *)repl->hook_entry[i] == repl->entries + offset)
BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " break;
"in distinguisher\n");
return -EINVAL;
} }
if (left < sizeof(struct ebt_entries))
goto Esmall; if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
if (i != NF_BR_NUMHOOKS) if (e->bitmask != 0) {
newinfo->hook_entry[i] = (struct ebt_entries *)e; /* we make userspace set this right,
return 0; so there is no misunderstanding */
BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
"in distinguisher\n");
return -EINVAL;
}
if (i != NF_BR_NUMHOOKS)
newinfo->hook_entry[i] = (struct ebt_entries *)e;
if (left < sizeof(struct ebt_entries))
break;
offset += sizeof(struct ebt_entries);
} else {
if (left < sizeof(struct ebt_entry))
break;
if (left < e->next_offset)
break;
offset += e->next_offset;
}
}
if (offset != limit) {
BUGPRINT("entries_size too small\n");
return -EINVAL;
} }
if (left < sizeof(struct ebt_entry))
goto Esmall;
if (left < e->next_offset)
goto Esmall;
return 0; return 0;
Esmall:
BUGPRINT("entries_size too small\n");
return -EINVAL;
} }
/* /*
...@@ -795,9 +801,7 @@ static int translate_table(struct ebt_replace *repl, ...@@ -795,9 +801,7 @@ static int translate_table(struct ebt_replace *repl,
newinfo->entries_size = repl->entries_size; newinfo->entries_size = repl->entries_size;
newinfo->nentries = repl->nentries; newinfo->nentries = repl->nentries;
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, ret = ebt_verify_pointers(repl, newinfo);
__ebt_verify_pointers, newinfo, repl->entries,
repl->entries + repl->entries_size, repl->hook_entry, repl->valid_hooks);
if (ret != 0) if (ret != 0)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment