Skip to content

Commit

Permalink
Merge tag 'nf-next-24-05-12' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/netfilter/nf-next

Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

The following patchset contains Netfilter updates for net-next:

Patch #1 skips transaction if object type provides no .update interface.

Patch #2 skips NETDEV_CHANGENAME which is unused.

Patch #3 enables conntrack to handle Multicast Router Advertisements and
	 Multicast Router Solicitations from the Multicast Router Discovery
	 protocol (RFC4286) as untracked opposed to invalid packets.
	 From Linus Luessing.

Patch #4 updates DCCP conntracker to mark invalid as invalid, instead of
	 dropping them, from Jason Xing.

Patch #5 uses NF_DROP instead of -NF_DROP since NF_DROP is 0,
	 also from Jason.

Patch #6 removes reference in netfilter's sysctl documentation on pickup
	 entries which were already removed by Florian Westphal.

Patch #7 removes check for IPS_OFFLOAD flag to disable early drop which
	 allows to evict entries from the conntrack table,
	 also from Florian.

Patches #8 to #16 updates nf_tables pipapo set backend to allocate
	 the datastructure copy on-demand from preparation phase,
	 to better deal with OOM situations where .commit step is too late
	 to fail. Series from Florian Westphal.

Patch #17 adds a selftest with packetdrill to cover conntrack TCP state
	 transitions, also from Florian.

Patch #18 use GFP_KERNEL to clone elements from control plane to avoid
	 quick atomic reserves exhaustion with large sets, reporter refers
	 to million entries magnitude.

* tag 'nf-next-24-05-12' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
  netfilter: nf_tables: allow clone callbacks to sleep
  selftests: netfilter: add packetdrill based conntrack tests
  netfilter: nft_set_pipapo: remove dirty flag
  netfilter: nft_set_pipapo: move cloning of match info to insert/removal path
  netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone
  netfilter: nft_set_pipapo: merge deactivate helper into caller
  netfilter: nft_set_pipapo: prepare walk function for on-demand clone
  netfilter: nft_set_pipapo: prepare destroy function for on-demand clone
  netfilter: nft_set_pipapo: make pipapo_clone helper return NULL
  netfilter: nft_set_pipapo: move prove_locking helper around
  netfilter: conntrack: remove flowtable early-drop test
  netfilter: conntrack: documentation: remove reference to non-existent sysctl
  netfilter: use NF_DROP instead of -NF_DROP
  netfilter: conntrack: dccp: try not to drop skb in conntrack
  netfilter: conntrack: fix ct-state for ICMPv6 Multicast Router Discovery
  netfilter: nf_tables: remove NETDEV_CHANGENAME from netdev chain event handler
  netfilter: nf_tables: skip transaction if update object is not implemented
====================

Link: https://lore.kernel.org/r/20240512161436.168973-1-pablo@netfilter.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
kuba-moo committed May 13, 2024
2 parents cddd2dc + fa23e0d commit c85e41b
Show file tree
Hide file tree
Showing 28 changed files with 639 additions and 175 deletions.
4 changes: 2 additions & 2 deletions Documentation/networking/nf_conntrack-sysctl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,11 @@ nf_flowtable_tcp_timeout - INTEGER (seconds)

Control offload timeout for tcp connections.
TCP connections may be offloaded from nf conntrack to nf flow table.
Once aged, the connection is returned to nf conntrack with tcp pickup timeout.
Once aged, the connection is returned to nf conntrack.

nf_flowtable_udp_timeout - INTEGER (seconds)
default 30

Control offload timeout for udp connections.
UDP connections may be offloaded from nf conntrack to nf flow table.
Once aged, the connection is returned to nf conntrack with udp pickup timeout.
Once aged, the connection is returned to nf conntrack.
4 changes: 2 additions & 2 deletions include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ struct nft_expr_info;

int nft_expr_inner_parse(const struct nft_ctx *ctx, const struct nlattr *nla,
struct nft_expr_info *info);
int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src);
int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src, gfp_t gfp);
void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
const struct nft_expr *expr, bool reset);
Expand Down Expand Up @@ -935,7 +935,7 @@ struct nft_expr_ops {
struct nft_regs *regs,
const struct nft_pktinfo *pkt);
int (*clone)(struct nft_expr *dst,
const struct nft_expr *src);
const struct nft_expr *src, gfp_t gfp);
unsigned int size;

