Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8dddd327 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: arp_tables: simplify translate_compat_table args

parent 329a0807
Loading
Loading
Loading
Loading
+36 −46
Original line number Diff line number Diff line
@@ -1214,6 +1214,18 @@ static int do_add_counters(struct net *net, const void __user *user,
}

#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)
{
	struct xt_entry_target *t;
@@ -1229,8 +1241,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
				  const unsigned char *base,
				  const unsigned char *limit,
				  const unsigned int *hook_entries,
				  const unsigned int *underflows,
				  const char *name)
				  const unsigned int *underflows)
{
	struct xt_entry_target *t;
	struct xt_target *target;
@@ -1301,7 +1312,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,

static int
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_entry_target *t;
@@ -1334,14 +1345,9 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
	return ret;
}

static int translate_compat_table(const char *name,
				  unsigned int valid_hooks,
				  struct xt_table_info **pinfo,
static int translate_compat_table(struct xt_table_info **pinfo,
				  void **pentry0,
				  unsigned int total_size,
				  unsigned int number,
				  unsigned int *hook_entries,
				  unsigned int *underflows)
				  const struct compat_arpt_replace *compatr)
{
	unsigned int i, j;
	struct xt_table_info *newinfo, *info;
@@ -1353,8 +1359,8 @@ static int translate_compat_table(const char *name,

	info = *pinfo;
	entry0 = *pentry0;
	size = total_size;
	info->number = number;
	size = compatr->size;
	info->number = compatr->num_entries;

	/* Init all hooks to impossible value. */
	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
@@ -1365,40 +1371,39 @@ static int translate_compat_table(const char *name,
	duprintf("translate_compat_table: size %u\n", info->size);
	j = 0;
	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. */
	xt_entry_foreach(iter0, entry0, total_size) {
	xt_entry_foreach(iter0, entry0, compatr->size) {
		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
							entry0,
							entry0 + total_size,
							hook_entries,
							underflows,
							name);
							entry0 + compatr->size,
							compatr->hook_entry,
							compatr->underflow);
		if (ret != 0)
			goto out_unlock;
		++j;
	}

	ret = -EINVAL;
	if (j != number) {
	if (j != compatr->num_entries) {
		duprintf("translate_compat_table: %u not %u entries\n",
			 j, number);
			 j, compatr->num_entries);
		goto out_unlock;
	}

	/* Check hooks all assigned */
	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
		/* Only hooks which are valid */
		if (!(valid_hooks & (1 << i)))
		if (!(compatr->valid_hooks & (1 << i)))
			continue;
		if (info->hook_entry[i] == 0xFFFFFFFF) {
			duprintf("Invalid hook entry %u %u\n",
				 i, hook_entries[i]);
				 i, info->hook_entry[i]);
			goto out_unlock;
		}
		if (info->underflow[i] == 0xFFFFFFFF) {
			duprintf("Invalid underflow %u %u\n",
				 i, underflows[i]);
				 i, info->underflow[i]);
			goto out_unlock;
		}
	}
@@ -1408,17 +1413,17 @@ static int translate_compat_table(const char *name,
	if (!newinfo)
		goto out_unlock;

	newinfo->number = number;
	newinfo->number = compatr->num_entries;
	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
		newinfo->hook_entry[i] = info->hook_entry[i];
		newinfo->underflow[i] = info->underflow[i];
	}
	entry1 = newinfo->entries;
	pos = entry1;
	size = total_size;
	xt_entry_foreach(iter0, entry0, total_size) {
	size = compatr->size;
	xt_entry_foreach(iter0, entry0, compatr->size) {
		ret = compat_copy_entry_from_user(iter0, &pos, &size,
						  name, newinfo, entry1);
						  newinfo, entry1);
		if (ret != 0)
			break;
	}
@@ -1428,7 +1433,7 @@ static int translate_compat_table(const char *name,
		goto free_newinfo;

	ret = -ELOOP;
	if (!mark_source_chains(newinfo, valid_hooks, entry1))
	if (!mark_source_chains(newinfo, compatr->valid_hooks, entry1))
		goto free_newinfo;

	i = 0;
@@ -1439,7 +1444,7 @@ static int translate_compat_table(const char *name,
			break;
		}

		ret = check_target(iter1, name);
		ret = check_target(iter1, compatr->name);
		if (ret != 0) {
			xt_percpu_counter_free(iter1->counters.pcnt);
			break;
@@ -1481,7 +1486,7 @@ static int translate_compat_table(const char *name,
free_newinfo:
	xt_free_table_info(newinfo);
out:
	xt_entry_foreach(iter0, entry0, total_size) {
	xt_entry_foreach(iter0, entry0, compatr->size) {
		if (j-- == 0)
			break;
		compat_release_entry(iter0);
@@ -1493,18 +1498,6 @@ static int translate_compat_table(const char *name,
	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,
			     unsigned int len)
{
@@ -1537,10 +1530,7 @@ static int compat_do_replace(struct net *net, void __user *user,
		goto free_newinfo;
	}

	ret = translate_compat_table(tmp.name, tmp.valid_hooks,
				     &newinfo, &loc_cpu_entry, tmp.size,
				     tmp.num_entries, tmp.hook_entry,
				     tmp.underflow);
	ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
	if (ret != 0)
		goto free_newinfo;