Commit d6da8381 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The follow patchset contains Netfilter fixes for your net tree,
they are:

1) Fix compilation warning in x_tables with clang due to useless
   redundant reassignment, from Colin Ian King.

2) Add bugtrap to net_exit to catch uninitialized lists, patch
   from Vasily Averin.

3) Fix out of bounds memory reads in H323 conntrack helper, this
   comes with an initial patch to remove replace the obscure
   CHECK_BOUND macro as a dependency. From Eric Sesterhenn.

4) Reduce retransmission timeout when window is 0 in TCP conntrack,
   from Florian Westphal.

6) ctnetlink clamp timeout to INT_MAX if timeout is too large,
   otherwise timeout wraps around and it results in killing the
   entry that is being added immediately.

7) Missing CAP_NET_ADMIN checks in cthelper and xt_osf, due to
   no netns support. From Kevin Cernekee.

8) Missing maximum number of instructions checks in xt_bpf, patch
   from Jann Horn.

9) With no CONFIG_PROC_FS ipt_CLUSTERIP compilation breaks,
   patch from Arnd Bergmann.

10) Missing netlink attribute policy in nftables exthdr, from
    Florian Westphal.

11) Enable conntrack with IPv6 MASQUERADE rules, as a357b3f8
    should have done in first place, from Konstantin Khlebnikov.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2a9ee696 23715275