int (*init)(const struct nft_ctx *ctx,
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/icmpv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct icmp6hdr {
#define ICMPV6_MOBILE_PREFIX_ADV 147

#define ICMPV6_MRDISC_ADV 151
#define ICMPV6_MRDISC_SOL 152

#define ICMPV6_MSG_MAX 255

Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/netfilter/iptable_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static int iptable_filter_table_init(struct net *net)
return -ENOMEM;
/* Entry 1 is the FORWARD hook */
((struct ipt_standard *)repl->entries)[1].target.verdict =
forward ? -NF_ACCEPT - 1 : -NF_DROP - 1;
forward ? -NF_ACCEPT - 1 : NF_DROP - 1;

err = ipt_register_table(net, &packet_filter, repl, filter_ops);
kfree(repl);
Expand Down
2 changes: 1 addition & 1 deletion net/ipv6/netfilter/ip6table_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static int ip6table_filter_table_init(struct net *net)
return -ENOMEM;
/* Entry 1 is the FORWARD hook */
((struct ip6t_standard *)repl->entries)[1].target.verdict =
forward ? -NF_ACCEPT - 1 : -NF_DROP - 1;
forward ? -NF_ACCEPT - 1 : NF_DROP - 1;

err = ip6t_register_table(net, &packet_filter, repl, filter_ops);
kfree(repl);
Expand Down
4 changes: 1 addition & 3 deletions net/netfilter/nf_conntrack_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1440,8 +1440,6 @@ static bool gc_worker_can_early_drop(const struct nf_conn *ct)
const struct nf_conntrack_l4proto *l4proto;
u8 protonum = nf_ct_protonum(ct);

if (test_bit(IPS_OFFLOAD_BIT, &ct->status) && protonum != IPPROTO_UDP)
return false;
if (!test_bit(IPS_ASSURED_BIT, &ct->status))
return true;

Expand Down Expand Up @@ -2024,7 +2022,7 @@ nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state)
goto repeat;

NF_CT_STAT_INC_ATOMIC(state->net, invalid);
if (ret == -NF_DROP)
if (ret == NF_DROP)
NF_CT_STAT_INC_ATOMIC(state->net, drop);

ret = -ret;
Expand Down
4 changes: 2 additions & 2 deletions net/netfilter/nf_conntrack_proto_dccp.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,15 +525,15 @@ int nf_conntrack_dccp_packet(struct nf_conn *ct, struct sk_buff *skb,

dh = skb_header_pointer(skb, dataoff, sizeof(*dh), &_dh.dh);
if (!dh)
return NF_DROP;
return -NF_ACCEPT;

if (dccp_error(dh, skb, dataoff, state))
return -NF_ACCEPT;

/* pull again, including possible 48 bit sequences and subtype header */
dh = dccp_header_pointer(skb, dataoff, dh, &_dh);
if (!dh)
return NF_DROP;
return -NF_ACCEPT;

type = dh->dccph_type;
if (!nf_ct_is_confirmed(ct) && !dccp_new(ct, skb, dh, state))
Expand Down
4 changes: 3 additions & 1 deletion net/netfilter/nf_conntrack_proto_icmpv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ static const u_int8_t noct_valid_new[] = {
[NDISC_ROUTER_ADVERTISEMENT - 130] = 1,
[NDISC_NEIGHBOUR_SOLICITATION - 130] = 1,
[NDISC_NEIGHBOUR_ADVERTISEMENT - 130] = 1,
[ICMPV6_MLD2_REPORT - 130] = 1
[ICMPV6_MLD2_REPORT - 130] = 1,
[ICMPV6_MRDISC_ADV - 130] = 1,
[ICMPV6_MRDISC_SOL - 130] = 1
};

bool nf_conntrack_invert_icmpv6_tuple(struct nf_conntrack_tuple *tuple,
Expand Down
16 changes: 10 additions & 6 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -3333,15 +3333,15 @@ static struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
return ERR_PTR(err);
}

int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src)
int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src, gfp_t gfp)
{
int err;

if (WARN_ON_ONCE(!src->ops->clone))
return -EINVAL;

dst->ops = src->ops;
err = src->ops->clone(dst, src);
err = src->ops->clone(dst, src, gfp);
if (err < 0)
return err;

Expand Down Expand Up @@ -6525,7 +6525,7 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
if (!expr)
goto err_expr;

err = nft_expr_clone(expr, set->exprs[i]);
err = nft_expr_clone(expr, set->exprs[i], GFP_KERNEL_ACCOUNT);
if (err < 0) {
kfree(expr);
goto err_expr;
Expand Down Expand Up @@ -6564,7 +6564,7 @@ static int nft_set_elem_expr_setup(struct nft_ctx *ctx,

for (i = 0; i < num_exprs; i++) {
expr = nft_setelem_expr_at(elem_expr, elem_expr->size);
err = nft_expr_clone(expr, expr_array[i]);
err = nft_expr_clone(expr, expr_array[i], GFP_KERNEL_ACCOUNT);
if (err < 0)
goto err_elem_expr_setup;

Expand Down Expand Up @@ -7776,6 +7776,9 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
if (WARN_ON_ONCE(!type))
return -ENOENT;

if (!obj->ops->update)
return 0;

nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);

return nf_tables_updobj(&ctx, type, nla[NFTA_OBJ_DATA], obj);
Expand Down Expand Up @@ -9467,9 +9470,10 @@ static void nft_obj_commit_update(struct nft_trans *trans)
obj = nft_trans_obj(trans);
newobj = nft_trans_obj_newobj(trans);

if (obj->ops->update)
obj->ops->update(obj, newobj);
if (WARN_ON_ONCE(!obj->ops->update))
return;

obj->ops->update(obj, newobj);
nft_obj_destroy(&trans->ctx, newobj);
}

Expand Down
6 changes: 1 addition & 5 deletions net/netfilter/nft_chain_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,6 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
struct nft_hook *hook, *found = NULL;
int n = 0;

if (event != NETDEV_UNREGISTER)
return;

list_for_each_entry(hook, &basechain->hook_list, list) {
if (hook->ops.dev == dev)
found = hook;
Expand Down Expand Up @@ -367,8 +364,7 @@ static int nf_tables_netdev_event(struct notifier_block *this,
.net = dev_net(dev),
};

if (event != NETDEV_UNREGISTER &&
event != NETDEV_CHANGENAME)
if (event != NETDEV_UNREGISTER)
return NOTIFY_DONE;

nft_net = nft_pernet(ctx.net);
Expand Down
4 changes: 2 additions & 2 deletions net/netfilter/nft_connlimit.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,12 @@ static void nft_connlimit_destroy(const struct nft_ctx *ctx,
nft_connlimit_do_destroy(ctx, priv);
}

static int nft_connlimit_clone(struct nft_expr *dst, const struct nft_expr *src)
static int nft_connlimit_clone(struct nft_expr *dst, const struct nft_expr *src, gfp_t gfp)
{
struct nft_connlimit *priv_dst = nft_expr_priv(dst);
struct nft_connlimit *priv_src = nft_expr_priv(src);

priv_dst->list = kmalloc(sizeof(*priv_dst->list), GFP_ATOMIC);
priv_dst->list = kmalloc(sizeof(*priv_dst->list), gfp);
if (!priv_dst->list)
return -ENOMEM;

Expand Down
4 changes: 2 additions & 2 deletions net/netfilter/nft_counter.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ static void nft_counter_destroy(const struct nft_ctx *ctx,
nft_counter_do_destroy(priv);
}

static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src)
static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src, gfp_t gfp)
{
struct nft_counter_percpu_priv *priv = nft_expr_priv(src);
struct nft_counter_percpu_priv *priv_clone = nft_expr_priv(dst);
Expand All @@ -236,7 +236,7 @@ static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src)

nft_counter_fetch(priv, &total);

cpu_stats = alloc_percpu_gfp(struct nft_counter, GFP_ATOMIC);
cpu_stats = alloc_percpu_gfp(struct nft_counter, gfp);
if (cpu_stats == NULL)
return -ENOMEM;

Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/nft_dynset.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv,

for (i = 0; i < priv->num_exprs; i++) {
expr = nft_setelem_expr_at(elem_expr, elem_expr->size);
if (nft_expr_clone(expr, priv->expr_array[i]) < 0)
if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0)
return -1;

elem_expr->size += priv->expr_array[i]->ops->size;
Expand Down
4 changes: 2 additions & 2 deletions net/netfilter/nft_last.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ static void nft_last_destroy(const struct nft_ctx *ctx,
kfree(priv->last);
}

static int nft_last_clone(struct nft_expr *dst, const struct nft_expr *src)
static int nft_last_clone(struct nft_expr *dst, const struct nft_expr *src, gfp_t gfp)
{
struct nft_last_priv *priv_dst = nft_expr_priv(dst);
struct nft_last_priv *priv_src = nft_expr_priv(src);

priv_dst->last = kzalloc(sizeof(*priv_dst->last), GFP_ATOMIC);
priv_dst->last = kzalloc(sizeof(*priv_dst->last), gfp);
if (!priv_dst->last)
return -ENOMEM;

Expand Down
14 changes: 8 additions & 6 deletions net/netfilter/nft_limit.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,15 @@ static void nft_limit_destroy(const struct nft_ctx *ctx,
}

static int nft_limit_clone(struct nft_limit_priv *priv_dst,
const struct nft_limit_priv *priv_src)
const struct nft_limit_priv *priv_src, gfp_t gfp)
{
priv_dst->tokens_max = priv_src->tokens_max;
priv_dst->rate = priv_src->rate;
priv_dst->nsecs = priv_src->nsecs;
priv_dst->burst = priv_src->burst;
priv_dst->invert = priv_src->invert;

priv_dst->limit = kmalloc(sizeof(*priv_dst->limit), GFP_ATOMIC);
priv_dst->limit = kmalloc(sizeof(*priv_dst->limit), gfp);
if (!priv_dst->limit)
return -ENOMEM;

Expand Down Expand Up @@ -223,14 +223,15 @@ static void nft_limit_pkts_destroy(const struct nft_ctx *ctx,
nft_limit_destroy(ctx, &priv->limit);
}

static int nft_limit_pkts_clone(struct nft_expr *dst, const struct nft_expr *src)
static int nft_limit_pkts_clone(struct nft_expr *dst, const struct nft_expr *src,
gfp_t gfp)
{
struct nft_limit_priv_pkts *priv_dst = nft_expr_priv(dst);
struct nft_limit_priv_pkts *priv_src = nft_expr_priv(src);

priv_dst->cost = priv_src->cost;

return nft_limit_clone(&priv_dst->limit, &priv_src->limit);
return nft_limit_clone(&priv_dst->limit, &priv_src->limit, gfp);
}

static struct nft_expr_type nft_limit_type;
Expand Down Expand Up @@ -281,12 +282,13 @@ static void nft_limit_bytes_destroy(const struct nft_ctx *ctx,
nft_limit_destroy(ctx, priv);
}

static int nft_limit_bytes_clone(struct nft_expr *dst, const struct nft_expr *src)
static int nft_limit_bytes_clone(struct nft_expr *dst, const struct nft_expr *src,
gfp_t gfp)
{
struct nft_limit_priv *priv_dst = nft_expr_priv(dst);
struct nft_limit_priv *priv_src = nft_expr_priv(src);

return nft_limit_clone(priv_dst, priv_src);
return nft_limit_clone(priv_dst, priv_src, gfp);
}

static const struct nft_expr_ops nft_limit_bytes_ops = {
Expand Down
4 changes: 2 additions & 2 deletions net/netfilter/nft_quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,15 @@ static void nft_quota_destroy(const struct nft_ctx *ctx,
return nft_quota_do_destroy(ctx, priv);
}

static int nft_quota_clone(struct nft_expr *dst, const struct nft_expr *src)
static int nft_quota_clone(struct nft_expr *dst, const struct nft_expr *src, gfp_t gfp)
{
struct nft_quota *priv_dst = nft_expr_priv(dst);
struct nft_quota *priv_src = nft_expr_priv(src);

priv_dst->quota = priv_src->quota;
priv_dst->flags = priv_src->flags;

priv_dst->consumed = kmalloc(sizeof(*priv_dst->consumed), GFP_ATOMIC);
priv_dst->consumed = kmalloc(sizeof(*priv_dst->consumed), gfp);
if (!priv_dst->consumed)
return -ENOMEM;

Expand Down
Loading

0 comments on commit c85e41b

Please sign in to comment.