Skip to content

Commit c9d9eb9

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: nft_limit: reject configurations that cause integer overflow
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]>
1 parent 01acb2e commit c9d9eb9

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
@@ -58,17 +58,19 @@ static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)
5858
static int nft_limit_init(struct nft_limit_priv *priv,
5959
const struct nlattr * const tb[], bool pkts)
6060
{
61+
u64 unit, tokens, rate_with_burst;
6162
bool invert = false;
62-
u64 unit, tokens;
6363

6464
if (tb[NFTA_LIMIT_RATE] == NULL ||
6565
tb[NFTA_LIMIT_UNIT] == NULL)
6666
return -EINVAL;
6767

6868
priv->rate = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_RATE]));
69+
if (priv->rate == 0)
70+
return -EINVAL;
71+
6972
unit = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_UNIT]));
70-
priv->nsecs = unit * NSEC_PER_SEC;
71-
if (priv->rate == 0 || priv->nsecs < unit)
73+
if (check_mul_overflow(unit, NSEC_PER_SEC, &priv->nsecs))
7274
return -EOVERFLOW;
7375

7476
if (tb[NFTA_LIMIT_BURST])
@@ -77,18 +79,25 @@ static int nft_limit_init(struct nft_limit_priv *priv,
7779
if (pkts && priv->burst == 0)
7880
priv->burst = NFT_LIMIT_PKT_BURST_DEFAULT;
7981

80-
if (priv->rate + priv->burst < priv->rate)
82+
if (check_add_overflow(priv->rate, priv->burst, &rate_with_burst))
8183
return -EOVERFLOW;
8284

8385
if (pkts) {
84-
tokens = div64_u64(priv->nsecs, priv->rate) * priv->burst;
86+
u64 tmp = div64_u64(priv->nsecs, priv->rate);
87+
88+
if (check_mul_overflow(tmp, priv->burst, &tokens))
89+
return -EOVERFLOW;
8590
} else {
91+
u64 tmp;
92+
8693
/* The token bucket size limits the number of tokens can be
8794
* accumulated. tokens_max specifies the bucket size.
8895
* tokens_max = unit * (rate + burst) / rate.
8996
*/
90-
tokens = div64_u64(priv->nsecs * (priv->rate + priv->burst),
91-
priv->rate);
97+
if (check_mul_overflow(priv->nsecs, rate_with_burst, &tmp))
98+
return -EOVERFLOW;
99+
100+
tokens = div64_u64(tmp, priv->rate);
92101
}
93102

94103
if (tb[NFTA_LIMIT_FLAGS]) {

0 commit comments

Comments
 (0)