diff options
author | Florian Westphal <fw@strlen.de> | 2016-04-01 14:17:23 +0200 |
---|---|---|
committer | Sasha Levin <sasha.levin@oracle.com> | 2016-07-12 08:48:30 -0400 |
commit | 62e6fd2010f76a52adcf0cf016b5d7c402ec17aa (patch) | |
tree | b2e77b28c3aacfc102fb3841167a2fb821ffdf81 /net/netfilter/x_tables.c | |
parent | 674c7e173d0112abb8cb666cb84a819e3ea69018 (diff) | |
download | linux-stable-62e6fd2010f76a52adcf0cf016b5d7c402ec17aa.tar.gz linux-stable-62e6fd2010f76a52adcf0cf016b5d7c402ec17aa.tar.bz2 linux-stable-62e6fd2010f76a52adcf0cf016b5d7c402ec17aa.zip |
netfilter: x_tables: add and use xt_check_entry_offsets
[ Upstream commit 7d35812c3214afa5b37a675113555259cfd67b98 ]
Currently arp/ip and ip6tables each implement a short helper to check that
the target offset is large enough to hold one xt_entry_target struct and
that t->u.target_size fits within the current rule.
Unfortunately these checks are not sufficient.
To avoid adding new tests to all of ip/ip6/arptables move the current
checks into a helper, then extend this helper in followup patches.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Diffstat (limited to 'net/netfilter/x_tables.c')
-rw-r--r-- | net/netfilter/x_tables.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 133eb4772f12..d846b52a6fc0 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -543,6 +543,40 @@ int xt_compat_match_to_user(const struct xt_entry_match *m, EXPORT_SYMBOL_GPL(xt_compat_match_to_user); #endif /* CONFIG_COMPAT */ +/** + * xt_check_entry_offsets - validate arp/ip/ip6t_entry + * + * @base: pointer to arp/ip/ip6t_entry + * @target_offset: the arp/ip/ip6_t->target_offset + * @next_offset: the arp/ip/ip6_t->next_offset + * + * validates that target_offset and next_offset are sane. + * + * The arp/ip/ip6t_entry structure @base must have passed following tests: + * - it must point to a valid memory location + * - base to base + next_offset must be accessible, i.e. not exceed allocated + * length. + * + * Return: 0 on success, negative errno on failure. + */ +int xt_check_entry_offsets(const void *base, + unsigned int target_offset, + unsigned int next_offset) +{ + const struct xt_entry_target *t; + const char *e = base; + + if (target_offset + sizeof(*t) > next_offset) + return -EINVAL; + + t = (void *)(e + target_offset); + if (target_offset + t->u.target_size > next_offset) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(xt_check_entry_offsets); + int xt_check_target(struct xt_tgchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { |