]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: nft_ct: expectation timeouts are passed in milliseconds
authorFlorian Westphal <fw@strlen.de>
Tue, 23 Jun 2026 05:30:34 +0000 (07:30 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 23 Jun 2026 11:10:47 +0000 (13:10 +0200)
Userspace passes '5000' in case user asks for 5 seconds.

Allowing for sub-second expectation lifetimes makes sense to me. so
fix up the kernel side instead of munging nft to send a value rounded
up to next second.

Also note that this violates nft convention of passing integers in
network byte order, but we can't change this anymore.

Fixes: 857b46027d6f ("netfilter: nft_ct: add ct expectations support")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nft_ct.c

index 958054dd2e2ecce2815b791623bbf881ec6d6cb2..03a88c77e0f0281928fce38882357d79c265b737 100644 (file)
@@ -1215,11 +1215,23 @@ struct nft_ct_expect_obj {
        u32             timeout;
 };
 
+static int nft_ct_expect_timeout_get(const struct nlattr *attr, u32 *val)
+{
+       unsigned long jiffies_val = msecs_to_jiffies(nla_get_u32(attr));
+
+       if (jiffies_val > UINT_MAX)
+               return -ERANGE;
+
+       *val = jiffies_val;
+       return 0;
+}
+
 static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
                                  const struct nlattr * const tb[],
                                  struct nft_object *obj)
 {
        struct nft_ct_expect_obj *priv = nft_obj_data(obj);
+       int err;
 
        if (!tb[NFTA_CT_EXPECT_L4PROTO] ||
            !tb[NFTA_CT_EXPECT_DPORT] ||
@@ -1254,8 +1266,11 @@ static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
                return -EOPNOTSUPP;
        }
 
+       err = nft_ct_expect_timeout_get(tb[NFTA_CT_EXPECT_TIMEOUT], &priv->timeout);
+       if (err)
+               return err;
+
        priv->dport = nla_get_be16(tb[NFTA_CT_EXPECT_DPORT]);
-       priv->timeout = nla_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]);
        priv->size = nla_get_u8(tb[NFTA_CT_EXPECT_SIZE]);
 
        return nf_ct_netns_get(ctx->net, ctx->family);
@@ -1275,7 +1290,7 @@ static int nft_ct_expect_obj_dump(struct sk_buff *skb,
        if (nla_put_be16(skb, NFTA_CT_EXPECT_L3PROTO, htons(priv->l3num)) ||
            nla_put_u8(skb, NFTA_CT_EXPECT_L4PROTO, priv->l4proto) ||
            nla_put_be16(skb, NFTA_CT_EXPECT_DPORT, priv->dport) ||
-           nla_put_u32(skb, NFTA_CT_EXPECT_TIMEOUT, priv->timeout) ||
+           nla_put_u32(skb, NFTA_CT_EXPECT_TIMEOUT, jiffies_to_msecs(priv->timeout)) ||
            nla_put_u8(skb, NFTA_CT_EXPECT_SIZE, priv->size))
                return -1;
 
@@ -1325,7 +1340,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
                          &ct->tuplehash[!dir].tuple.src.u3,
                          &ct->tuplehash[!dir].tuple.dst.u3,
                          priv->l4proto, NULL, &priv->dport);
-       exp->timeout += priv->timeout * HZ;
+       exp->timeout += priv->timeout;
 
        if (nf_ct_expect_related(exp, 0) != 0)
                regs->verdict.code = NF_DROP;