Skip to content

Commit 7c45d32

Browse files
committed
netfilter: nf_tables: Introduce NFT_MSG_GETSETELEM_RESET
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1925492 Upstream Status: commit 079cd63 commit 079cd63 Author: Phil Sutter <phil@nwl.cc> Date: Thu Jun 15 16:31:40 2023 +0200 netfilter: nf_tables: Introduce NFT_MSG_GETSETELEM_RESET Analogous to NFT_MSG_GETOBJ_RESET, but for set elements with a timeout or attached stateful expressions like counters or quotas - reset them all at once. Respect a per element timeout value if present to reset the 'expires' value to. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Phil Sutter <psutter@redhat.com>
1 parent 6f6e9c9 commit 7c45d32

File tree

2 files changed

+50
-20
lines changed

2 files changed

+50
-20
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ enum nft_verdicts {
105105
* @NFT_MSG_DESTROYSETELEM: destroy a set element (enum nft_set_elem_attributes)
106106
* @NFT_MSG_DESTROYOBJ: destroy a stateful object (enum nft_object_attributes)
107107
* @NFT_MSG_DESTROYFLOWTABLE: destroy flow table (enum nft_flowtable_attributes)
108+
* @NFT_MSG_GETSETELEM_RESET: get set elements and reset attached stateful expressions (enum nft_set_elem_attributes)
108109
*/
109110
enum nf_tables_msg_types {
110111
NFT_MSG_NEWTABLE,
@@ -140,6 +141,7 @@ enum nf_tables_msg_types {
140141
NFT_MSG_DESTROYSETELEM,
141142
NFT_MSG_DESTROYOBJ,
142143
NFT_MSG_DESTROYFLOWTABLE,
144+
NFT_MSG_GETSETELEM_RESET,
143145
NFT_MSG_MAX,
144146
};
145147

net/netfilter/nf_tables_api.c

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4977,7 +4977,8 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
49774977

49784978
static int nft_set_elem_expr_dump(struct sk_buff *skb,
49794979
const struct nft_set *set,
4980-
const struct nft_set_ext *ext)
4980+
const struct nft_set_ext *ext,
4981+
bool reset)
49814982
{
49824983
struct nft_set_elem_expr *elem_expr;
49834984
u32 size, num_exprs = 0;
@@ -4990,7 +4991,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
49904991

49914992
if (num_exprs == 1) {
49924993
expr = nft_setelem_expr_at(elem_expr, 0);
4993-
if (nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, expr, false) < 0)
4994+
if (nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, expr, reset) < 0)
49944995
return -1;
49954996

49964997
return 0;
@@ -5001,7 +5002,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
50015002

50025003
nft_setelem_expr_foreach(expr, elem_expr, size) {
50035004
expr = nft_setelem_expr_at(elem_expr, size);
5004-
if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr, false) < 0)
5005+
if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr, reset) < 0)
50055006
goto nla_put_failure;
50065007
}
50075008
nla_nest_end(skb, nest);
@@ -5014,11 +5015,13 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
50145015

50155016
static int nf_tables_fill_setelem(struct sk_buff *skb,
50165017
const struct nft_set *set,
5017-
const struct nft_set_elem *elem)
5018+
const struct nft_set_elem *elem,
5019+
bool reset)
50185020
{
50195021
const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
50205022
unsigned char *b = skb_tail_pointer(skb);
50215023
struct nlattr *nest;
5024+
u64 timeout = 0;
50225025

50235026
nest = nla_nest_start_noflag(skb, NFTA_LIST_ELEM);
50245027
if (nest == NULL)
@@ -5041,7 +5044,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
50415044
goto nla_put_failure;
50425045

50435046
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS) &&
5044-
nft_set_elem_expr_dump(skb, set, ext))
5047+
nft_set_elem_expr_dump(skb, set, ext, reset))
50455048
goto nla_put_failure;
50465049

50475050
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
@@ -5054,11 +5057,15 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
50545057
htonl(*nft_set_ext_flags(ext))))
50555058
goto nla_put_failure;
50565059

5057-
if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) &&
5058-
nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT,
5059-
nf_jiffies64_to_msecs(*nft_set_ext_timeout(ext)),
5060-
NFTA_SET_ELEM_PAD))
5061-
goto nla_put_failure;
5060+
if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT)) {
5061+
timeout = *nft_set_ext_timeout(ext);
5062+
if (nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT,
5063+
nf_jiffies64_to_msecs(timeout),
5064+
NFTA_SET_ELEM_PAD))
5065+
goto nla_put_failure;
5066+
} else if (set->flags & NFT_SET_TIMEOUT) {
5067+
timeout = READ_ONCE(set->timeout);
5068+
}
50625069

50635070
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
50645071
u64 expires, now = get_jiffies_64();
@@ -5073,6 +5080,9 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
50735080
nf_jiffies64_to_msecs(expires),
50745081
NFTA_SET_ELEM_PAD))
50755082
goto nla_put_failure;
5083+
5084+
if (reset)
5085+
*nft_set_ext_expiration(ext) = now + timeout;
50765086
}
50775087

50785088
if (nft_set_ext_exists(ext, NFT_SET_EXT_USERDATA)) {
@@ -5096,6 +5106,7 @@ struct nft_set_dump_args {
50965106
const struct netlink_callback *cb;
50975107
struct nft_set_iter iter;
50985108
struct sk_buff *skb;
5109+
bool reset;
50995110
};
51005111

51015112
static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
@@ -5106,7 +5117,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
51065117
struct nft_set_dump_args *args;
51075118

51085119
args = container_of(iter, struct nft_set_dump_args, iter);
5109-
return nf_tables_fill_setelem(args->skb, set, elem);
5120+
return nf_tables_fill_setelem(args->skb, set, elem, args->reset);
51105121
}
51115122

