]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
Fix price overflow in ratelimiting, defer
authorLukáš Ondráček <lukas.ondracek@nic.cz>
Thu, 23 Apr 2026 11:10:55 +0000 (13:10 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 27 Apr 2026 07:07:18 +0000 (09:07 +0200)
daemon/defer.c
daemon/ratelimiting.c
doc/_static/config.schema.json
python/knot_resolver/datamodel/types/__init__.py
python/knot_resolver/datamodel/types/base_types.py
python/knot_resolver/datamodel/types/types.py
python/knot_resolver/datamodel/view_schema.py

index 46ae18fed7e37415a184896e9749ce274566fb23..d9fbbaf4a33e44813c23168b1177ec9a8547812a 100644 (file)
@@ -42,7 +42,10 @@ V6_CONF = {1, V6_PREFIXES_CNT, V6_PREFIXES, V6_RATE_MULT, V6_SUBPRIO};
 
 #define Q0_INSTANT_LIMIT      1000000 // ns
 #define KRU_CAPACITY          (1<<19) // same as ratelimiting default
-#define BASE_PRICE(nsec)      ((uint64_t)KRU_LIMIT * LOADS_THRESHOLDS[0] / (1<<16) * (nsec) / Q0_INSTANT_LIMIT)
+#define BASE_PRICE(nsec)      ((nsec) >= UINT64_MAX / ((uint64_t)KRU_LIMIT * LOADS_THRESHOLDS[0] / (1<<16)) ? UINT64_MAX : \
+                                                       (uint64_t)KRU_LIMIT * LOADS_THRESHOLDS[0] / (1<<16) * (nsec) / Q0_INSTANT_LIMIT)
+       // with current settings BASE_PRICE(x) is approximately x
+       // with nsec > ~(2<<32) the KRU limit is reached, so rounding >~(2<<44) to ~(2<<64) is OK
 #define MAX_DECAY             (BASE_PRICE(1000000) / 2)  // max value at 50% utilization of single cpu
        //   see log written by defer_str_conf for details
 
index a98b5c99e3bdc84cd8185ade3eb097c79a67aa18..5d58f29b55e242d50a861c081b47cf86f7f95e5a 100644 (file)
@@ -143,8 +143,9 @@ bool ratelimiting_request_begin(struct kr_request *req)
                // compute adjusted prices, using standard rounding
                kru_price_t prices[V6_PREFIXES_CNT];
                for (int i = 0; i < V6_PREFIXES_CNT; ++i) {
-                       prices[i] = (req->qsource.price_factor16
+                       uint64_t price = (req->qsource.price_factor16
                                        * (uint64_t)ratelimiting->v6_prices[i] + (1<<15)) >> 16;
+                       prices[i] = price > (kru_price_t)-1 ? -1 : price;
                }
                limited_prefix = KRU.limited_multi_prefix_or((struct kru *)ratelimiting->kru, time_now,
                                1, key, V6_PREFIXES, prices, V6_PREFIXES_CNT, NULL);
@@ -155,8 +156,9 @@ bool ratelimiting_request_begin(struct kr_request *req)
                // compute adjusted prices, using standard rounding
                kru_price_t prices[V4_PREFIXES_CNT];
                for (int i = 0; i < V4_PREFIXES_CNT; ++i) {
-                       prices[i] = (req->qsource.price_factor16
+                       uint64_t price = (req->qsource.price_factor16
                                        * (uint64_t)ratelimiting->v4_prices[i] + (1<<15)) >> 16;
+                       prices[i] = price > (kru_price_t)-1 ? -1 : price;
                }
                limited_prefix = KRU.limited_multi_prefix_or((struct kru *)ratelimiting->kru, time_now,
                                0, key, V4_PREFIXES, prices, V4_PREFIXES_CNT, NULL);
index 263007de0e6abcc440be9cb71afebf4e070fbfb0..ccfb9479001b03791a46d9661141526f77d51fe6 100644 (file)
                             "price-factor": {
                                 "type": "number",
                                 "minimum": 0.0,
+                                "maximum": 65535.0,
                                 "description": "Multiplies rate-limiting and defer prices of operations, use 0 to whitelist.",
                                 "default": 1.0
                             },
index e30312c9d554a12b06bbd5419da68993b00304cb..07f212e1ace2586923f23e3a95c6fafa6f0f26fb 100644 (file)
@@ -5,6 +5,7 @@ from .types import (
     DomainName,
     EscapedStr,
     EscapedStr32B,
+    Float0_65535,
     FloatNonNegative,
     IDPattern,
     Int0_32,
@@ -39,6 +40,7 @@ __all__ = [
     "DomainName",
     "EscapedStr",
     "EscapedStr32B",
+    "Float0_65535",
     "FloatNonNegative",
     "IDPattern",
     "Int0_32",
index fb131b5ca17a0085e73391a774112c2e42c4df03..66179afc93d73c74dd6951b0a481ec951808ff26 100644 (file)
@@ -194,7 +194,7 @@ class FloatRangeBase(FloatBase):
 
     Just inherit the class and set the values for '_min' and '_max'.
 
-    class FloatNonNegative(IntRangeBase):
+    class FloatNonNegative(FloatRangeBase):
         _min: float = 0.0
     """
 
index b361029314de73aee9574d71067101c60e1774a2..b2080223aa87f873f4e5ef50775a977fbf9e748e 100644 (file)
@@ -62,6 +62,11 @@ class FloatNonNegative(FloatRangeBase):
     _min: float = 0.0
 
 
+class Float0_65535(FloatRangeBase):  # noqa: N801
+    _min: float = 0.0
+    _max: float = 65535.0
+
+
 class SizeUnit(UnitBase):
     _units = {"B": 1, "K": 1024, "M": 1024**2, "G": 1024**3}
 
index d46ea5442c3943ce0a06d409fdf69aa21023044c..af186927f8b675af8728a84af66627625b264ef4 100644 (file)
@@ -1,6 +1,6 @@
 from typing import List, Literal, Optional
 
-from knot_resolver.datamodel.types import FloatNonNegative, IDPattern, IPNetwork
+from knot_resolver.datamodel.types import Float0_65535, IDPattern, IPNetwork
 from knot_resolver.utils.modeling import ConfigSchema
 
 
@@ -17,7 +17,7 @@ class ViewOptionsSchema(ConfigSchema):
 
     minimize: bool = True
     dns64: bool = True
-    price_factor: FloatNonNegative = FloatNonNegative(1.0)
+    price_factor: Float0_65535 = Float0_65535(1.0)
     fallback: bool = True