aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2016-04-01 08:17:28 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2016-04-13 18:30:37 -0400
commitce683e5f9d045e5d67d1312a42b359cb2ab2a13c (patch)
tree74c29eb462a8829b7cffac63a09d2e702788144c /net/netfilter
parent7ed2abddd20cf8f6bd27f65bd218f26fa5bf7f44 (diff)
netfilter: x_tables: check for bogus target offset
We're currently asserting that targetoff + targetsize <= nextoff. Extend it to also check that targetoff is >= sizeof(xt_entry). Since this is generic code, add an argument pointing to the start of the match/target, we can then derive the base structure size from the delta. We also need the e->elems pointer in a followup change to validate matches. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/x_tables.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 1cb7a271c024..e2a6f2a9051b 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -546,14 +546,17 @@ struct compat_xt_standard_target {
546 compat_uint_t verdict; 546 compat_uint_t verdict;
547}; 547};
548 548
549/* see xt_check_entry_offsets */ 549int xt_compat_check_entry_offsets(const void *base, const char *elems,
550int xt_compat_check_entry_offsets(const void *base,
551 unsigned int target_offset, 550 unsigned int target_offset,
552 unsigned int next_offset) 551 unsigned int next_offset)
553{ 552{
553 long size_of_base_struct = elems - (const char *)base;
554 const struct compat_xt_entry_target *t; 554 const struct compat_xt_entry_target *t;
555 const char *e = base; 555 const char *e = base;
556 556
557 if (target_offset < size_of_base_struct)
558 return -EINVAL;
559
557 if (target_offset + sizeof(*t) > next_offset) 560 if (target_offset + sizeof(*t) > next_offset)
558 return -EINVAL; 561 return -EINVAL;
559 562
@@ -577,12 +580,16 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets);
577 * xt_check_entry_offsets - validate arp/ip/ip6t_entry 580 * xt_check_entry_offsets - validate arp/ip/ip6t_entry
578 * 581 *
579 * @base: pointer to arp/ip/ip6t_entry 582 * @base: pointer to arp/ip/ip6t_entry
583 * @elems: pointer to first xt_entry_match, i.e. ip(6)t_entry->elems
580 * @target_offset: the arp/ip/ip6_t->target_offset 584 * @target_offset: the arp/ip/ip6_t->target_offset
581 * @next_offset: the arp/ip/ip6_t->next_offset 585 * @next_offset: the arp/ip/ip6_t->next_offset
582 * 586 *
583 * validates that target_offset and next_offset are sane. 587 * validates that target_offset and next_offset are sane.
584 * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version. 588 * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
585 * 589 *
590 * This function does not validate the targets or matches themselves, it
591 * only tests that all the offsets and sizes are correct.
592 *
586 * The arp/ip/ip6t_entry structure @base must have passed following tests: 593 * The arp/ip/ip6t_entry structure @base must have passed following tests:
587 * - it must point to a valid memory location 594 * - it must point to a valid memory location
588 * - base to base + next_offset must be accessible, i.e. not exceed allocated 595 * - base to base + next_offset must be accessible, i.e. not exceed allocated
@@ -591,12 +598,18 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets);
591 * Return: 0 on success, negative errno on failure. 598 * Return: 0 on success, negative errno on failure.
592 */ 599 */
593int xt_check_entry_offsets(const void *base, 600int xt_check_entry_offsets(const void *base,
601 const char *elems,
594 unsigned int target_offset, 602 unsigned int target_offset,
595 unsigned int next_offset) 603 unsigned int next_offset)
596{ 604{
605 long size_of_base_struct = elems - (const char *)base;
597 const struct xt_entry_target *t; 606 const struct xt_entry_target *t;
598 const char *e = base; 607 const char *e = base;
599 608
609 /* target start is within the ip/ip6/arpt_entry struct */
610 if (target_offset < size_of_base_struct)
611 return -EINVAL;
612
600 if (target_offset + sizeof(*t) > next_offset) 613 if (target_offset + sizeof(*t) > next_offset)
601 return -EINVAL; 614 return -EINVAL;
602 615