Commit 45c465bb authored by Florian Westphal's avatar Florian Westphal Committed by Jiri Slaby

netfilter: x_tables: add compat version of xt_check_entry_offsets

commit fc1221b3 upstream.

32bit rulesets have different layout and alignment requirements, so once
more integrity checks get added to xt_check_entry_offsets it will reject
well-formed 32bit rulesets.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
parent d5056b9b
......@@ -437,6 +437,9 @@ extern void xt_compat_target_from_user(struct xt_entry_target *t,
void **dstptr, unsigned int *size);
extern int xt_compat_target_to_user(const struct xt_entry_target *t,
void __user **dstptr, unsigned int *size);
int xt_compat_check_entry_offsets(const void *base,
unsigned int target_offset,
unsigned int next_offset);
#endif /* CONFIG_COMPAT */
#endif /* _X_TABLES_H */
......@@ -1223,7 +1223,8 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
if (!arp_checkentry(&e->arp))
return -EINVAL;
ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
ret = xt_compat_check_entry_offsets(e, e->target_offset,
e->next_offset);
if (ret)
return ret;
......
......@@ -1488,7 +1488,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
if (!ip_checkentry(&e->ip))
return -EINVAL;
ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
ret = xt_compat_check_entry_offsets(e,
e->target_offset, e->next_offset);
if (ret)
return ret;
......
......@@ -1500,7 +1500,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
if (!ip6_checkentry(&e->ipv6))
return -EINVAL;
ret = xt_check_entry_offsets(e, e->target_offset, e->next_offset);
ret = xt_compat_check_entry_offsets(e,
e->target_offset, e->next_offset);
if (ret)
return ret;
......
......@@ -558,6 +558,27 @@ int xt_compat_match_to_user(const struct xt_entry_match *m,
return 0;
}
EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
int xt_compat_check_entry_offsets(const void *base,
unsigned int target_offset,
unsigned int next_offset)
{
const struct compat_xt_entry_target *t;
const char *e = base;
if (target_offset + sizeof(*t) > next_offset)
return -EINVAL;
t = (void *)(e + target_offset);
if (t->u.target_size < sizeof(*t))
return -EINVAL;
if (target_offset + t->u.target_size > next_offset)
return -EINVAL;
return 0;
}
EXPORT_SYMBOL(xt_compat_check_entry_offsets);
#endif /* CONFIG_COMPAT */
/**
......@@ -568,6 +589,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
* @next_offset: the arp/ip/ip6_t->next_offset
*
* validates that target_offset and next_offset are sane.
* Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
*
* The arp/ip/ip6t_entry structure @base must have passed following tests:
* - it must point to a valid memory location
......
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