Commit c2fcc885 authored by Florian Westphal's avatar Florian Westphal Committed by Ben Hutchings

netfilter: arp_tables: simplify translate_compat_table args

commit 8dddd327 upstream.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
[bwh: Backported to 3.6: adjust context]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent f20f892e
...@@ -1188,6 +1188,18 @@ static int do_add_counters(struct net *net, const void __user *user, ...@@ -1188,6 +1188,18 @@ static int do_add_counters(struct net *net, const void __user *user,
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
struct compat_arpt_replace {
char name[XT_TABLE_MAXNAMELEN];
u32 valid_hooks;
u32 num_entries;
u32 size;
u32 hook_entry[NF_ARP_NUMHOOKS];
u32 underflow[NF_ARP_NUMHOOKS];
u32 num_counters;
compat_uptr_t counters;
struct compat_arpt_entry entries[0];
};
static inline void compat_release_entry(struct compat_arpt_entry *e) static inline void compat_release_entry(struct compat_arpt_entry *e)
{ {
struct xt_entry_target *t; struct xt_entry_target *t;
...@@ -1203,8 +1215,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, ...@@ -1203,8 +1215,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
const unsigned char *base, const unsigned char *base,
const unsigned char *limit, const unsigned char *limit,
const unsigned int *hook_entries, const unsigned int *hook_entries,
const unsigned int *underflows, const unsigned int *underflows)
const char *name)
{ {
struct xt_entry_target *t; struct xt_entry_target *t;
struct xt_target *target; struct xt_target *target;
...@@ -1275,7 +1286,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, ...@@ -1275,7 +1286,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
static int static int
compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
unsigned int *size, const char *name, unsigned int *size,
struct xt_table_info *newinfo, unsigned char *base) struct xt_table_info *newinfo, unsigned char *base)
{ {
struct xt_entry_target *t; struct xt_entry_target *t;
...@@ -1308,14 +1319,9 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, ...@@ -1308,14 +1319,9 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
return ret; return ret;
} }
static int translate_compat_table(const char *name, static int translate_compat_table(struct xt_table_info **pinfo,
unsigned int valid_hooks,
struct xt_table_info **pinfo,
void **pentry0, void **pentry0,
unsigned int total_size, const struct compat_arpt_replace *compatr)
unsigned int number,
unsigned int *hook_entries,
unsigned int *underflows)
{ {
unsigned int i, j; unsigned int i, j;
struct xt_table_info *newinfo, *info; struct xt_table_info *newinfo, *info;
...@@ -1327,8 +1333,8 @@ static int translate_compat_table(const char *name, ...@@ -1327,8 +1333,8 @@ static int translate_compat_table(const char *name,
info = *pinfo; info = *pinfo;
entry0 = *pentry0; entry0 = *pentry0;
size = total_size; size = compatr->size;
info->number = number; info->number = compatr->num_entries;
/* Init all hooks to impossible value. */ /* Init all hooks to impossible value. */
for (i = 0; i < NF_ARP_NUMHOOKS; i++) { for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
...@@ -1339,40 +1345,39 @@ static int translate_compat_table(const char *name, ...@@ -1339,40 +1345,39 @@ static int translate_compat_table(const char *name,
duprintf("translate_compat_table: size %u\n", info->size); duprintf("translate_compat_table: size %u\n", info->size);
j = 0; j = 0;
xt_compat_lock(NFPROTO_ARP); xt_compat_lock(NFPROTO_ARP);
xt_compat_init_offsets(NFPROTO_ARP, number); xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries);
/* Walk through entries, checking offsets. */ /* Walk through entries, checking offsets. */
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, compatr->size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size, ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0, entry0,
entry0 + total_size, entry0 + compatr->size,
hook_entries, compatr->hook_entry,
underflows, compatr->underflow);
name);
if (ret != 0) if (ret != 0)
goto out_unlock; goto out_unlock;
++j; ++j;
} }
ret = -EINVAL; ret = -EINVAL;
if (j != number) { if (j != compatr->num_entries) {
duprintf("translate_compat_table: %u not %u entries\n", duprintf("translate_compat_table: %u not %u entries\n",
j, number); j, compatr->num_entries);
goto out_unlock; goto out_unlock;
} }
/* Check hooks all assigned */ /* Check hooks all assigned */
for (i = 0; i < NF_ARP_NUMHOOKS; i++) { for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
/* Only hooks which are valid */ /* Only hooks which are valid */
if (!(valid_hooks & (1 << i))) if (!(compatr->valid_hooks & (1 << i)))
continue; continue;
if (info->hook_entry[i] == 0xFFFFFFFF) { if (info->hook_entry[i] == 0xFFFFFFFF) {
duprintf("Invalid hook entry %u %u\n", duprintf("Invalid hook entry %u %u\n",
i, hook_entries[i]); i, info->hook_entry[i]);
goto out_unlock; goto out_unlock;
} }
if (info->underflow[i] == 0xFFFFFFFF) { if (info->underflow[i] == 0xFFFFFFFF) {
duprintf("Invalid underflow %u %u\n", duprintf("Invalid underflow %u %u\n",
i, underflows[i]); i, info->underflow[i]);
goto out_unlock; goto out_unlock;
} }
} }
...@@ -1382,17 +1387,17 @@ static int translate_compat_table(const char *name, ...@@ -1382,17 +1387,17 @@ static int translate_compat_table(const char *name,
if (!newinfo) if (!newinfo)
goto out_unlock; goto out_unlock;
newinfo->number = number; newinfo->number = compatr->num_entries;
for (i = 0; i < NF_ARP_NUMHOOKS; i++) { for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
newinfo->hook_entry[i] = info->hook_entry[i]; newinfo->hook_entry[i] = info->hook_entry[i];
newinfo->underflow[i] = info->underflow[i]; newinfo->underflow[i] = info->underflow[i];
} }
entry1 = newinfo->entries[raw_smp_processor_id()]; entry1 = newinfo->entries[raw_smp_processor_id()];
pos = entry1; pos = entry1;
size = total_size; size = compatr->size;
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, compatr->size) {
ret = compat_copy_entry_from_user(iter0, &pos, &size, ret = compat_copy_entry_from_user(iter0, &pos, &size,
name, newinfo, entry1); newinfo, entry1);
if (ret != 0) if (ret != 0)
break; break;
} }
...@@ -1402,12 +1407,12 @@ static int translate_compat_table(const char *name, ...@@ -1402,12 +1407,12 @@ static int translate_compat_table(const char *name,
goto free_newinfo; goto free_newinfo;
ret = -ELOOP; ret = -ELOOP;
if (!mark_source_chains(newinfo, valid_hooks, entry1)) if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
goto free_newinfo; goto free_newinfo;
i = 0; i = 0;
xt_entry_foreach(iter1, entry1, newinfo->size) { xt_entry_foreach(iter1, entry1, newinfo->size) {
ret = check_target(iter1, name); ret = check_target(iter1, compatr->name);
if (ret != 0) if (ret != 0)
break; break;
++i; ++i;
...@@ -1452,7 +1457,7 @@ static int translate_compat_table(const char *name, ...@@ -1452,7 +1457,7 @@ static int translate_compat_table(const char *name,
free_newinfo: free_newinfo:
xt_free_table_info(newinfo); xt_free_table_info(newinfo);
out: out:
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, compatr->size) {
if (j-- == 0) if (j-- == 0)
break; break;
compat_release_entry(iter0); compat_release_entry(iter0);
...@@ -1464,18 +1469,6 @@ static int translate_compat_table(const char *name, ...@@ -1464,18 +1469,6 @@ static int translate_compat_table(const char *name,
goto out; goto out;
} }
struct compat_arpt_replace {
char name[XT_TABLE_MAXNAMELEN];
u32 valid_hooks;
u32 num_entries;
u32 size;
u32 hook_entry[NF_ARP_NUMHOOKS];
u32 underflow[NF_ARP_NUMHOOKS];
u32 num_counters;
compat_uptr_t counters;
struct compat_arpt_entry entries[0];
};
static int compat_do_replace(struct net *net, void __user *user, static int compat_do_replace(struct net *net, void __user *user,
unsigned int len) unsigned int len)
{ {
...@@ -1506,10 +1499,7 @@ static int compat_do_replace(struct net *net, void __user *user, ...@@ -1506,10 +1499,7 @@ static int compat_do_replace(struct net *net, void __user *user,
goto free_newinfo; goto free_newinfo;
} }
ret = translate_compat_table(tmp.name, tmp.valid_hooks, ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
&newinfo, &loc_cpu_entry, tmp.size,
tmp.num_entries, tmp.hook_entry,
tmp.underflow);
if (ret != 0) if (ret != 0)
goto free_newinfo; goto free_newinfo;
......
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