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) ...@@ -670,8 +670,13 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
return false; return false;
tstamp = nf_conn_tstamp_find(ct); 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(); tstamp->stop = ktime_get_real_ns();
if (timeout < 0)
tstamp->stop -= jiffies_to_nsecs(-timeout);
}
if (nf_conntrack_event_report(IPCT_DESTROY, ct, if (nf_conntrack_event_report(IPCT_DESTROY, ct,
portid, report) < 0) { portid, report) < 0) {
......
...@@ -331,7 +331,11 @@ EXPORT_SYMBOL_GPL(flow_offload_add); ...@@ -331,7 +331,11 @@ EXPORT_SYMBOL_GPL(flow_offload_add);
void flow_offload_refresh(struct nf_flowtable *flow_table, void flow_offload_refresh(struct nf_flowtable *flow_table,
struct flow_offload *flow) 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))) if (likely(!nf_flowtable_hw_offload(flow_table)))
return; return;
......
...@@ -8445,6 +8445,16 @@ static int nf_tables_commit_audit_alloc(struct list_head *adl, ...@@ -8445,6 +8445,16 @@ static int nf_tables_commit_audit_alloc(struct list_head *adl,
return 0; 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, static void nf_tables_commit_audit_collect(struct list_head *adl,
struct nft_table *table, u32 op) struct nft_table *table, u32 op)
{ {
...@@ -8509,6 +8519,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) ...@@ -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); ret = nf_tables_commit_audit_alloc(&adl, trans->ctx.table);
if (ret) { if (ret) {
nf_tables_commit_chain_prepare_cancel(net); nf_tables_commit_chain_prepare_cancel(net);
nf_tables_commit_audit_free(&adl);
return ret; return ret;
} }
if (trans->msg_type == NFT_MSG_NEWRULE || if (trans->msg_type == NFT_MSG_NEWRULE ||
...@@ -8518,6 +8529,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) ...@@ -8518,6 +8529,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
ret = nf_tables_commit_chain_prepare(net, chain); ret = nf_tables_commit_chain_prepare(net, chain);
if (ret < 0) { if (ret < 0) {
nf_tables_commit_chain_prepare_cancel(net); nf_tables_commit_chain_prepare_cancel(net);
nf_tables_commit_audit_free(&adl);
return ret; return ret;
} }
} }
......
...@@ -174,7 +174,9 @@ static const struct nf_hook_entries * ...@@ -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) nfnl_hook_entries_head(u8 pf, unsigned int hook, struct net *net, const char *dev)
{ {
const struct nf_hook_entries *hook_head = NULL; const struct nf_hook_entries *hook_head = NULL;
#ifdef CONFIG_NETFILTER_INGRESS
struct net_device *netdev; struct net_device *netdev;
#endif
switch (pf) { switch (pf) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
......
...@@ -48,24 +48,30 @@ static void nft_last_eval(const struct nft_expr *expr, ...@@ -48,24 +48,30 @@ static void nft_last_eval(const struct nft_expr *expr,
{ {
struct nft_last_priv *priv = nft_expr_priv(expr); struct nft_last_priv *priv = nft_expr_priv(expr);
priv->last_jiffies = jiffies; if (READ_ONCE(priv->last_jiffies) != jiffies)
priv->last_set = 1; 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) static int nft_last_dump(struct sk_buff *skb, const struct nft_expr *expr)
{ {
struct nft_last_priv *priv = nft_expr_priv(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; __be64 msecs;
if (time_before(jiffies, priv->last_jiffies)) if (time_before(jiffies, last_jiffies)) {
priv->last_set = 0; WRITE_ONCE(priv->last_set, 0);
last_set = 0;
}
if (priv->last_set) if (last_set)
msecs = nf_jiffies64_to_msecs(jiffies - priv->last_jiffies); msecs = nf_jiffies64_to_msecs(jiffies - last_jiffies);
else else
msecs = 0; 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)) nla_put_be64(skb, NFTA_LAST_MSECS, msecs, NFTA_LAST_PAD))
goto nla_put_failure; goto nla_put_failure;
......
...@@ -201,7 +201,9 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, ...@@ -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); alen = sizeof_field(struct nf_nat_range, min_addr.ip6);
break; break;
default: default:
return -EAFNOSUPPORT; if (tb[NFTA_NAT_REG_ADDR_MIN])
return -EAFNOSUPPORT;
break;
} }
priv->family = family; 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