Skip to content

Commit 6fb721c

Browse files
committed
netfilter: nf_tables: honor NLM_F_CREATE and NLM_F_EXCL in event notification
Include the NLM_F_CREATE and NLM_F_EXCL flags in netlink event notifications, otherwise userspace cannot distiguish between create and add commands. Fixes: 9651851 ("netfilter: add nftables") Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 2c964c5 commit 6fb721c

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ struct nft_object *nft_obj_lookup(const struct net *net,
12021202

12031203
void nft_obj_notify(struct net *net, const struct nft_table *table,
12041204
struct nft_object *obj, u32 portid, u32 seq,
1205-
int event, int family, int report, gfp_t gfp);
1205+
int event, u16 flags, int family, int report, gfp_t gfp);
12061206

12071207
/**
12081208
* struct nft_object_type - stateful object type

net/netfilter/nf_tables_api.c

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
780780
{
781781
struct nftables_pernet *nft_net;
782782
struct sk_buff *skb;
783+
u16 flags = 0;
783784
int err;
784785

785786
if (!ctx->report &&
@@ -790,8 +791,11 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
790791
if (skb == NULL)
791792
goto err;
792793

794+
if (ctx->flags & (NLM_F_CREATE | NLM_F_EXCL))
795+
flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);
796+
793797
err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq,
794-
event, 0, ctx->family, ctx->table);
798+
event, flags, ctx->family, ctx->table);
795799
if (err < 0) {
796800
kfree_skb(skb);
797801
goto err;
@@ -1563,6 +1567,7 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
15631567
{
15641568
struct nftables_pernet *nft_net;
15651569
struct sk_buff *skb;
1570+
u16 flags = 0;
15661571
int err;
15671572

15681573
if (!ctx->report &&
@@ -1573,8 +1578,11 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
15731578
if (skb == NULL)
15741579
goto err;
15751580

1581+
if (ctx->flags & (NLM_F_CREATE | NLM_F_EXCL))
1582+
flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);
1583+
15761584
err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq,
1577-
event, 0, ctx->family, ctx->table,
1585+
event, flags, ctx->family, ctx->table,
15781586
ctx->chain);
15791587
if (err < 0) {
15801588
kfree_skb(skb);
@@ -2945,6 +2953,8 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
29452953
}
29462954
if (ctx->flags & (NLM_F_APPEND | NLM_F_REPLACE))
29472955
flags |= NLM_F_APPEND;
2956+
if (ctx->flags & (NLM_F_CREATE | NLM_F_EXCL))
2957+
flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);
29482958

29492959
err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
29502960
event, flags, ctx->family, ctx->table,
@@ -3957,8 +3967,9 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
39573967
gfp_t gfp_flags)
39583968
{
39593969
struct nftables_pernet *nft_net = nft_pernet(ctx->net);
3960-
struct sk_buff *skb;
39613970
u32 portid = ctx->portid;
3971+
struct sk_buff *skb;
3972+
u16 flags = 0;
39623973
int err;
39633974

39643975
if (!ctx->report &&
@@ -3969,7 +3980,10 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
39693980
if (skb == NULL)
39703981
goto err;
39713982

3972-
err = nf_tables_fill_set(skb, ctx, set, event, 0);
3983+
if (ctx->flags & (NLM_F_CREATE | NLM_F_EXCL))
3984+
flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);
3985+
3986+
err = nf_tables_fill_set(skb, ctx, set, event, flags);
39733987
if (err < 0) {
39743988
kfree_skb(skb);
39753989
goto err;
@@ -5245,12 +5259,13 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
52455259
static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
52465260
const struct nft_set *set,
52475261
const struct nft_set_elem *elem,
5248-
int event, u16 flags)
5262+
int event)
52495263
{
52505264
struct nftables_pernet *nft_net;
52515265
struct net *net = ctx->net;
52525266
u32 portid = ctx->portid;
52535267
struct sk_buff *skb;
5268+
u16 flags = 0;
52545269
int err;
52555270

52565271
if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
@@ -5260,6 +5275,9 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
52605275
if (skb == NULL)
52615276
goto err;
52625277

5278+
if (ctx->flags & (NLM_F_CREATE | NLM_F_EXCL))
5279+
flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);
5280+
52635281
err = nf_tables_fill_setelem_info(skb, ctx, 0, portid, event, flags,
52645282
set, elem);
52655283
if (err < 0) {
@@ -6935,7 +6953,7 @@ static int nf_tables_delobj(struct sk_buff *skb, const struct nfnl_info *info,
69356953

69366954
void nft_obj_notify(struct net *net, const struct nft_table *table,
69376955
struct nft_object *obj, u32 portid, u32 seq, int event,
6938-
int family, int report, gfp_t gfp)
6956+
u16 flags, int family, int report, gfp_t gfp)
69396957
{
69406958
struct nftables_pernet *nft_net = nft_pernet(net);
69416959
struct sk_buff *skb;
@@ -6960,8 +6978,9 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
69606978
if (skb == NULL)
69616979
goto err;
69626980

6963-
err = nf_tables_fill_obj_info(skb, net, portid, seq, event, 0, family,
6964-
table, obj, false);
6981+
err = nf_tables_fill_obj_info(skb, net, portid, seq, event,
6982+
flags & (NLM_F_CREATE | NLM_F_EXCL),
6983+
family, table, obj, false);
69656984
if (err < 0) {
69666985
kfree_skb(skb);
69676986
goto err;
@@ -6978,7 +6997,7 @@ static void nf_tables_obj_notify(const struct nft_ctx *ctx,
69786997
struct nft_object *obj, int event)
69796998
{
69806999
nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
6981-
ctx->family, ctx->report, GFP_KERNEL);
7000+
ctx->flags, ctx->family, ctx->report, GFP_KERNEL);
69827001
}
69837002

69847003
/*
@@ -7759,6 +7778,7 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
77597778
{
77607779
struct nftables_pernet *nft_net = nft_pernet(ctx->net);
77617780
struct sk_buff *skb;
7781+
u16 flags = 0;
77627782
int err;
77637783

77647784
if (!ctx->report &&
@@ -7769,8 +7789,11 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
77697789
if (skb == NULL)
77707790
goto err;
77717791

7792+
if (ctx->flags & (NLM_F_CREATE | NLM_F_EXCL))
7793+
flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);
7794+
77727795
err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid,
7773-
ctx->seq, event, 0,
7796+
ctx->seq, event, flags,
77747797
ctx->family, flowtable, hook_list);
77757798
if (err < 0) {
77767799
kfree_skb(skb);
@@ -8648,15 +8671,15 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
86488671
nft_setelem_activate(net, te->set, &te->elem);
86498672
nf_tables_setelem_notify(&trans->ctx, te->set,
86508673
&te->elem,
8651-
NFT_MSG_NEWSETELEM, 0);
8674+
NFT_MSG_NEWSETELEM);
86528675
nft_trans_destroy(trans);
86538676
break;
86548677
case NFT_MSG_DELSETELEM:
86558678
te = (struct nft_trans_elem *)trans->data;
86568679

86578680
nf_tables_setelem_notify(&trans->ctx, te->set,
86588681
&te->elem,
8659-
NFT_MSG_DELSETELEM, 0);
8682+
NFT_MSG_DELSETELEM);
86608683
nft_setelem_remove(net, te->set, &te->elem);
86618684
if (!nft_setelem_is_catchall(te->set, &te->elem)) {
86628685
atomic_dec(&te->set->nelems);

net/netfilter/nft_quota.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static void nft_quota_obj_eval(struct nft_object *obj,
6060
if (overquota &&
6161
!test_and_set_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags))
6262
nft_obj_notify(nft_net(pkt), obj->key.table, obj, 0, 0,
63-
NFT_MSG_NEWOBJ, nft_pf(pkt), 0, GFP_ATOMIC);
63+
NFT_MSG_NEWOBJ, 0, nft_pf(pkt), 0, GFP_ATOMIC);
6464
}
6565

6666
static int nft_quota_do_init(const struct nlattr * const tb[],

0 commit comments

Comments
 (0)