mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
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: d2168e849e
("netfilter: nft_limit: add per-byte limiting")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
01acb2e866
commit
c9d9eb9c53
@ -58,17 +58,19 @@ static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)
|
||||
static int nft_limit_init(struct nft_limit_priv *priv,
|
||||
const struct nlattr * const tb[], bool pkts)
|
||||
{
|
||||
u64 unit, tokens, rate_with_burst;
|
||||
bool invert = false;
|
||||
u64 unit, tokens;
|
||||
|
||||
if (tb[NFTA_LIMIT_RATE] == NULL ||
|
||||
tb[NFTA_LIMIT_UNIT] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
priv->rate = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_RATE]));
|
||||
if (priv->rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
unit = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_UNIT]));
|
||||
priv->nsecs = unit * NSEC_PER_SEC;
|
||||
if (priv->rate == 0 || priv->nsecs < unit)
|
||||
if (check_mul_overflow(unit, NSEC_PER_SEC, &priv->nsecs))
|
||||
return -EOVERFLOW;
|
||||
|
||||
if (tb[NFTA_LIMIT_BURST])
|
||||
@ -77,18 +79,25 @@ static int nft_limit_init(struct nft_limit_priv *priv,
|
||||
if (pkts && priv->burst == 0)
|
||||
priv->burst = NFT_LIMIT_PKT_BURST_DEFAULT;
|
||||
|
||||
if (priv->rate + priv->burst < priv->rate)
|
||||
if (check_add_overflow(priv->rate, priv->burst, &rate_with_burst))
|
||||
return -EOVERFLOW;
|
||||
|
||||
if (pkts) {
|
||||
tokens = div64_u64(priv->nsecs, priv->rate) * priv->burst;
|
||||
u64 tmp = div64_u64(priv->nsecs, priv->rate);
|
||||
|
||||
if (check_mul_overflow(tmp, priv->burst, &tokens))
|
||||
return -EOVERFLOW;
|
||||
} else {
|
||||
u64 tmp;
|
||||
|
||||
/* The token bucket size limits the number of tokens can be
|
||||
* accumulated. tokens_max specifies the bucket size.
|
||||
* tokens_max = unit * (rate + burst) / rate.
|
||||
*/
|
||||
tokens = div64_u64(priv->nsecs * (priv->rate + priv->burst),
|
||||
priv->rate);
|
||||
if (check_mul_overflow(priv->nsecs, rate_with_burst, &tmp))
|
||||
return -EOVERFLOW;
|
||||
|
||||
tokens = div64_u64(tmp, priv->rate);
|
||||
}
|
||||
|
||||
if (tb[NFTA_LIMIT_FLAGS]) {
|
||||
|
Loading…
Reference in New Issue
Block a user