Commit 73cd598d authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: ip_tables: fix compat types

Use compat types and compat iterators when dealing with compat entries for
clarity. This doesn't actually make a difference for ip_tables, but is
needed for ip6_tables and arp_tables.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 30c08c41
...@@ -236,11 +236,6 @@ ipt_get_target(struct ipt_entry *e) ...@@ -236,11 +236,6 @@ ipt_get_target(struct ipt_entry *e)
#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ #define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
/* fn returns 0 to continue iteration */
#define IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
XT_ENTRY_ITERATE_CONTINUE(struct ipt_entry, entries, size, n, fn, \
## args)
/* /*
* Main firewall chains definitions and global var's definitions. * Main firewall chains definitions and global var's definitions.
*/ */
...@@ -316,8 +311,28 @@ struct compat_ipt_entry ...@@ -316,8 +311,28 @@ struct compat_ipt_entry
unsigned char elems[0]; unsigned char elems[0];
}; };
/* Helper functions */
static inline struct ipt_entry_target *
compat_ipt_get_target(struct compat_ipt_entry *e)
{
return (void *)e + e->target_offset;
}
#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s) #define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s)
/* fn returns 0 to continue iteration */
#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \
XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args)
/* fn returns 0 to continue iteration */
#define COMPAT_IPT_ENTRY_ITERATE(entries, size, fn, args...) \
XT_ENTRY_ITERATE(struct compat_ipt_entry, entries, size, fn, ## args)
/* fn returns 0 to continue iteration */
#define COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
XT_ENTRY_ITERATE_CONTINUE(struct compat_ipt_entry, entries, size, n, \
fn, ## args)
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
#endif /*__KERNEL__*/ #endif /*__KERNEL__*/
#endif /* _IPTABLES_H */ #endif /* _IPTABLES_H */
...@@ -1559,7 +1559,7 @@ compat_release_match(struct ipt_entry_match *m, unsigned int *i) ...@@ -1559,7 +1559,7 @@ compat_release_match(struct ipt_entry_match *m, unsigned int *i)
} }
static inline int static inline int
compat_release_entry(struct ipt_entry *e, unsigned int *i) compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
{ {
struct ipt_entry_target *t; struct ipt_entry_target *t;
...@@ -1567,14 +1567,14 @@ compat_release_entry(struct ipt_entry *e, unsigned int *i) ...@@ -1567,14 +1567,14 @@ compat_release_entry(struct ipt_entry *e, unsigned int *i)
return 1; return 1;
/* Cleanup all matches */ /* Cleanup all matches */
IPT_MATCH_ITERATE(e, compat_release_match, NULL); COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
t = ipt_get_target(e); t = compat_ipt_get_target(e);
module_put(t->u.kernel.target->me); module_put(t->u.kernel.target->me);
return 0; return 0;
} }
static inline int static inline int
check_compat_entry_size_and_hooks(struct ipt_entry *e, check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
struct xt_table_info *newinfo, struct xt_table_info *newinfo,
unsigned int *size, unsigned int *size,
unsigned char *base, unsigned char *base,
...@@ -1603,19 +1603,20 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, ...@@ -1603,19 +1603,20 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
return -EINVAL; return -EINVAL;
} }
ret = check_entry(e, name); /* For purposes of check_entry casting the compat entry is fine */
ret = check_entry((struct ipt_entry *)e, name);
if (ret) if (ret)
return ret; return ret;
off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
entry_offset = (void *)e - (void *)base; entry_offset = (void *)e - (void *)base;
j = 0; j = 0;
ret = IPT_MATCH_ITERATE(e, compat_find_calc_match, name, &e->ip, ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
e->comefrom, &off, &j); &e->ip, e->comefrom, &off, &j);
if (ret != 0) if (ret != 0)
goto release_matches; goto release_matches;
t = ipt_get_target(e); t = compat_ipt_get_target(e);
target = try_then_request_module(xt_find_target(AF_INET, target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name, t->u.user.name,
t->u.user.revision), t->u.user.revision),
...@@ -1643,7 +1644,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, ...@@ -1643,7 +1644,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
} }
/* Clear counters and comefrom */ /* Clear counters and comefrom */
e->counters = ((struct ipt_counters) { 0, 0 }); memset(&e->counters, 0, sizeof(e->counters));
e->comefrom = 0; e->comefrom = 0;
(*i)++; (*i)++;
...@@ -1657,7 +1658,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, ...@@ -1657,7 +1658,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
} }
static int static int
compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
unsigned int *size, const char *name, unsigned int *size, const char *name,
struct xt_table_info *newinfo, unsigned char *base) struct xt_table_info *newinfo, unsigned char *base)
{ {
...@@ -1671,15 +1672,17 @@ compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, ...@@ -1671,15 +1672,17 @@ compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
origsize = *size; origsize = *size;
de = (struct ipt_entry *)*dstptr; de = (struct ipt_entry *)*dstptr;
memcpy(de, e, sizeof(struct ipt_entry)); memcpy(de, e, sizeof(struct ipt_entry));
memcpy(&de->counters, &e->counters, sizeof(e->counters));
*dstptr += sizeof(struct compat_ipt_entry); *dstptr += sizeof(struct ipt_entry);
*size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
ret = IPT_MATCH_ITERATE(e, xt_compat_match_from_user, dstptr, size); ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
dstptr, size);
if (ret) if (ret)
return ret; return ret;
de->target_offset = e->target_offset - (origsize - *size); de->target_offset = e->target_offset - (origsize - *size);
t = ipt_get_target(e); t = compat_ipt_get_target(e);
target = t->u.kernel.target; target = t->u.kernel.target;
xt_compat_target_from_user(t, dstptr, size); xt_compat_target_from_user(t, dstptr, size);
...@@ -1746,11 +1749,11 @@ translate_compat_table(const char *name, ...@@ -1746,11 +1749,11 @@ translate_compat_table(const char *name,
j = 0; j = 0;
xt_compat_lock(AF_INET); xt_compat_lock(AF_INET);
/* Walk through entries, checking offsets. */ /* Walk through entries, checking offsets. */
ret = IPT_ENTRY_ITERATE(entry0, total_size, ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
check_compat_entry_size_and_hooks, check_compat_entry_size_and_hooks,
info, &size, entry0, info, &size, entry0,
entry0 + total_size, entry0 + total_size,
hook_entries, underflows, &j, name); hook_entries, underflows, &j, name);
if (ret != 0) if (ret != 0)
goto out_unlock; goto out_unlock;
...@@ -1791,9 +1794,9 @@ translate_compat_table(const char *name, ...@@ -1791,9 +1794,9 @@ translate_compat_table(const char *name,
entry1 = newinfo->entries[raw_smp_processor_id()]; entry1 = newinfo->entries[raw_smp_processor_id()];
pos = entry1; pos = entry1;
size = total_size; size = total_size;
ret = IPT_ENTRY_ITERATE(entry0, total_size, ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
compat_copy_entry_from_user, &pos, &size, compat_copy_entry_from_user, &pos, &size,
name, newinfo, entry1); name, newinfo, entry1);
compat_flush_offsets(); compat_flush_offsets();
xt_compat_unlock(AF_INET); xt_compat_unlock(AF_INET);
if (ret) if (ret)
...@@ -1808,8 +1811,8 @@ translate_compat_table(const char *name, ...@@ -1808,8 +1811,8 @@ translate_compat_table(const char *name,
name, &i); name, &i);
if (ret) { if (ret) {
j -= i; j -= i;
IPT_ENTRY_ITERATE_CONTINUE(entry1, newinfo->size, i, COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
compat_release_entry, &j); compat_release_entry, &j);
IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
xt_free_table_info(newinfo); xt_free_table_info(newinfo);
return ret; return ret;
...@@ -1828,7 +1831,7 @@ translate_compat_table(const char *name, ...@@ -1828,7 +1831,7 @@ translate_compat_table(const char *name,
free_newinfo: free_newinfo:
xt_free_table_info(newinfo); xt_free_table_info(newinfo);
out: out:
IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
return ret; return ret;
out_unlock: out_unlock:
compat_flush_offsets(); compat_flush_offsets();
......
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