diff options
-rw-r--r-- | include/net/netfilter/nf_tables.h | 7 | ||||
-rw-r--r-- | include/uapi/linux/netfilter/nf_tables.h | 2 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 39 | ||||
-rw-r--r-- | net/netfilter/nft_dynset.c | 3 |
4 files changed, 31 insertions, 20 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 1e9b5e1659a1..7511918dce6f 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -832,8 +832,11 @@ static inline struct nft_set_elem_expr *nft_set_ext_expr(const struct nft_set_ex static inline bool __nft_set_elem_expired(const struct nft_set_ext *ext, u64 tstamp) { - return nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) && - time_after_eq64(tstamp, READ_ONCE(nft_set_ext_timeout(ext)->expiration)); + if (!nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) || + nft_set_ext_timeout(ext)->timeout == 0) + return false; + + return time_after_eq64(tstamp, READ_ONCE(nft_set_ext_timeout(ext)->expiration)); } static inline bool nft_set_elem_expired(const struct nft_set_ext *ext) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 639894ed1b97..d6476ca5d7a6 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -436,7 +436,7 @@ enum nft_set_elem_flags { * @NFTA_SET_ELEM_KEY: key value (NLA_NESTED: nft_data) * @NFTA_SET_ELEM_DATA: data value of mapping (NLA_NESTED: nft_data_attributes) * @NFTA_SET_ELEM_FLAGS: bitmask of nft_set_elem_flags (NLA_U32) - * @NFTA_SET_ELEM_TIMEOUT: timeout value (NLA_U64) + * @NFTA_SET_ELEM_TIMEOUT: timeout value, zero means never times out (NLA_U64) * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64) * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY) * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index c295d6e6c1fb..ed85b10edb32 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5815,24 +5815,31 @@ static int nf_tables_fill_setelem(struct sk_buff *skb, goto nla_put_failure; if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT)) { - u64 expires, now = get_jiffies_64(); + u64 timeout = nft_set_ext_timeout(ext)->timeout; + u64 set_timeout = READ_ONCE(set->timeout); + __be64 msecs = 0; + + if (set_timeout != timeout) { + msecs = nf_jiffies64_to_msecs(timeout); + if (nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT, msecs, + NFTA_SET_ELEM_PAD)) + goto nla_put_failure; + } - if (nft_set_ext_timeout(ext)->timeout != READ_ONCE(set->timeout) && - nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT, - nf_jiffies64_to_msecs(nft_set_ext_timeout(ext)->timeout), - NFTA_SET_ELEM_PAD)) - goto nla_put_failure; + if (timeout > 0) { + u64 expires, now = get_jiffies_64(); - expires = READ_ONCE(nft_set_ext_timeout(ext)->expiration); - if (time_before64(now, expires)) - expires -= now; - else - expires = 0; + expires = READ_ONCE(nft_set_ext_timeout(ext)->expiration); + if (time_before64(now, expires)) + expires -= now; + else + expires = 0; - if (nla_put_be64(skb, NFTA_SET_ELEM_EXPIRATION, - nf_jiffies64_to_msecs(expires), - NFTA_SET_ELEM_PAD)) - goto nla_put_failure; + if (nla_put_be64(skb, NFTA_SET_ELEM_EXPIRATION, + nf_jiffies64_to_msecs(expires), + NFTA_SET_ELEM_PAD)) + goto nla_put_failure; + } } if (nft_set_ext_exists(ext, NFT_SET_EXT_USERDATA)) { @@ -7015,7 +7022,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, goto err_parse_key_end; } - if (timeout > 0) { + if (set->flags & NFT_SET_TIMEOUT) { err = nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT); if (err < 0) goto err_parse_key_end; diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index ed8d692bebe3..6a10305de24b 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c @@ -94,7 +94,8 @@ void nft_dynset_eval(const struct nft_expr *expr, if (set->ops->update(set, ®s->data[priv->sreg_key], nft_dynset_new, expr, regs, &ext)) { if (priv->op == NFT_DYNSET_OP_UPDATE && - nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT)) { + nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) && + nft_set_ext_timeout(ext)->timeout != 0) { timeout = priv->timeout ? : READ_ONCE(set->timeout); WRITE_ONCE(nft_set_ext_timeout(ext)->expiration, get_jiffies_64() + timeout); } |