...@@ -373,7 +373,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo, ...@@ -373,7 +373,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
if (!xt_find_jump_offset(offsets, newpos, if (!xt_find_jump_offset(offsets, newpos,
newinfo->number)) newinfo->number))
return 0; return 0;
e = entry0 + newpos;
} else { } else {
/* ... this is a fallthru */ /* ... this is a fallthru */
newpos = pos + e->next_offset; newpos = pos + e->next_offset;
......
...@@ -439,7 +439,6 @@ mark_source_chains(const struct xt_table_info *newinfo, ...@@ -439,7 +439,6 @@ mark_source_chains(const struct xt_table_info *newinfo,
if (!xt_find_jump_offset(offsets, newpos, if (!xt_find_jump_offset(offsets, newpos,
newinfo->number)) newinfo->number))
return 0; return 0;
e = entry0 + newpos;
} else { } else {
/* ... this is a fallthru */ /* ... this is a fallthru */
newpos = pos + e->next_offset; newpos = pos + e->next_offset;
......
...@@ -813,12 +813,13 @@ static int clusterip_net_init(struct net *net) ...@@ -813,12 +813,13 @@ static int clusterip_net_init(struct net *net)
static void clusterip_net_exit(struct net *net) static void clusterip_net_exit(struct net *net)
{ {
#ifdef CONFIG_PROC_FS
struct clusterip_net *cn = net_generic(net, clusterip_net_id); struct clusterip_net *cn = net_generic(net, clusterip_net_id);
#ifdef CONFIG_PROC_FS
proc_remove(cn->procdir); proc_remove(cn->procdir);
cn->procdir = NULL; cn->procdir = NULL;
#endif #endif
nf_unregister_net_hook(net, &cip_arp_ops); nf_unregister_net_hook(net, &cip_arp_ops);
WARN_ON_ONCE(!list_empty(&cn->configs));
} }
static struct pernet_operations clusterip_net_ops = { static struct pernet_operations clusterip_net_ops = {
......
...@@ -458,7 +458,6 @@ mark_source_chains(const struct xt_table_info *newinfo, ...@@ -458,7 +458,6 @@ mark_source_chains(const struct xt_table_info *newinfo,
if (!xt_find_jump_offset(offsets, newpos, if (!xt_find_jump_offset(offsets, newpos,
newinfo->number)) newinfo->number))
return 0; return 0;
e = entry0 + newpos;
} else { } else {
/* ... this is a fallthru */ /* ... this is a fallthru */
newpos = pos + e->next_offset; newpos = pos + e->next_offset;
......
...@@ -33,13 +33,19 @@ static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par) ...@@ -33,13 +33,19 @@ static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
if (range->flags & NF_NAT_RANGE_MAP_IPS) if (range->flags & NF_NAT_RANGE_MAP_IPS)
return -EINVAL; return -EINVAL;
return 0; return nf_ct_netns_get(par->net, par->family);
}
static void masquerade_tg6_destroy(const struct xt_tgdtor_param *par)
{
nf_ct_netns_put(par->net, par->family);
} }
static struct xt_target masquerade_tg6_reg __read_mostly = { static struct xt_target masquerade_tg6_reg __read_mostly = {
.name = "MASQUERADE", .name = "MASQUERADE",
.family = NFPROTO_IPV6, .family = NFPROTO_IPV6,
.checkentry = masquerade_tg6_checkentry, .checkentry = masquerade_tg6_checkentry,
.destroy = masquerade_tg6_destroy,
.target = masquerade_tg6, .target = masquerade_tg6,
.targetsize = sizeof(struct nf_nat_range), .targetsize = sizeof(struct nf_nat_range),
.table = "nat", .table = "nat",
......
This diff is collapsed.
...@@ -1565,9 +1565,11 @@ static int ctnetlink_change_helper(struct nf_conn *ct, ...@@ -1565,9 +1565,11 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
static int ctnetlink_change_timeout(struct nf_conn *ct, static int ctnetlink_change_timeout(struct nf_conn *ct,
const struct nlattr * const cda[]) const struct nlattr * const cda[])
{ {
u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); u64 timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
ct->timeout = nfct_time_stamp + timeout * HZ; if (timeout > INT_MAX)
timeout = INT_MAX;
ct->timeout = nfct_time_stamp + (u32)timeout;
if (test_bit(IPS_DYING_BIT, &ct->status)) if (test_bit(IPS_DYING_BIT, &ct->status))
return -ETIME; return -ETIME;
...@@ -1767,6 +1769,7 @@ ctnetlink_create_conntrack(struct net *net, ...@@ -1767,6 +1769,7 @@ ctnetlink_create_conntrack(struct net *net,
int err = -EINVAL; int err = -EINVAL;
struct nf_conntrack_helper *helper; struct nf_conntrack_helper *helper;
struct nf_conn_tstamp *tstamp; struct nf_conn_tstamp *tstamp;
u64 timeout;
ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC);
if (IS_ERR(ct)) if (IS_ERR(ct))
...@@ -1775,7 +1778,10 @@ ctnetlink_create_conntrack(struct net *net, ...@@ -1775,7 +1778,10 @@ ctnetlink_create_conntrack(struct net *net,
if (!cda[CTA_TIMEOUT]) if (!cda[CTA_TIMEOUT])
goto err1; goto err1;
ct->timeout = nfct_time_stamp + ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ; timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
if (timeout > INT_MAX)
timeout = INT_MAX;
ct->timeout = (u32)timeout + nfct_time_stamp;
rcu_read_lock(); rcu_read_lock();
if (cda[CTA_HELP]) { if (cda[CTA_HELP]) {
......
...@@ -1039,6 +1039,9 @@ static int tcp_packet(struct nf_conn *ct, ...@@ -1039,6 +1039,9 @@ static int tcp_packet(struct nf_conn *ct,
IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK]) timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
timeout = timeouts[TCP_CONNTRACK_UNACK]; timeout = timeouts[TCP_CONNTRACK_UNACK];
else if (ct->proto.tcp.last_win == 0 &&
timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS])
timeout = timeouts[TCP_CONNTRACK_RETRANS];
else else
timeout = timeouts[new_state]; timeout = timeouts[new_state];
spin_unlock_bh(&ct->lock); spin_unlock_bh(&ct->lock);
......
...@@ -5847,6 +5847,12 @@ static int __net_init nf_tables_init_net(struct net *net) ...@@ -5847,6 +5847,12 @@ static int __net_init nf_tables_init_net(struct net *net)
return 0; return 0;
} }
static void __net_exit nf_tables_exit_net(struct net *net)
{
WARN_ON_ONCE(!list_empty(&net->nft.af_info));
WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
}
int __nft_release_basechain(struct nft_ctx *ctx) int __nft_release_basechain(struct nft_ctx *ctx)
{ {
struct nft_rule *rule, *nr; struct nft_rule *rule, *nr;
...@@ -5917,6 +5923,7 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) ...@@ -5917,6 +5923,7 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
static struct pernet_operations nf_tables_net_ops = { static struct pernet_operations nf_tables_net_ops = {
.init = nf_tables_init_net, .init = nf_tables_init_net,
.exit = nf_tables_exit_net,
}; };
static int __init nf_tables_module_init(void) static int __init nf_tables_module_init(void)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/capability.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/sock.h> #include <net/sock.h>
...@@ -407,6 +408,9 @@ static int nfnl_cthelper_new(struct net *net, struct sock *nfnl, ...@@ -407,6 +408,9 @@ static int nfnl_cthelper_new(struct net *net, struct sock *nfnl,
struct nfnl_cthelper *nlcth; struct nfnl_cthelper *nlcth;
int ret = 0; int ret = 0;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE]) if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE])
return -EINVAL; return -EINVAL;
...@@ -611,6 +615,9 @@ static int nfnl_cthelper_get(struct net *net, struct sock *nfnl, ...@@ -611,6 +615,9 @@ static int nfnl_cthelper_get(struct net *net, struct sock *nfnl,
struct nfnl_cthelper *nlcth; struct nfnl_cthelper *nlcth;
bool tuple_set = false; bool tuple_set = false;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (nlh->nlmsg_flags & NLM_F_DUMP) { if (nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = { struct netlink_dump_control c = {
.dump = nfnl_cthelper_dump_table, .dump = nfnl_cthelper_dump_table,
...@@ -678,6 +685,9 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl, ...@@ -678,6 +685,9 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
struct nfnl_cthelper *nlcth, *n; struct nfnl_cthelper *nlcth, *n;
int j = 0, ret; int j = 0, ret;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (tb[NFCTH_NAME]) if (tb[NFCTH_NAME])
helper_name = nla_data(tb[NFCTH_NAME]); helper_name = nla_data(tb[NFCTH_NAME]);
......
...@@ -1093,10 +1093,15 @@ static int __net_init nfnl_log_net_init(struct net *net) ...@@ -1093,10 +1093,15 @@ static int __net_init nfnl_log_net_init(struct net *net)
static void __net_exit nfnl_log_net_exit(struct net *net) static void __net_exit nfnl_log_net_exit(struct net *net)
{ {
struct nfnl_log_net *log = nfnl_log_pernet(net);
unsigned int i;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter); remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
#endif #endif
nf_log_unset(net, &nfulnl_logger); nf_log_unset(net, &nfulnl_logger);
for (i = 0; i < INSTANCE_BUCKETS; i++)
WARN_ON_ONCE(!hlist_empty(&log->instance_table[i]));
} }
static struct pernet_operations nfnl_log_net_ops = { static struct pernet_operations nfnl_log_net_ops = {
......
...@@ -1512,10 +1512,15 @@ static int __net_init nfnl_queue_net_init(struct net *net) ...@@ -1512,10 +1512,15 @@ static int __net_init nfnl_queue_net_init(struct net *net)
static void __net_exit nfnl_queue_net_exit(struct net *net) static void __net_exit nfnl_queue_net_exit(struct net *net)
{ {
struct nfnl_queue_net *q = nfnl_queue_pernet(net);
unsigned int i;
nf_unregister_queue_handler(net); nf_unregister_queue_handler(net);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter); remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter);
#endif #endif
for (i = 0; i < INSTANCE_BUCKETS; i++)
WARN_ON_ONCE(!hlist_empty(&q->instance_table[i]));
} }
static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list) static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list)
......
...@@ -214,6 +214,8 @@ static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = { ...@@ -214,6 +214,8 @@ static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = {
[NFTA_EXTHDR_OFFSET] = { .type = NLA_U32 }, [NFTA_EXTHDR_OFFSET] = { .type = NLA_U32 },
[NFTA_EXTHDR_LEN] = { .type = NLA_U32 }, [NFTA_EXTHDR_LEN] = { .type = NLA_U32 },
[NFTA_EXTHDR_FLAGS] = { .type = NLA_U32 }, [NFTA_EXTHDR_FLAGS] = { .type = NLA_U32 },
[NFTA_EXTHDR_OP] = { .type = NLA_U32 },
[NFTA_EXTHDR_SREG] = { .type = NLA_U32 },
}; };
static int nft_exthdr_init(const struct nft_ctx *ctx, static int nft_exthdr_init(const struct nft_ctx *ctx,
......
...@@ -1729,8 +1729,17 @@ static int __net_init xt_net_init(struct net *net) ...@@ -1729,8 +1729,17 @@ static int __net_init xt_net_init(struct net *net)
return 0; return 0;
} }
static void __net_exit xt_net_exit(struct net *net)
{
int i;
for (i = 0; i < NFPROTO_NUMPROTO; i++)
WARN_ON_ONCE(!list_empty(&net->xt.tables[i]));
}
static struct pernet_operations xt_net_ops = { static struct pernet_operations xt_net_ops = {
.init = xt_net_init, .init = xt_net_init,
.exit = xt_net_exit,
}; };
static int __init xt_init(void) static int __init xt_init(void)
......
...@@ -27,6 +27,9 @@ static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len, ...@@ -27,6 +27,9 @@ static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len,
{ {
struct sock_fprog_kern program; struct sock_fprog_kern program;
if (len > XT_BPF_MAX_NUM_INSTR)
return -EINVAL;
program.len = len; program.len = len;
program.filter = insns; program.filter = insns;
...@@ -55,6 +58,9 @@ static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret) ...@@ -55,6 +58,9 @@ static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret)
mm_segment_t oldfs = get_fs(); mm_segment_t oldfs = get_fs();
int retval, fd; int retval, fd;
if (strnlen(path, XT_BPF_PATH_MAX) == XT_BPF_PATH_MAX)
return -EINVAL;
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
fd = bpf_obj_get_user(path, 0); fd = bpf_obj_get_user(path, 0);
set_fs(oldfs); set_fs(oldfs);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/capability.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/inetdevice.h> #include <linux/inetdevice.h>
#include <linux/ip.h> #include <linux/ip.h>
...@@ -70,6 +71,9 @@ static int xt_osf_add_callback(struct net *net, struct sock *ctnl, ...@@ -70,6 +71,9 @@ static int xt_osf_add_callback(struct net *net, struct sock *ctnl,
struct xt_osf_finger *kf = NULL, *sf; struct xt_osf_finger *kf = NULL, *sf;
int err = 0; int err = 0;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (!osf_attrs[OSF_ATTR_FINGER]) if (!osf_attrs[OSF_ATTR_FINGER])
return -EINVAL; return -EINVAL;
...@@ -115,6 +119,9 @@ static int xt_osf_remove_callback(struct net *net, struct sock *ctnl, ...@@ -115,6 +119,9 @@ static int xt_osf_remove_callback(struct net *net, struct sock *ctnl,
struct xt_osf_finger *sf; struct xt_osf_finger *sf;
int err = -ENOENT; int err = -ENOENT;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (!osf_attrs[OSF_ATTR_FINGER]) if (!osf_attrs[OSF_ATTR_FINGER])
return -EINVAL; return -EINVAL;
......
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