Skip to content

Commit 16e1adf

Browse files
committed
netfilter: nft_limit: reject configurations that cause integer overflow
jira VULN-8197 cve CVE-2024-26668 commit-author Florian Westphal <[email protected]> commit c9d9eb9 upstream-diff Used `limit' struct instead of `priv' because of missing 369b6cb. Also added casts to `u64' where appropriate as inspired by the RH's LTS 9.4 backport of this patch embedded in 270e20b. Reject bogus configs where internal token counter wraps around. This only occurs with very very large requests, such as 17gbyte/s. Its better to reject this rather than having incorrect ratelimit. Fixes: d2168e8 ("netfilter: nft_limit: add per-byte limiting") Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> (cherry picked from commit c9d9eb9) Signed-off-by: Marcin Wcisło <[email protected]>
1 parent bce037a commit 16e1adf

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

net/netfilter/nft_limit.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,18 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
5454
static int nft_limit_init(struct nft_limit *limit,
5555
const struct nlattr * const tb[], bool pkts)
5656
{
57-
u64 unit, tokens;
57+
u64 unit, tokens, rate_with_burst;
5858

5959
if (tb[NFTA_LIMIT_RATE] == NULL ||
6060
tb[NFTA_LIMIT_UNIT] == NULL)
6161
return -EINVAL;
6262

6363
limit->rate = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_RATE]));
64+
if (limit->rate == 0)
65+
return -EINVAL;
66+
6467
unit = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_UNIT]));
65-
limit->nsecs = unit * NSEC_PER_SEC;
66-
if (limit->rate == 0 || limit->nsecs < unit)
68+
if (check_mul_overflow(unit, (u64)NSEC_PER_SEC, &limit->nsecs))
6769
return -EOVERFLOW;
6870

6971
if (tb[NFTA_LIMIT_BURST])
@@ -72,18 +74,25 @@ static int nft_limit_init(struct nft_limit *limit,
7274
if (pkts && limit->burst == 0)
7375
limit->burst = NFT_LIMIT_PKT_BURST_DEFAULT;
7476

75-
if (limit->rate + limit->burst < limit->rate)
77+
if (check_add_overflow(limit->rate, (u64)limit->burst, &rate_with_burst))
7678
return -EOVERFLOW;
7779

7880
if (pkts) {
79-
tokens = div64_u64(limit->nsecs, limit->rate) * limit->burst;
81+
u64 tmp = div64_u64(limit->nsecs, limit->rate);
82+
83+
if (check_mul_overflow(tmp, (u64)limit->burst, &tokens))
84+
return -EOVERFLOW;
8085
} else {
86+
u64 tmp;
87+
8188
/* The token bucket size limits the number of tokens can be
8289
* accumulated. tokens_max specifies the bucket size.
8390
* tokens_max = unit * (rate + burst) / rate.
8491
*/
85-
tokens = div64_u64(limit->nsecs * (limit->rate + limit->burst),
86-
limit->rate);
92+
if (check_mul_overflow(limit->nsecs, rate_with_burst, &tmp))
93+
return -EOVERFLOW;
94+
95+
tokens = div64_u64(tmp, limit->rate);
8796
}
8897

8998
limit->tokens = tokens;

0 commit comments

Comments
 (0)