51125123
struct nft_set_dump_ctx {
@@ -5115,7 +5126,7 @@ struct nft_set_dump_ctx {
51155126
};
51165127

51175128
static int nft_set_catchall_dump(struct net *net, struct sk_buff *skb,
5118-
const struct nft_set *set)
5129+
const struct nft_set *set, bool reset)
51195130
{
51205131
struct nft_set_elem_catchall *catchall;
51215132
u8 genmask = nft_genmask_cur(net);
@@ -5130,7 +5141,7 @@ static int nft_set_catchall_dump(struct net *net, struct sk_buff *skb,
51305141
continue;
51315142

51325143
elem.priv = catchall->elem;
5133-
ret = nf_tables_fill_setelem(skb, set, &elem);
5144+
ret = nf_tables_fill_setelem(skb, set, &elem, reset);
51345145
break;
51355146
}
51365147

@@ -5148,6 +5159,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
51485159
bool set_found = false;
51495160
struct nlmsghdr *nlh;
51505161
struct nlattr *nest;
5162+
bool reset = false;
51515163
u32 portid, seq;
51525164
int event;
51535165

@@ -5195,8 +5207,12 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
51955207
if (nest == NULL)
51965208
goto nla_put_failure;
51975209

5210+
if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETSETELEM_RESET)
5211+
reset = true;
5212+
51985213
args.cb = cb;
51995214
args.skb = skb;
5215+
args.reset = reset;
52005216
args.iter.genmask = nft_genmask_cur(net);
52015217
args.iter.skip = cb->args[0];
52025218
args.iter.count = 0;
@@ -5205,7 +5221,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
52055221
set->ops->walk(&dump_ctx->ctx, set, &args.iter);
52065222

52075223
if (!args.iter.err && args.iter.count == cb->args[0])
5208-
args.iter.err = nft_set_catchall_dump(net, skb, set);
5224+
args.iter.err = nft_set_catchall_dump(net, skb, set, reset);
52095225
rcu_read_unlock();
52105226

52115227
nla_nest_end(skb, nest);
@@ -5243,7 +5259,8 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
52435259
const struct nft_ctx *ctx, u32 seq,
52445260
u32 portid, int event, u16 flags,
52455261
const struct nft_set *set,
5246-
const struct nft_set_elem *elem)
5262+
const struct nft_set_elem *elem,
5263+
bool reset)
52475264
{
52485265
struct nlmsghdr *nlh;
52495266
struct nlattr *nest;
@@ -5264,7 +5281,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
52645281
if (nest == NULL)
52655282
goto nla_put_failure;
52665283

5267-
err = nf_tables_fill_setelem(skb, set, elem);
5284+
err = nf_tables_fill_setelem(skb, set, elem, reset);
52685285
if (err < 0)
52695286
goto nla_put_failure;
52705287

@@ -5384,7 +5401,7 @@ static int nft_setelem_get(struct nft_ctx *ctx, struct nft_set *set,
53845401
}
53855402

53865403
static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5387-
const struct nlattr *attr)
5404+
const struct nlattr *attr, bool reset)
53885405
{
53895406
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
53905407
struct nft_set_elem elem;
@@ -5428,7 +5445,8 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
54285445
return err;
54295446

54305447
err = nf_tables_fill_setelem_info(skb, ctx, ctx->seq, ctx->portid,
5431-
NFT_MSG_NEWSETELEM, 0, set, &elem);
5448+
NFT_MSG_NEWSETELEM, 0, set, &elem,
5449+
reset);
54325450
if (err < 0)
54335451
goto err_fill_setelem;
54345452

@@ -5452,6 +5470,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
54525470
struct nft_set *set;
54535471
struct nlattr *attr;
54545472
struct nft_ctx ctx;
5473+
bool reset = false;
54555474
int rem, err = 0;
54565475

54575476
table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family,
@@ -5486,8 +5505,11 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
54865505
if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
54875506
return -EINVAL;
54885507

5508+
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETSETELEM_RESET)
5509+
reset = true;
5510+
54895511
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
5490-
err = nft_get_set_elem(&ctx, set, attr);
5512+
err = nft_get_set_elem(&ctx, set, attr, reset);
54915513
if (err < 0) {
54925514
NL_SET_BAD_ATTR(extack, attr);
54935515
break;
@@ -5520,7 +5542,7 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
55205542
flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);
55215543

55225544
err = nf_tables_fill_setelem_info(skb, ctx, 0, portid, event, flags,
5523-
set, elem);
5545+
set, elem, false);
55245546
if (err < 0) {
55255547
kfree_skb(skb);
55265548
goto err;
@@ -8396,6 +8418,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
83968418
.attr_count = NFTA_SET_ELEM_LIST_MAX,
83978419
.policy = nft_set_elem_list_policy,
83988420
},
8421+
[NFT_MSG_GETSETELEM_RESET] = {
8422+
.call = nf_tables_getsetelem,
8423+
.type = NFNL_CB_RCU,
8424+
.attr_count = NFTA_SET_ELEM_LIST_MAX,
8425+
.policy = nft_set_elem_list_policy,
8426+
},
83998427
[NFT_MSG_DELSETELEM] = {
84008428
.call = nf_tables_delsetelem,
84018429
.type = NFNL_CB_BATCH,

0 commit comments

Comments
 (0)