Commit 47a6959f authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: allow to turn off xtables compat layer

The compat layer needs to parse untrusted input (the ruleset)
to translate it to a 64bit compatible format.

We had a number of bugs in this department in the past, so allow users
to turn this feature off.

Add CONFIG_NETFILTER_XTABLES_COMPAT kconfig knob and make it default to y
to keep existing behaviour.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 50f2db9e
...@@ -158,7 +158,7 @@ struct xt_match { ...@@ -158,7 +158,7 @@ struct xt_match {
/* Called when entry of this type deleted. */ /* Called when entry of this type deleted. */
void (*destroy)(const struct xt_mtdtor_param *); void (*destroy)(const struct xt_mtdtor_param *);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
/* Called when userspace align differs from kernel space one */ /* Called when userspace align differs from kernel space one */
void (*compat_from_user)(void *dst, const void *src); void (*compat_from_user)(void *dst, const void *src);
int (*compat_to_user)(void __user *dst, const void *src); int (*compat_to_user)(void __user *dst, const void *src);
...@@ -169,7 +169,7 @@ struct xt_match { ...@@ -169,7 +169,7 @@ struct xt_match {
const char *table; const char *table;
unsigned int matchsize; unsigned int matchsize;
unsigned int usersize; unsigned int usersize;
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
unsigned int compatsize; unsigned int compatsize;
#endif #endif
unsigned int hooks; unsigned int hooks;
...@@ -199,7 +199,7 @@ struct xt_target { ...@@ -199,7 +199,7 @@ struct xt_target {
/* Called when entry of this type deleted. */ /* Called when entry of this type deleted. */
void (*destroy)(const struct xt_tgdtor_param *); void (*destroy)(const struct xt_tgdtor_param *);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
/* Called when userspace align differs from kernel space one */ /* Called when userspace align differs from kernel space one */
void (*compat_from_user)(void *dst, const void *src); void (*compat_from_user)(void *dst, const void *src);
int (*compat_to_user)(void __user *dst, const void *src); int (*compat_to_user)(void __user *dst, const void *src);
...@@ -210,7 +210,7 @@ struct xt_target { ...@@ -210,7 +210,7 @@ struct xt_target {
const char *table; const char *table;
unsigned int targetsize; unsigned int targetsize;
unsigned int usersize; unsigned int usersize;
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
unsigned int compatsize; unsigned int compatsize;
#endif #endif
unsigned int hooks; unsigned int hooks;
...@@ -452,7 +452,7 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu) ...@@ -452,7 +452,7 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu)
struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *); struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
#include <net/compat.h> #include <net/compat.h>
struct compat_xt_entry_match { struct compat_xt_entry_match {
...@@ -533,5 +533,5 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems, ...@@ -533,5 +533,5 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
unsigned int target_offset, unsigned int target_offset,
unsigned int next_offset); unsigned int next_offset);
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_NETFILTER_XTABLES_COMPAT */
#endif /* _X_TABLES_H */ #endif /* _X_TABLES_H */
...@@ -59,7 +59,7 @@ extern unsigned int arpt_do_table(struct sk_buff *skb, ...@@ -59,7 +59,7 @@ extern unsigned int arpt_do_table(struct sk_buff *skb,
const struct nf_hook_state *state, const struct nf_hook_state *state,
struct xt_table *table); struct xt_table *table);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
#include <net/compat.h> #include <net/compat.h>
struct compat_arpt_entry { struct compat_arpt_entry {
......
...@@ -67,7 +67,7 @@ extern unsigned int ipt_do_table(struct sk_buff *skb, ...@@ -67,7 +67,7 @@ extern unsigned int ipt_do_table(struct sk_buff *skb,
const struct nf_hook_state *state, const struct nf_hook_state *state,
struct xt_table *table); struct xt_table *table);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
#include <net/compat.h> #include <net/compat.h>
struct compat_ipt_entry { struct compat_ipt_entry {
......
...@@ -33,7 +33,7 @@ extern unsigned int ip6t_do_table(struct sk_buff *skb, ...@@ -33,7 +33,7 @@ extern unsigned int ip6t_do_table(struct sk_buff *skb,
const struct nf_hook_state *state, const struct nf_hook_state *state,
struct xt_table *table); struct xt_table *table);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
#include <net/compat.h> #include <net/compat.h>
struct compat_ip6t_entry { struct compat_ip6t_entry {
......
...@@ -87,7 +87,7 @@ static int ebt_limit_mt_check(const struct xt_mtchk_param *par) ...@@ -87,7 +87,7 @@ static int ebt_limit_mt_check(const struct xt_mtchk_param *par)
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
/* /*
* no conversion function needed -- * no conversion function needed --
* only avg/burst have meaningful values in userspace. * only avg/burst have meaningful values in userspace.
...@@ -107,7 +107,7 @@ static struct xt_match ebt_limit_mt_reg __read_mostly = { ...@@ -107,7 +107,7 @@ static struct xt_match ebt_limit_mt_reg __read_mostly = {
.checkentry = ebt_limit_mt_check, .checkentry = ebt_limit_mt_check,
.matchsize = sizeof(struct ebt_limit_info), .matchsize = sizeof(struct ebt_limit_info),
.usersize = offsetof(struct ebt_limit_info, prev), .usersize = offsetof(struct ebt_limit_info, prev),
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(struct ebt_compat_limit_info), .compatsize = sizeof(struct ebt_compat_limit_info),
#endif #endif
.me = THIS_MODULE, .me = THIS_MODULE,
......
...@@ -53,7 +53,7 @@ static int ebt_mark_tg_check(const struct xt_tgchk_param *par) ...@@ -53,7 +53,7 @@ static int ebt_mark_tg_check(const struct xt_tgchk_param *par)
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct compat_ebt_mark_t_info { struct compat_ebt_mark_t_info {
compat_ulong_t mark; compat_ulong_t mark;
compat_uint_t target; compat_uint_t target;
...@@ -87,7 +87,7 @@ static struct xt_target ebt_mark_tg_reg __read_mostly = { ...@@ -87,7 +87,7 @@ static struct xt_target ebt_mark_tg_reg __read_mostly = {
.target = ebt_mark_tg, .target = ebt_mark_tg,
.checkentry = ebt_mark_tg_check, .checkentry = ebt_mark_tg_check,
.targetsize = sizeof(struct ebt_mark_t_info), .targetsize = sizeof(struct ebt_mark_t_info),
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(struct compat_ebt_mark_t_info), .compatsize = sizeof(struct compat_ebt_mark_t_info),
.compat_from_user = mark_tg_compat_from_user, .compat_from_user = mark_tg_compat_from_user,
.compat_to_user = mark_tg_compat_to_user, .compat_to_user = mark_tg_compat_to_user,
......
...@@ -37,7 +37,7 @@ static int ebt_mark_mt_check(const struct xt_mtchk_param *par) ...@@ -37,7 +37,7 @@ static int ebt_mark_mt_check(const struct xt_mtchk_param *par)
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct compat_ebt_mark_m_info { struct compat_ebt_mark_m_info {
compat_ulong_t mark, mask; compat_ulong_t mark, mask;
uint8_t invert, bitmask; uint8_t invert, bitmask;
...@@ -75,7 +75,7 @@ static struct xt_match ebt_mark_mt_reg __read_mostly = { ...@@ -75,7 +75,7 @@ static struct xt_match ebt_mark_mt_reg __read_mostly = {
.match = ebt_mark_mt, .match = ebt_mark_mt,
.checkentry = ebt_mark_mt_check, .checkentry = ebt_mark_mt_check,
.matchsize = sizeof(struct ebt_mark_m_info), .matchsize = sizeof(struct ebt_mark_m_info),
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(struct compat_ebt_mark_m_info), .compatsize = sizeof(struct compat_ebt_mark_m_info),
.compat_from_user = mark_mt_compat_from_user, .compat_from_user = mark_mt_compat_from_user,
.compat_to_user = mark_mt_compat_to_user, .compat_to_user = mark_mt_compat_to_user,
......
...@@ -47,7 +47,7 @@ struct ebt_pernet { ...@@ -47,7 +47,7 @@ struct ebt_pernet {
static unsigned int ebt_pernet_id __read_mostly; static unsigned int ebt_pernet_id __read_mostly;
static DEFINE_MUTEX(ebt_mutex); static DEFINE_MUTEX(ebt_mutex);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
static void ebt_standard_compat_from_user(void *dst, const void *src) static void ebt_standard_compat_from_user(void *dst, const void *src)
{ {
int v = *(compat_int_t *)src; int v = *(compat_int_t *)src;
...@@ -73,7 +73,7 @@ static struct xt_target ebt_standard_target = { ...@@ -73,7 +73,7 @@ static struct xt_target ebt_standard_target = {
.revision = 0, .revision = 0,
.family = NFPROTO_BRIDGE, .family = NFPROTO_BRIDGE,
.targetsize = sizeof(int), .targetsize = sizeof(int),
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(compat_int_t), .compatsize = sizeof(compat_int_t),
.compat_from_user = ebt_standard_compat_from_user, .compat_from_user = ebt_standard_compat_from_user,
.compat_to_user = ebt_standard_compat_to_user, .compat_to_user = ebt_standard_compat_to_user,
...@@ -1502,7 +1502,7 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user, ...@@ -1502,7 +1502,7 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user,
ebt_entry_to_user, entries, tmp.entries); ebt_entry_to_user, entries, tmp.entries);
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
/* 32 bit-userspace compatibility definitions. */ /* 32 bit-userspace compatibility definitions. */
struct compat_ebt_replace { struct compat_ebt_replace {
char name[EBT_TABLE_MAXNAMELEN]; char name[EBT_TABLE_MAXNAMELEN];
...@@ -2367,7 +2367,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ...@@ -2367,7 +2367,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM; return -EPERM;
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
/* try real handler in case userland supplied needed padding */ /* try real handler in case userland supplied needed padding */
if (in_compat_syscall() && if (in_compat_syscall() &&
((cmd != EBT_SO_GET_INFO && cmd != EBT_SO_GET_INIT_INFO) || ((cmd != EBT_SO_GET_INFO && cmd != EBT_SO_GET_INIT_INFO) ||
...@@ -2434,7 +2434,7 @@ static int do_ebt_set_ctl(struct sock *sk, int cmd, sockptr_t arg, ...@@ -2434,7 +2434,7 @@ static int do_ebt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
switch (cmd) { switch (cmd) {
case EBT_SO_SET_ENTRIES: case EBT_SO_SET_ENTRIES:
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
ret = compat_do_replace(net, arg, len); ret = compat_do_replace(net, arg, len);
else else
...@@ -2442,7 +2442,7 @@ static int do_ebt_set_ctl(struct sock *sk, int cmd, sockptr_t arg, ...@@ -2442,7 +2442,7 @@ static int do_ebt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
ret = do_replace(net, arg, len); ret = do_replace(net, arg, len);
break; break;
case EBT_SO_SET_COUNTERS: case EBT_SO_SET_COUNTERS:
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
ret = compat_update_counters(net, arg, len); ret = compat_update_counters(net, arg, len);
else else
......
...@@ -713,7 +713,7 @@ static int copy_entries_to_user(unsigned int total_size, ...@@ -713,7 +713,7 @@ static int copy_entries_to_user(unsigned int total_size,
return ret; return ret;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
static void compat_standard_from_user(void *dst, const void *src) static void compat_standard_from_user(void *dst, const void *src)
{ {
int v = *(compat_int_t *)src; int v = *(compat_int_t *)src;
...@@ -800,7 +800,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -800,7 +800,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
return -EFAULT; return -EFAULT;
name[XT_TABLE_MAXNAMELEN-1] = '\0'; name[XT_TABLE_MAXNAMELEN-1] = '\0';
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
xt_compat_lock(NFPROTO_ARP); xt_compat_lock(NFPROTO_ARP);
#endif #endif
...@@ -808,7 +808,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -808,7 +808,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
if (!IS_ERR(t)) { if (!IS_ERR(t)) {
struct arpt_getinfo info; struct arpt_getinfo info;
const struct xt_table_info *private = t->private; const struct xt_table_info *private = t->private;
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct xt_table_info tmp; struct xt_table_info tmp;
if (in_compat_syscall()) { if (in_compat_syscall()) {
...@@ -835,7 +835,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -835,7 +835,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
module_put(t->me); module_put(t->me);
} else } else
ret = PTR_ERR(t); ret = PTR_ERR(t);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
xt_compat_unlock(NFPROTO_ARP); xt_compat_unlock(NFPROTO_ARP);
#endif #endif
...@@ -1044,7 +1044,7 @@ static int do_add_counters(struct net *net, sockptr_t arg, unsigned int len) ...@@ -1044,7 +1044,7 @@ static int do_add_counters(struct net *net, sockptr_t arg, unsigned int len)
return ret; return ret;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct compat_arpt_replace { struct compat_arpt_replace {
char name[XT_TABLE_MAXNAMELEN]; char name[XT_TABLE_MAXNAMELEN];
u32 valid_hooks; u32 valid_hooks;
...@@ -1412,7 +1412,7 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, sockptr_t arg, ...@@ -1412,7 +1412,7 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
switch (cmd) { switch (cmd) {
case ARPT_SO_SET_REPLACE: case ARPT_SO_SET_REPLACE:
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
ret = compat_do_replace(sock_net(sk), arg, len); ret = compat_do_replace(sock_net(sk), arg, len);
else else
...@@ -1444,7 +1444,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len ...@@ -1444,7 +1444,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
break; break;
case ARPT_SO_GET_ENTRIES: case ARPT_SO_GET_ENTRIES:
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
ret = compat_get_entries(sock_net(sk), user, len); ret = compat_get_entries(sock_net(sk), user, len);
else else
...@@ -1580,7 +1580,7 @@ static struct xt_target arpt_builtin_tg[] __read_mostly = { ...@@ -1580,7 +1580,7 @@ static struct xt_target arpt_builtin_tg[] __read_mostly = {
.name = XT_STANDARD_TARGET, .name = XT_STANDARD_TARGET,
.targetsize = sizeof(int), .targetsize = sizeof(int),
.family = NFPROTO_ARP, .family = NFPROTO_ARP,
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(compat_int_t), .compatsize = sizeof(compat_int_t),
.compat_from_user = compat_standard_from_user, .compat_from_user = compat_standard_from_user,
.compat_to_user = compat_standard_to_user, .compat_to_user = compat_standard_to_user,
......
...@@ -868,7 +868,7 @@ copy_entries_to_user(unsigned int total_size, ...@@ -868,7 +868,7 @@ copy_entries_to_user(unsigned int total_size,
return ret; return ret;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
static void compat_standard_from_user(void *dst, const void *src) static void compat_standard_from_user(void *dst, const void *src)
{ {
int v = *(compat_int_t *)src; int v = *(compat_int_t *)src;
...@@ -957,7 +957,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -957,7 +957,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
return -EFAULT; return -EFAULT;
name[XT_TABLE_MAXNAMELEN-1] = '\0'; name[XT_TABLE_MAXNAMELEN-1] = '\0';
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
xt_compat_lock(AF_INET); xt_compat_lock(AF_INET);
#endif #endif
...@@ -965,7 +965,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -965,7 +965,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
if (!IS_ERR(t)) { if (!IS_ERR(t)) {
struct ipt_getinfo info; struct ipt_getinfo info;
const struct xt_table_info *private = t->private; const struct xt_table_info *private = t->private;
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct xt_table_info tmp; struct xt_table_info tmp;
if (in_compat_syscall()) { if (in_compat_syscall()) {
...@@ -993,7 +993,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -993,7 +993,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
module_put(t->me); module_put(t->me);
} else } else
ret = PTR_ERR(t); ret = PTR_ERR(t);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
xt_compat_unlock(AF_INET); xt_compat_unlock(AF_INET);
#endif #endif
...@@ -1199,7 +1199,7 @@ do_add_counters(struct net *net, sockptr_t arg, unsigned int len) ...@@ -1199,7 +1199,7 @@ do_add_counters(struct net *net, sockptr_t arg, unsigned int len)
return ret; return ret;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct compat_ipt_replace { struct compat_ipt_replace {
char name[XT_TABLE_MAXNAMELEN]; char name[XT_TABLE_MAXNAMELEN];
u32 valid_hooks; u32 valid_hooks;
...@@ -1621,7 +1621,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, sockptr_t arg, unsigned int len) ...@@ -1621,7 +1621,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, sockptr_t arg, unsigned int len)
switch (cmd) { switch (cmd) {
case IPT_SO_SET_REPLACE: case IPT_SO_SET_REPLACE:
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
ret = compat_do_replace(sock_net(sk), arg, len); ret = compat_do_replace(sock_net(sk), arg, len);
else else
...@@ -1654,7 +1654,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ...@@ -1654,7 +1654,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
break; break;
case IPT_SO_GET_ENTRIES: case IPT_SO_GET_ENTRIES:
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
ret = compat_get_entries(sock_net(sk), user, len); ret = compat_get_entries(sock_net(sk), user, len);
else else
...@@ -1846,7 +1846,7 @@ static struct xt_target ipt_builtin_tg[] __read_mostly = { ...@@ -1846,7 +1846,7 @@ static struct xt_target ipt_builtin_tg[] __read_mostly = {
.name = XT_STANDARD_TARGET, .name = XT_STANDARD_TARGET,
.targetsize = sizeof(int), .targetsize = sizeof(int),
.family = NFPROTO_IPV4, .family = NFPROTO_IPV4,
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(compat_int_t), .compatsize = sizeof(compat_int_t),
.compat_from_user = compat_standard_from_user, .compat_from_user = compat_standard_from_user,
.compat_to_user = compat_standard_to_user, .compat_to_user = compat_standard_to_user,
......
...@@ -541,7 +541,7 @@ static void clusterip_tg_destroy(const struct xt_tgdtor_param *par) ...@@ -541,7 +541,7 @@ static void clusterip_tg_destroy(const struct xt_tgdtor_param *par)
nf_ct_netns_put(par->net, par->family); nf_ct_netns_put(par->net, par->family);
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct compat_ipt_clusterip_tgt_info struct compat_ipt_clusterip_tgt_info
{ {
u_int32_t flags; u_int32_t flags;
...@@ -553,7 +553,7 @@ struct compat_ipt_clusterip_tgt_info ...@@ -553,7 +553,7 @@ struct compat_ipt_clusterip_tgt_info
u_int32_t hash_initval; u_int32_t hash_initval;
compat_uptr_t config; compat_uptr_t config;
}; };
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_NETFILTER_XTABLES_COMPAT */
static struct xt_target clusterip_tg_reg __read_mostly = { static struct xt_target clusterip_tg_reg __read_mostly = {
.name = "CLUSTERIP", .name = "CLUSTERIP",
...@@ -563,9 +563,9 @@ static struct xt_target clusterip_tg_reg __read_mostly = { ...@@ -563,9 +563,9 @@ static struct xt_target clusterip_tg_reg __read_mostly = {
.destroy = clusterip_tg_destroy, .destroy = clusterip_tg_destroy,
.targetsize = sizeof(struct ipt_clusterip_tgt_info), .targetsize = sizeof(struct ipt_clusterip_tgt_info),
.usersize = offsetof(struct ipt_clusterip_tgt_info, config), .usersize = offsetof(struct ipt_clusterip_tgt_info, config),
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(struct compat_ipt_clusterip_tgt_info), .compatsize = sizeof(struct compat_ipt_clusterip_tgt_info),
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_NETFILTER_XTABLES_COMPAT */
.me = THIS_MODULE .me = THIS_MODULE
}; };
......
...@@ -884,7 +884,7 @@ copy_entries_to_user(unsigned int total_size, ...@@ -884,7 +884,7 @@ copy_entries_to_user(unsigned int total_size,
return ret; return ret;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
static void compat_standard_from_user(void *dst, const void *src) static void compat_standard_from_user(void *dst, const void *src)
{ {
int v = *(compat_int_t *)src; int v = *(compat_int_t *)src;
...@@ -973,7 +973,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -973,7 +973,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
return -EFAULT; return -EFAULT;
name[XT_TABLE_MAXNAMELEN-1] = '\0'; name[XT_TABLE_MAXNAMELEN-1] = '\0';
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
xt_compat_lock(AF_INET6); xt_compat_lock(AF_INET6);
#endif #endif
...@@ -981,7 +981,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -981,7 +981,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
if (!IS_ERR(t)) { if (!IS_ERR(t)) {
struct ip6t_getinfo info; struct ip6t_getinfo info;
const struct xt_table_info *private = t->private; const struct xt_table_info *private = t->private;
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct xt_table_info tmp; struct xt_table_info tmp;
if (in_compat_syscall()) { if (in_compat_syscall()) {
...@@ -1009,7 +1009,7 @@ static int get_info(struct net *net, void __user *user, const int *len) ...@@ -1009,7 +1009,7 @@ static int get_info(struct net *net, void __user *user, const int *len)
module_put(t->me); module_put(t->me);
} else } else
ret = PTR_ERR(t); ret = PTR_ERR(t);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
xt_compat_unlock(AF_INET6); xt_compat_unlock(AF_INET6);
#endif #endif
...@@ -1215,7 +1215,7 @@ do_add_counters(struct net *net, sockptr_t arg, unsigned int len) ...@@ -1215,7 +1215,7 @@ do_add_counters(struct net *net, sockptr_t arg, unsigned int len)
return ret; return ret;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct compat_ip6t_replace { struct compat_ip6t_replace {
char name[XT_TABLE_MAXNAMELEN]; char name[XT_TABLE_MAXNAMELEN];
u32 valid_hooks; u32 valid_hooks;
...@@ -1630,7 +1630,7 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, sockptr_t arg, unsigned int len) ...@@ -1630,7 +1630,7 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, sockptr_t arg, unsigned int len)
switch (cmd) { switch (cmd) {
case IP6T_SO_SET_REPLACE: case IP6T_SO_SET_REPLACE:
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
ret = compat_do_replace(sock_net(sk), arg, len); ret = compat_do_replace(sock_net(sk), arg, len);
else else
...@@ -1663,7 +1663,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ...@@ -1663,7 +1663,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
break; break;
case IP6T_SO_GET_ENTRIES: case IP6T_SO_GET_ENTRIES:
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) if (in_compat_syscall())
ret = compat_get_entries(sock_net(sk), user, len); ret = compat_get_entries(sock_net(sk), user, len);
else else
...@@ -1853,7 +1853,7 @@ static struct xt_target ip6t_builtin_tg[] __read_mostly = { ...@@ -1853,7 +1853,7 @@ static struct xt_target ip6t_builtin_tg[] __read_mostly = {
.name = XT_STANDARD_TARGET, .name = XT_STANDARD_TARGET,
.targetsize = sizeof(int), .targetsize = sizeof(int),
.family = NFPROTO_IPV6, .family = NFPROTO_IPV6,
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(compat_int_t), .compatsize = sizeof(compat_int_t),
.compat_from_user = compat_standard_from_user, .compat_from_user = compat_standard_from_user,
.compat_to_user = compat_standard_to_user, .compat_to_user = compat_standard_to_user,
......
...@@ -728,6 +728,16 @@ config NETFILTER_XTABLES ...@@ -728,6 +728,16 @@ config NETFILTER_XTABLES
if NETFILTER_XTABLES if NETFILTER_XTABLES
config NETFILTER_XTABLES_COMPAT
bool "Netfilter Xtables 32bit support"
depends on COMPAT
default y
help
This option provides a translation layer to run 32bit arp,ip(6),ebtables
binaries on 64bit kernels.
If unsure, say N.
comment "Xtables combined modules" comment "Xtables combined modules"
config NETFILTER_XT_MARK config NETFILTER_XT_MARK
......
...@@ -52,7 +52,7 @@ struct xt_af { ...@@ -52,7 +52,7 @@ struct xt_af {
struct mutex mutex; struct mutex mutex;
struct list_head match; struct list_head match;
struct list_head target; struct list_head target;
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct mutex compat_mutex; struct mutex compat_mutex;
struct compat_delta *compat_tab; struct compat_delta *compat_tab;
unsigned int number; /* number of slots in compat_tab[] */ unsigned int number; /* number of slots in compat_tab[] */
...@@ -647,7 +647,7 @@ static bool error_tg_ok(unsigned int usersize, unsigned int kernsize, ...@@ -647,7 +647,7 @@ static bool error_tg_ok(unsigned int usersize, unsigned int kernsize,
return usersize == kernsize && strnlen(msg, msglen) < msglen; return usersize == kernsize && strnlen(msg, msglen) < msglen;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta) int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta)
{ {
struct xt_af *xp = &xt[af]; struct xt_af *xp = &xt[af];
...@@ -850,7 +850,7 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems, ...@@ -850,7 +850,7 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
__alignof__(struct compat_xt_entry_match)); __alignof__(struct compat_xt_entry_match));
} }
EXPORT_SYMBOL(xt_compat_check_entry_offsets); EXPORT_SYMBOL(xt_compat_check_entry_offsets);
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_NETFILTER_XTABLES_COMPAT */
/** /**
* xt_check_entry_offsets - validate arp/ip/ip6t_entry * xt_check_entry_offsets - validate arp/ip/ip6t_entry
...@@ -868,7 +868,7 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets); ...@@ -868,7 +868,7 @@ EXPORT_SYMBOL(xt_compat_check_entry_offsets);
* match structures are aligned, and that the last structure ends where * match structures are aligned, and that the last structure ends where
* the target structure begins. * the target structure begins.
* *
* Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version. * Also see xt_compat_check_entry_offsets for CONFIG_NETFILTER_XTABLES_COMPAT version.
* *
* The arp/ip/ip6t_entry structure @base must have passed following tests: * The arp/ip/ip6t_entry structure @base must have passed following tests:
* - it must point to a valid memory location * - it must point to a valid memory location
...@@ -1059,7 +1059,7 @@ void *xt_copy_counters(sockptr_t arg, unsigned int len, ...@@ -1059,7 +1059,7 @@ void *xt_copy_counters(sockptr_t arg, unsigned int len,
void *mem; void *mem;
u64 size; u64 size;
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
if (in_compat_syscall()) { if (in_compat_syscall()) {
/* structures only differ in size due to alignment */ /* structures only differ in size due to alignment */
struct compat_xt_counters_info compat_tmp; struct compat_xt_counters_info compat_tmp;
...@@ -1106,7 +1106,7 @@ void *xt_copy_counters(sockptr_t arg, unsigned int len, ...@@ -1106,7 +1106,7 @@ void *xt_copy_counters(sockptr_t arg, unsigned int len,
} }
EXPORT_SYMBOL_GPL(xt_copy_counters); EXPORT_SYMBOL_GPL(xt_copy_counters);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
int xt_compat_target_offset(const struct xt_target *target) int xt_compat_target_offset(const struct xt_target *target)
{ {
u_int16_t csize = target->compatsize ? : target->targetsize; u_int16_t csize = target->compatsize ? : target->targetsize;
...@@ -1293,7 +1293,7 @@ void xt_table_unlock(struct xt_table *table) ...@@ -1293,7 +1293,7 @@ void xt_table_unlock(struct xt_table *table)
} }
EXPORT_SYMBOL_GPL(xt_table_unlock); EXPORT_SYMBOL_GPL(xt_table_unlock);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
void xt_compat_lock(u_int8_t af) void xt_compat_lock(u_int8_t af)
{ {
mutex_lock(&xt[af].compat_mutex); mutex_lock(&xt[af].compat_mutex);
...@@ -1931,7 +1931,7 @@ static int __init xt_init(void) ...@@ -1931,7 +1931,7 @@ static int __init xt_init(void)
for (i = 0; i < NFPROTO_NUMPROTO; i++) { for (i = 0; i < NFPROTO_NUMPROTO; i++) {
mutex_init(&xt[i].mutex); mutex_init(&xt[i].mutex);
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
mutex_init(&xt[i].compat_mutex); mutex_init(&xt[i].compat_mutex);
xt[i].compat_tab = NULL; xt[i].compat_tab = NULL;
#endif #endif
......
...@@ -134,7 +134,7 @@ static void limit_mt_destroy(const struct xt_mtdtor_param *par) ...@@ -134,7 +134,7 @@ static void limit_mt_destroy(const struct xt_mtdtor_param *par)
kfree(info->master); kfree(info->master);
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
struct compat_xt_rateinfo { struct compat_xt_rateinfo {
u_int32_t avg; u_int32_t avg;
u_int32_t burst; u_int32_t burst;
...@@ -176,7 +176,7 @@ static int limit_mt_compat_to_user(void __user *dst, const void *src) ...@@ -176,7 +176,7 @@ static int limit_mt_compat_to_user(void __user *dst, const void *src)
}; };
return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
} }
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_NETFILTER_XTABLES_COMPAT */
static struct xt_match limit_mt_reg __read_mostly = { static struct xt_match limit_mt_reg __read_mostly = {
.name = "limit", .name = "limit",
...@@ -186,7 +186,7 @@ static struct xt_match limit_mt_reg __read_mostly = { ...@@ -186,7 +186,7 @@ static struct xt_match limit_mt_reg __read_mostly = {
.checkentry = limit_mt_check, .checkentry = limit_mt_check,
.destroy = limit_mt_destroy, .destroy = limit_mt_destroy,
.matchsize = sizeof(struct xt_rateinfo), .matchsize = sizeof(struct xt_rateinfo),
#ifdef CONFIG_COMPAT #ifdef CONFIG_NETFILTER_XTABLES_COMPAT
.compatsize = sizeof(struct compat_xt_rateinfo), .compatsize = sizeof(struct compat_xt_rateinfo),
.compat_from_user = limit_mt_compat_from_user, .compat_from_user = limit_mt_compat_from_user,
.compat_to_user = limit_mt_compat_to_user, .compat_to_user = limit_mt_compat_to_user,
......
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