Commit 7ef13f49 authored by Florian Westphal's avatar Florian Westphal Committed by Sasha Levin

netfilter: x_tables: add compat version of xt_check_entry_offsets

[ Upstream commit fc1221b3 ]

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 avatarSasha Levin <sasha.levin@oracle.com>
parent 37a6fed6
......@@ -435,6 +435,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
unsigned int *size);
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 */
......@@ -1244,7 +1244,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;
......
......@@ -1509,7 +1509,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;
......
......@@ -1521,7 +1521,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;
......
......@@ -541,6 +541,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 */
/**
......@@ -551,6 +572,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