[PATCH nf v3 1/1] ipvs: bound LBLCR and LBLC cache growth
Zhiling Zou [email protected]
| Newsgroups | org.kernel.vger.lvs-devel,org.kernel.vger.netfilter-devel |
|---|---|
| Message-ID | <0bdd5abe9968ded7ca2b9cb6844ba83d94cc8d53.1787318053.git.zhilinz@nebusec.ai> |
From: Zhiling Zou <[email protected]> ip_vs_lblcr_new() and ip_vs_lblc_new() create cache entries for every previously unseen destination address. The table max_size only tells the periodic collector to reclaim entries after the cache has already exceeded the limit. It does not reclaim entries that the attacker continues to use. Reject new cache entries once either table reaches max_size * 3 / 2. The extra headroom lets the periodic collector catch up while the existing scheduler fallback continues to use the selected destination when cache creation fails. New traffic therefore stays serviceable without growing the tables further. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: [email protected] Reported-by: Vega <[email protected]> Suggested-by: Julian Anastasov <[email protected]> Signed-off-by: Zhiling Zou <[email protected]> --- changes in v3: - Allow 50% headroom above max_size before rejecting new cache entries, as suggested by Julian Anastasov. - Apply the max_size * 3 / 2 cutoff to both LBLC and LBLCR. - v2 Link: https://lore.kernel.org/all/17cbb1d0649f4e19aa2e407ab4b528d42b8edac4.1786949472.git.zhilinz@nebusec.ai/ changes in v2: - Change the LBLCR limit check from >= max_size to > max_size. - Apply the same cache growth bound to LBLC. - Add Suggested-by: Julian Anastasov <[email protected]>. - v1 Link: https://lore.kernel.org/all/62790a9f94ac5318f107a1811cff5a1f2fc7e0bf.1786884824.git.zhilinz@nebusec.ai/ net/netfilter/ipvs/ip_vs_lblc.c | 3 +++ net/netfilter/ipvs/ip_vs_lblcr.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 693bcc82ccb77..8180a7ba9f538 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -204,6 +204,9 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr, return en; ip_vs_lblc_del(en); } + if (atomic_read(&tbl->entries) >= tbl->max_size * 3 / 2) + return NULL; + en = kmalloc_obj(*en, GFP_ATOMIC); if (!en) return NULL; diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index f53f05ceea36f..858393b1d2d17 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -363,6 +363,9 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr, en = ip_vs_lblcr_get(af, tbl, daddr); if (!en) { + if (atomic_read(&tbl->entries) >= tbl->max_size * 3 / 2) + return NULL; + en = kmalloc_obj(*en, GFP_ATOMIC); if (!en) return NULL; -- 2.43.0