Patch "netfilter: x_tables: add and use xt_check_entry_offsets" has been added to the 4.6-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
netfilter: x_tables: add and use xt_check_entry_offsets
to the 4.6-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
netfilter-x_tables-add-and-use-xt_check_entry_offsets.patch
and it can be found in the queue-4.6 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
7d35812c3214afa5b37a675113555259cfd67b98Mon Sep 17 00:00:00 2001
From: Florian Westphal <[email protected]>
Date: Fri, 1 Apr 2016 14:17:23 +0200
Subject: netfilter: x_tables: add and use xt_check_entry_offsets
From: Florian Westphal <[email protected]>
commit 7d35812c3214afa5b37a675113555259cfd67b98 upstream.
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.
--- include/linux/netfilter/x_tables.h | 4 ++++ net/ipv4/netfilter/arp_tables.c | 11 +---------- net/ipv4/netfilter/ip_tables.c | 12 +----------- net/ipv6/netfilter/ip6_tables.c | 12 +----------- net/netfilter/x_tables.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 41 insertions(+), 32 deletions(-)
include/linux/netfilter/x_tables.h +4 -0
@@ -242,6 +242,10 @@ void xt_unregister_match(struct xt_matchint xt_register_matches (struct xt_match *match,unsigned int n);void xt_unregister_matches (struct xt_match *match,unsigned int n); +int xt_check_entry_offsets (const void *base, +unsigned int target_offset, +unsigned int next_offset); +int xt_check_match (struct xt_mtchk_param *,unsigned int size,u_int8_t proto,bool inv_proto); int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto,
net/ipv4/netfilter/arp_tables.c +1 -10
@@ -496,19 +496,10 @@ next:static inline int check_entry (const struct arpt_entry *e) { -const struct xt_entry_target *t; -if (!arp_checkentry (&e->arp))return -EINVAL ; -if (e->target_offset +sizeof (struct xt_entry_target ) > e->next_offset) -return -EINVAL ; - - t =arpt_get_target_c (e); -if (e->target_offset + t->u.target_size > e->next_offset) -return -EINVAL ; - -return 0 ; +return xt_check_entry_offsets (e, e->target_offset, e->next_offset); }static inline int check_target (struct arpt_entry *e,const char *name)
net/ipv4/netfilter/ip_tables.c +1 -11
@@ -590,20 +590,10 @@ static void cleanup_match(struct xt_entrstatic int check_entry (const struct ipt_entry *e) { -const struct xt_entry_target *t; -if (!ip_checkentry (&e->ip))return -EINVAL ; -if (e->target_offset +sizeof (struct xt_entry_target ) > - e->next_offset) -return -EINVAL ; - - t =ipt_get_target_c (e); -if (e->target_offset + t->u.target_size > e->next_offset) -return -EINVAL ; - -return 0 ; +return xt_check_entry_offsets (e, e->target_offset, e->next_offset); } static int
net/ipv6/netfilter/ip6_tables.c +1 -11
@@ -602,20 +602,10 @@ static void cleanup_match(struct xt_entrstatic int check_entry (const struct ip6t_entry *e) { -const struct xt_entry_target *t; -if (!ip6_checkentry (&e->ipv6))return -EINVAL ; -if (e->target_offset +sizeof (struct xt_entry_target ) > - e->next_offset) -return -EINVAL ; - - t =ip6t_get_target_c (e); -if (e->target_offset + t->u.target_size > e->next_offset) -return -EINVAL ; - -return 0 ; +return xt_check_entry_offsets (e, e->target_offset, e->next_offset); }static int check_match (struct xt_entry_match *m,struct xt_mtchk_param *par)
net/netfilter/x_tables.c +34 -0
@@ -541,6 +541,40 @@ int xt_compat_match_to_user(const structEXPORT_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) {
Patches currently in stable-queue which might be from [email protected] are
queue-4.6/netfilter-x_tables-add-and-use-xt_check_entry_offsets.patch queue-4.6/netfilter-x_tables-assert-minimum-target-size.patch queue-4.6/netfilter-x_tables-add-compat-version-of-xt_check_entry_offsets.patch queue-4.6/netfilter-x_tables-check-for-bogus-target-offset.patch queue-4.6/netfilter-x_tables-validate-targets-of-jumps.patch queue-4.6/netfilter-x_tables-don-t-move-to-non-existent-next-rule.patch queue-4.6/netfilter-x_tables-kill-check_entry-helper.patch queue-4.6/netfilter-x_tables-check-standard-target-size-too.patch queue-4.6/netfilter-x_tables-validate-all-offsets-and-sizes-in-a-rule.patch