@@ -465,26 +465,38 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx)
465
465
return 0 ;
466
466
}
467
467
468
- static int nft_trans_set_add (const struct nft_ctx * ctx , int msg_type ,
469
- struct nft_set * set )
468
+ static int __nft_trans_set_add (const struct nft_ctx * ctx , int msg_type ,
469
+ struct nft_set * set ,
470
+ const struct nft_set_desc * desc )
470
471
{
471
472
struct nft_trans * trans ;
472
473
473
474
trans = nft_trans_alloc (ctx , msg_type , sizeof (struct nft_trans_set ));
474
475
if (trans == NULL )
475
476
return - ENOMEM ;
476
477
477
- if (msg_type == NFT_MSG_NEWSET && ctx -> nla [NFTA_SET_ID ] != NULL ) {
478
+ if (msg_type == NFT_MSG_NEWSET && ctx -> nla [NFTA_SET_ID ] && ! desc ) {
478
479
nft_trans_set_id (trans ) =
479
480
ntohl (nla_get_be32 (ctx -> nla [NFTA_SET_ID ]));
480
481
nft_activate_next (ctx -> net , set );
481
482
}
482
483
nft_trans_set (trans ) = set ;
484
+ if (desc ) {
485
+ nft_trans_set_update (trans ) = true;
486
+ nft_trans_set_gc_int (trans ) = desc -> gc_int ;
487
+ nft_trans_set_timeout (trans ) = desc -> timeout ;
488
+ }
483
489
nft_trans_commit_list_add_tail (ctx -> net , trans );
484
490
485
491
return 0 ;
486
492
}
487
493
494
+ static int nft_trans_set_add (const struct nft_ctx * ctx , int msg_type ,
495
+ struct nft_set * set )
496
+ {
497
+ return __nft_trans_set_add (ctx , msg_type , set , NULL );
498
+ }
499
+
488
500
static int nft_delset (const struct nft_ctx * ctx , struct nft_set * set )
489
501
{
490
502
int err ;
@@ -4044,8 +4056,10 @@ static int nf_tables_fill_set_concat(struct sk_buff *skb,
4044
4056
static int nf_tables_fill_set (struct sk_buff * skb , const struct nft_ctx * ctx ,
4045
4057
const struct nft_set * set , u16 event , u16 flags )
4046
4058
{
4047
- struct nlmsghdr * nlh ;
4059
+ u64 timeout = READ_ONCE (set -> timeout );
4060
+ u32 gc_int = READ_ONCE (set -> gc_int );
4048
4061
u32 portid = ctx -> portid ;
4062
+ struct nlmsghdr * nlh ;
4049
4063
struct nlattr * nest ;
4050
4064
u32 seq = ctx -> seq ;
4051
4065
int i ;
@@ -4081,13 +4095,13 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
4081
4095
nla_put_be32 (skb , NFTA_SET_OBJ_TYPE , htonl (set -> objtype )))
4082
4096
goto nla_put_failure ;
4083
4097
4084
- if (set -> timeout &&
4098
+ if (timeout &&
4085
4099
nla_put_be64 (skb , NFTA_SET_TIMEOUT ,
4086
- nf_jiffies64_to_msecs (set -> timeout ),
4100
+ nf_jiffies64_to_msecs (timeout ),
4087
4101
NFTA_SET_PAD ))
4088
4102
goto nla_put_failure ;
4089
- if (set -> gc_int &&
4090
- nla_put_be32 (skb , NFTA_SET_GC_INTERVAL , htonl (set -> gc_int )))
4103
+ if (gc_int &&
4104
+ nla_put_be32 (skb , NFTA_SET_GC_INTERVAL , htonl (gc_int )))
4091
4105
goto nla_put_failure ;
4092
4106
4093
4107
if (set -> policy != NFT_SET_POL_PERFORMANCE ) {
@@ -4632,7 +4646,10 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
4632
4646
for (i = 0 ; i < num_exprs ; i ++ )
4633
4647
nft_expr_destroy (& ctx , exprs [i ]);
4634
4648
4635
- return err ;
4649
+ if (err < 0 )
4650
+ return err ;
4651
+
4652
+ return __nft_trans_set_add (& ctx , NFT_MSG_NEWSET , set , & desc );
4636
4653
}
4637
4654
4638
4655
if (!(info -> nlh -> nlmsg_flags & NLM_F_CREATE ))
@@ -6070,7 +6087,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
6070
6087
return err ;
6071
6088
} else if (set -> flags & NFT_SET_TIMEOUT &&
6072
6089
!(flags & NFT_SET_ELEM_INTERVAL_END )) {
6073
- timeout = set -> timeout ;
6090
+ timeout = READ_ONCE ( set -> timeout ) ;
6074
6091
}
6075
6092
6076
6093
expiration = 0 ;
@@ -6171,7 +6188,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
6171
6188
if (err < 0 )
6172
6189
goto err_parse_key_end ;
6173
6190
6174
- if (timeout != set -> timeout ) {
6191
+ if (timeout != READ_ONCE ( set -> timeout ) ) {
6175
6192
err = nft_set_ext_add (& tmpl , NFT_SET_EXT_TIMEOUT );
6176
6193
if (err < 0 )
6177
6194
goto err_parse_key_end ;
@@ -9093,14 +9110,20 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
9093
9110
nft_flow_rule_destroy (nft_trans_flow_rule (trans ));
9094
9111
break ;
9095
9112
case NFT_MSG_NEWSET :
9096
- nft_clear (net , nft_trans_set (trans ));
9097
- /* This avoids hitting -EBUSY when deleting the table
9098
- * from the transaction.
9099
- */
9100
- if (nft_set_is_anonymous (nft_trans_set (trans )) &&
9101
- !list_empty (& nft_trans_set (trans )-> bindings ))
9102
- trans -> ctx .table -> use -- ;
9113
+ if (nft_trans_set_update (trans )) {
9114
+ struct nft_set * set = nft_trans_set (trans );
9103
9115
9116
+ WRITE_ONCE (set -> timeout , nft_trans_set_timeout (trans ));
9117
+ WRITE_ONCE (set -> gc_int , nft_trans_set_gc_int (trans ));
9118
+ } else {
9119
+ nft_clear (net , nft_trans_set (trans ));
9120
+ /* This avoids hitting -EBUSY when deleting the table
9121
+ * from the transaction.
9122
+ */
9123
+ if (nft_set_is_anonymous (nft_trans_set (trans )) &&
9124
+ !list_empty (& nft_trans_set (trans )-> bindings ))
9125
+ trans -> ctx .table -> use -- ;
9126
+ }
9104
9127
nf_tables_set_notify (& trans -> ctx , nft_trans_set (trans ),
9105
9128
NFT_MSG_NEWSET , GFP_KERNEL );
9106
9129
nft_trans_destroy (trans );
@@ -9322,6 +9345,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
9322
9345
nft_trans_destroy (trans );
9323
9346
break ;
9324
9347
case NFT_MSG_NEWSET :
9348
+ if (nft_trans_set_update (trans )) {
9349
+ nft_trans_destroy (trans );
9350
+ break ;
9351
+ }
9325
9352
trans -> ctx .table -> use -- ;
9326
9353
if (nft_trans_set_bound (trans )) {
9327
9354
nft_trans_destroy (trans );
0 commit comments