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: Jan Engelhardt <jengelh@medozas.de>
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
@@ -563,13 +563,15 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
|
|||||||
continue;
|
continue;
|
||||||
if ((unsigned char *)e - base == hook_entries[h])
|
if ((unsigned char *)e - base == hook_entries[h])
|
||||||
newinfo->hook_entry[h] = 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];
|
newinfo->underflow[h] = underflows[h];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: underflows must be unconditional, standard verdicts
|
|
||||||
< 0 (not ARPT_RETURN). --RR */
|
|
||||||
|
|
||||||
/* Clear counters and comefrom */
|
/* Clear counters and comefrom */
|
||||||
e->counters = ((struct xt_counters) { 0, 0 });
|
e->counters = ((struct xt_counters) { 0, 0 });
|
||||||
e->comefrom = 0;
|
e->comefrom = 0;
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
#include <linux/cache.h>
|
#include <linux/cache.h>
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
@@ -738,13 +739,15 @@ check_entry_size_and_hooks(struct ipt_entry *e,
|
|||||||
continue;
|
continue;
|
||||||
if ((unsigned char *)e - base == hook_entries[h])
|
if ((unsigned char *)e - base == hook_entries[h])
|
||||||
newinfo->hook_entry[h] = 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];
|
newinfo->underflow[h] = underflows[h];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: underflows must be unconditional, standard verdicts
|
|
||||||
< 0 (not IPT_RETURN). --RR */
|
|
||||||
|
|
||||||
/* Clear counters and comefrom */
|
/* Clear counters and comefrom */
|
||||||
e->counters = ((struct xt_counters) { 0, 0 });
|
e->counters = ((struct xt_counters) { 0, 0 });
|
||||||
e->comefrom = 0;
|
e->comefrom = 0;
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#include <linux/in.h>
|
#include <linux/in.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
@@ -771,13 +771,15 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
|
|||||||
continue;
|
continue;
|
||||||
if ((unsigned char *)e - base == hook_entries[h])
|
if ((unsigned char *)e - base == hook_entries[h])
|
||||||
newinfo->hook_entry[h] = 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];
|
newinfo->underflow[h] = underflows[h];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: underflows must be unconditional, standard verdicts
|
|
||||||
< 0 (not IP6T_RETURN). --RR */
|
|
||||||
|
|
||||||
/* Clear counters and comefrom */
|
/* Clear counters and comefrom */
|
||||||
e->counters = ((struct xt_counters) { 0, 0 });
|
e->counters = ((struct xt_counters) { 0, 0 });
|
||||||
e->comefrom = 0;
|
e->comefrom = 0;
|
||||||
|
Reference in New Issue
Block a user