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

Commit 90e7d4ab authored by Jan Engelhardt's avatar Jan Engelhardt
Browse files

netfilter: xtables: check for unconditionality of policies



This adds a check that iptables's original author Rusty set forth in
a FIXME comment.

Underflows in iptables are better known as chain policies, and are
required to be unconditional or there would be a stochastical chance
for the policy rule to be skipped if it does not match. If that were
to happen, rule execution would continue in an unexpected spurious
fashion.

Signed-off-by: default avatarJan Engelhardt <jengelh@medozas.de>
parent a7d51738
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
 *
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -563,12 +563,14 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
			continue;
		if ((unsigned char *)e - base == hook_entries[h])
			newinfo->hook_entry[h] = hook_entries[h];
		if ((unsigned char *)e - base == underflows[h])
		if ((unsigned char *)e - base == underflows[h]) {
			if (!unconditional(&e->arp)) {
				pr_err("Underflows must be unconditional\n");
				return -EINVAL;
			}
			newinfo->underflow[h] = underflows[h];
		}

	/* FIXME: underflows must be unconditional, standard verdicts
	   < 0 (not ARPT_RETURN). --RR */
	}

	/* Clear counters and comefrom */
	e->counters = ((struct xt_counters) { 0, 0 });
+7 −4
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/cache.h>
#include <linux/capability.h>
#include <linux/skbuff.h>
@@ -738,12 +739,14 @@ check_entry_size_and_hooks(struct ipt_entry *e,
			continue;
		if ((unsigned char *)e - base == hook_entries[h])
			newinfo->hook_entry[h] = hook_entries[h];
		if ((unsigned char *)e - base == underflows[h])
		if ((unsigned char *)e - base == underflows[h]) {
			if (!unconditional(&e->ip)) {
				pr_err("Underflows must be unconditional\n");
				return -EINVAL;
			}
			newinfo->underflow[h] = underflows[h];
		}

	/* FIXME: underflows must be unconditional, standard verdicts
	   < 0 (not IPT_RETURN). --RR */
	}

	/* Clear counters and comefrom */
	e->counters = ((struct xt_counters) { 0, 0 });
+7 −5
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/capability.h>
#include <linux/in.h>
#include <linux/skbuff.h>
@@ -771,12 +771,14 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
			continue;
		if ((unsigned char *)e - base == hook_entries[h])
			newinfo->hook_entry[h] = hook_entries[h];
		if ((unsigned char *)e - base == underflows[h])
		if ((unsigned char *)e - base == underflows[h]) {
			if (!unconditional(&e->ipv6)) {
				pr_err("Underflows must be unconditional\n");
				return -EINVAL;
			}
			newinfo->underflow[h] = underflows[h];
		}

	/* FIXME: underflows must be unconditional, standard verdicts
	   < 0 (not IP6T_RETURN). --RR */
	}

	/* Clear counters and comefrom */
	e->counters = ((struct xt_counters) { 0, 0 });