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

Commit 3bd22997 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: arptables: use percpu jumpstack



commit 482cfc31 ("netfilter: xtables: avoid percpu ruleset duplication")

Unlike ip and ip6tables, arp tables were never converted to use the percpu
jump stack.

It still uses the rule blob to store return address, which isn't safe
anymore since we now share this blob among all processors.

Because there is no TEE support for arptables, we don't need to cope
with reentrancy, so we can use loocal variable to hold stack offset.

Fixes: 482cfc31 ("netfilter: xtables: avoid percpu ruleset duplication")
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent a1bc1b35
Loading
Loading
Loading
Loading
+16 −9
Original line number Diff line number Diff line
@@ -254,9 +254,10 @@ unsigned int arpt_do_table(struct sk_buff *skb,
	static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
	unsigned int verdict = NF_DROP;
	const struct arphdr *arp;
	struct arpt_entry *e, *back;
	struct arpt_entry *e, **jumpstack;
	const char *indev, *outdev;
	const void *table_base;
	unsigned int cpu, stackidx = 0;
	const struct xt_table_info *private;
	struct xt_action_param acpar;
	unsigned int addend;
@@ -270,15 +271,16 @@ unsigned int arpt_do_table(struct sk_buff *skb,
	local_bh_disable();
	addend = xt_write_recseq_begin();
	private = table->private;
	cpu     = smp_processor_id();
	/*
	 * Ensure we load private-> members after we've fetched the base
	 * pointer.
	 */
	smp_read_barrier_depends();
	table_base = private->entries;
	jumpstack  = (struct arpt_entry **)private->jumpstack[cpu];

	e = get_entry(table_base, private->hook_entry[hook]);
	back = get_entry(table_base, private->underflow[hook]);

	acpar.in      = state->in;
	acpar.out     = state->out;
@@ -312,18 +314,23 @@ unsigned int arpt_do_table(struct sk_buff *skb,
					verdict = (unsigned int)(-v) - 1;
					break;
				}
				e = back;
				back = get_entry(table_base, back->comefrom);
				if (stackidx == 0) {
					e = get_entry(table_base,
						      private->underflow[hook]);
				} else {
					e = jumpstack[--stackidx];
					e = arpt_next_entry(e);
				}
				continue;
			}
			if (table_base + v
			    != arpt_next_entry(e)) {
				/* Save old back ptr in next entry */
				struct arpt_entry *next = arpt_next_entry(e);
				next->comefrom = (void *)back - table_base;

				/* set back pointer to next entry */
				back = next;
				if (stackidx >= private->stacksize) {
					verdict = NF_DROP;
					break;
				}
				jumpstack[stackidx++] = e;
			}

			e = get_entry(table_base, v);