Commit 200bd566 authored by David S. Miller's avatar David S. Miller

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

Pablo Neira Ayusosays:

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

The following patchset contains Netfilter fixes for net:

1) Memleak in commit audit error path, from Dongliang Mu.

2) Avoid possible false sharing for flowtable timeout updates
   and nft_last use.

3) Adjust conntrack timestamp due to garbage collection delay,
   from Florian Westphal.

4) Fix nft_nat without layer 3 address for the inet family.

5) Fix compilation warning in nfnl_hook when ingress support
   is disabled, from Arnd Bergmann.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9986066d 217e26bd
......@@ -670,8 +670,13 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
return false;
tstamp = nf_conn_tstamp_find(ct);
if (tstamp && tstamp->stop == 0)
if (tstamp) {
s32 timeout = ct->timeout - nfct_time_stamp;
tstamp->stop = ktime_get_real_ns();
if (timeout < 0)
tstamp->stop -= jiffies_to_nsecs(-timeout);
}
if (nf_conntrack_event_report(IPCT_DESTROY, ct,
portid, report) < 0) {
......
......@@ -331,7 +331,11 @@ EXPORT_SYMBOL_GPL(flow_offload_add);
void flow_offload_refresh(struct nf_flowtable *flow_table,
struct flow_offload *flow)
{
flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
u32 timeout;
timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
if (READ_ONCE(flow->timeout) != timeout)
WRITE_ONCE(flow->timeout, timeout);
if (likely(!nf_flowtable_hw_offload(flow_table)))
return;
......
......@@ -8445,6 +8445,16 @@ static int nf_tables_commit_audit_alloc(struct list_head *adl,
return 0;
}
static void nf_tables_commit_audit_free(struct list_head *adl)
{
struct nft_audit_data *adp, *adn;
list_for_each_entry_safe(adp, adn, adl, list) {
list_del(&adp->list);
kfree(adp);
}
}
static void nf_tables_commit_audit_collect(struct list_head *adl,
struct nft_table *table, u32 op)
{
......@@ -8509,6 +8519,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
ret = nf_tables_commit_audit_alloc(&adl, trans->ctx.table);
if (ret) {
nf_tables_commit_chain_prepare_cancel(net);
nf_tables_commit_audit_free(&adl);
return ret;
}
if (trans->msg_type == NFT_MSG_NEWRULE ||
......@@ -8518,6 +8529,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
ret = nf_tables_commit_chain_prepare(net, chain);
if (ret < 0) {
nf_tables_commit_chain_prepare_cancel(net);
nf_tables_commit_audit_free(&adl);
return ret;
}
}
......
......@@ -174,7 +174,9 @@ static const struct nf_hook_entries *
nfnl_hook_entries_head(u8 pf, unsigned int hook, struct net *net, const char *dev)
{
const struct nf_hook_entries *hook_head = NULL;
#ifdef CONFIG_NETFILTER_INGRESS
struct net_device *netdev;
#endif
switch (pf) {
case NFPROTO_IPV4:
......
......@@ -48,24 +48,30 @@ static void nft_last_eval(const struct nft_expr *expr,
{
struct nft_last_priv *priv = nft_expr_priv(expr);
priv->last_jiffies = jiffies;
priv->last_set = 1;
if (READ_ONCE(priv->last_jiffies) != jiffies)
WRITE_ONCE(priv->last_jiffies, jiffies);
if (READ_ONCE(priv->last_set) == 0)
WRITE_ONCE(priv->last_set, 1);
}
static int nft_last_dump(struct sk_buff *skb, const struct nft_expr *expr)
{
struct nft_last_priv *priv = nft_expr_priv(expr);
unsigned long last_jiffies = READ_ONCE(priv->last_jiffies);
u32 last_set = READ_ONCE(priv->last_set);
__be64 msecs;
if (time_before(jiffies, priv->last_jiffies))
priv->last_set = 0;
if (time_before(jiffies, last_jiffies)) {
WRITE_ONCE(priv->last_set, 0);
last_set = 0;
}
if (priv->last_set)
msecs = nf_jiffies64_to_msecs(jiffies - priv->last_jiffies);
if (last_set)
msecs = nf_jiffies64_to_msecs(jiffies - last_jiffies);
else
msecs = 0;
if (nla_put_be32(skb, NFTA_LAST_SET, htonl(priv->last_set)) ||
if (nla_put_be32(skb, NFTA_LAST_SET, htonl(last_set)) ||
nla_put_be64(skb, NFTA_LAST_MSECS, msecs, NFTA_LAST_PAD))
goto nla_put_failure;
......
......@@ -201,7 +201,9 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
alen = sizeof_field(struct nf_nat_range, min_addr.ip6);
break;
default:
return -EAFNOSUPPORT;
if (tb[NFTA_NAT_REG_ADDR_MIN])
return -EAFNOSUPPORT;
break;
}
priv->family = family;
......
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