@@ -465,26 +465,38 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx)
465465 return 0 ;
466466}
467467
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 )
470471{
471472 struct nft_trans * trans ;
472473
473474 trans = nft_trans_alloc (ctx , msg_type , sizeof (struct nft_trans_set ));
474475 if (trans == NULL )
475476 return - ENOMEM ;
476477
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 ) {
478479 nft_trans_set_id (trans ) =
479480 ntohl (nla_get_be32 (ctx -> nla [NFTA_SET_ID ]));
480481 nft_activate_next (ctx -> net , set );
481482 }
482483 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+ }
483489 nft_trans_commit_list_add_tail (ctx -> net , trans );
484490
485491 return 0 ;
486492}
487493
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+
488500static int nft_delset (const struct nft_ctx * ctx , struct nft_set * set )
489501{
490502 int err ;
@@ -4044,8 +4056,10 @@ static int nf_tables_fill_set_concat(struct sk_buff *skb,
40444056static int nf_tables_fill_set (struct sk_buff * skb , const struct nft_ctx * ctx ,
40454057 const struct nft_set * set , u16 event , u16 flags )
40464058{
4047- struct nlmsghdr * nlh ;
4059+ u64 timeout = READ_ONCE (set -> timeout );
4060+ u32 gc_int = READ_ONCE (set -> gc_int );
40484061 u32 portid = ctx -> portid ;
4062+ struct nlmsghdr * nlh ;
40494063 struct nlattr * nest ;
40504064 u32 seq = ctx -> seq ;
40514065 int i ;
@@ -4081,13 +4095,13 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
40814095 nla_put_be32 (skb , NFTA_SET_OBJ_TYPE , htonl (set -> objtype )))
40824096 goto nla_put_failure ;
40834097
4084- if (set -> timeout &&
4098+ if (timeout &&
40854099 nla_put_be64 (skb , NFTA_SET_TIMEOUT ,
4086- nf_jiffies64_to_msecs (set -> timeout ),
4100+ nf_jiffies64_to_msecs (timeout ),
40874101 NFTA_SET_PAD ))
40884102 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 )))
40914105 goto nla_put_failure ;
40924106
40934107 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,
46324646 for (i = 0 ; i < num_exprs ; i ++ )
46334647 nft_expr_destroy (& ctx , exprs [i ]);
46344648
4635- return err ;
4649+ if (err < 0 )
4650+ return err ;
4651+
4652+ return __nft_trans_set_add (& ctx , NFT_MSG_NEWSET , set , & desc );
46364653 }
46374654
46384655 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,
60706087 return err ;
60716088 } else if (set -> flags & NFT_SET_TIMEOUT &&
60726089 !(flags & NFT_SET_ELEM_INTERVAL_END )) {
6073- timeout = set -> timeout ;
6090+ timeout = READ_ONCE ( set -> timeout ) ;
60746091 }
60756092
60766093 expiration = 0 ;
@@ -6171,7 +6188,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
61716188 if (err < 0 )
61726189 goto err_parse_key_end ;
61736190
6174- if (timeout != set -> timeout ) {
6191+ if (timeout != READ_ONCE ( set -> timeout ) ) {
61756192 err = nft_set_ext_add (& tmpl , NFT_SET_EXT_TIMEOUT );
61766193 if (err < 0 )
61776194 goto err_parse_key_end ;
@@ -9093,14 +9110,20 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
90939110 nft_flow_rule_destroy (nft_trans_flow_rule (trans ));
90949111 break ;
90959112 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 );
91039115
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+ }
91049127 nf_tables_set_notify (& trans -> ctx , nft_trans_set (trans ),
91059128 NFT_MSG_NEWSET , GFP_KERNEL );
91069129 nft_trans_destroy (trans );
@@ -9322,6 +9345,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
93229345 nft_trans_destroy (trans );
93239346 break ;
93249347 case NFT_MSG_NEWSET :
9348+ if (nft_trans_set_update (trans )) {
9349+ nft_trans_destroy (trans );
9350+ break ;
9351+ }
93259352 trans -> ctx .table -> use -- ;
93269353 if (nft_trans_set_bound (trans )) {
93279354 nft_trans_destroy (trans );
0 commit comments