netfilter: x_tables: add compat version of xt_check_entry_offsets
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: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
a08e4e190b
commit
fc1221b3a1
|
@ -494,6 +494,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 */
|
||||
|
|
|
@ -1254,7 +1254,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;
|
||||
|
||||
|
|
|
@ -1513,7 +1513,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;
|
||||
|
||||
|
|
|
@ -1525,7 +1525,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;
|
||||
|
||||
|
|
|
@ -539,6 +539,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 */
|
||||
|
||||
/**
|
||||
|
@ -549,6 +570,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
|
||||
|
|
Loading…
Reference in New Issue