Commit 67fc878a authored by Florian Westphal's avatar Florian Westphal Committed by Brad Figg

netfilter: x_tables: validate targets of jumps

When we see a jump also check that the offset gets us to beginning of
a rule (an ipt_entry).

The extra overhead is negible, even with absurd cases.

300k custom rules, 300k jumps to 'next' user chain:
[ plus one jump from INPUT to first userchain ]:

Before:
real    0m24.874s
user    0m7.532s
sys     0m16.076s

After:
real    0m27.464s
user    0m7.436s
sys     0m18.840s
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
(backported from commit 36472341)
[ luis: adjusted context ]
BugLink: https://bugs.launchpad.net/bugs/1595350Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
Acked-by: default avatarTim Gardner <tim.gardner@canonical.com>
Signed-off-by: default avatarBrad Figg <brad.figg@canonical.com>
parent 4654741d
......@@ -378,6 +378,18 @@ static bool next_offset_ok(const struct xt_table_info *t, unsigned int newpos)
return true;
}
static bool find_jump_target(const struct xt_table_info *t,
const struct arpt_entry *target)
{
struct arpt_entry *iter;
xt_entry_foreach(iter, t->entries, t->size) {
if (iter == target)
return true;
}
return false;
}
/* Figures out from what hook each rule can be called: returns 0 if
* there are loops. Puts hook bitmask in comefrom.
*/
......@@ -465,6 +477,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
e = (struct arpt_entry *)
(entry0 + newpos);
if (!find_jump_target(newinfo, e))
return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
......
......@@ -454,6 +454,18 @@ static bool next_offset_ok(const struct xt_table_info *t, unsigned int newpos)
return true;
}
static bool find_jump_target(const struct xt_table_info *t,
const struct ipt_entry *target)
{
struct ipt_entry *iter;
xt_entry_foreach(iter, t->entries, t->size) {
if (iter == target)
return true;
}
return false;
}
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
......@@ -546,6 +558,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
e = (struct ipt_entry *)
(entry0 + newpos);
if (!find_jump_target(newinfo, e))
return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
......
......@@ -466,6 +466,18 @@ static bool next_offset_ok(const struct xt_table_info *t, unsigned int newpos)
return true;
}
static bool find_jump_target(const struct xt_table_info *t,
const struct ip6t_entry *target)
{
struct ip6t_entry *iter;
xt_entry_foreach(iter, t->entries, t->size) {
if (iter == target)
return true;
}
return false;
}
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
......@@ -558,6 +570,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
e = (struct ip6t_entry *)
(entry0 + newpos);
if (!find_jump_target(newinfo, e))
return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
......
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