| From 8cdf30813ea8ce881cecc08664144416dbdb3e16 Mon Sep 17 00:00:00 2001 |
| From: Josh Law <objecting@objecting.org> |
| Date: Sun, 8 Mar 2026 20:20:28 +0000 |
| Subject: lib/ts_kmp: fix integer overflow in pattern length calculation |
| |
| From: Josh Law <objecting@objecting.org> |
| |
| commit 8cdf30813ea8ce881cecc08664144416dbdb3e16 upstream. |
| |
| The ts_kmp algorithm stores its prefix_tbl[] table and pattern in a single |
| allocation sized from the pattern length. If the prefix_tbl[] size |
| calculation wraps, the resulting allocation can be too small and |
| subsequent pattern copies can overflow it. |
| |
| Fix this by rejecting zero-length patterns and by using overflow helpers |
| before calculating the combined allocation size. |
| |
| |
| This fixes a potential heap overflow. The pattern length calculation can |
| wrap during a size_t addition, leading to an undersized allocation. |
| Because the textsearch library is reachable from userspace via Netfilter's |
| xt_string module, this is a security risk that should be backported to LTS |
| kernels. |
| |
| Link: https://lkml.kernel.org/r/20260308202028.2889285-2-objecting@objecting.org |
| Signed-off-by: Josh Law <objecting@objecting.org> |
| Reviewed-by: Andrew Morton <akpm@linux-foundation.org> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| lib/ts_kmp.c | 18 ++++++++++++++++-- |
| 1 file changed, 16 insertions(+), 2 deletions(-) |
| |
| --- a/lib/ts_kmp.c |
| +++ b/lib/ts_kmp.c |
| @@ -94,8 +94,22 @@ static struct ts_config *kmp_init(const |
| struct ts_config *conf; |
| struct ts_kmp *kmp; |
| int i; |
| - unsigned int prefix_tbl_len = len * sizeof(unsigned int); |
| - size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len; |
| + unsigned int prefix_tbl_len; |
| + size_t priv_size; |
| + |
| + /* Zero-length patterns would make kmp_find() read beyond kmp->pattern. */ |
| + if (unlikely(!len)) |
| + return ERR_PTR(-EINVAL); |
| + |
| + /* |
| + * kmp->pattern is stored immediately after the prefix_tbl[] table. |
| + * Reject lengths that would wrap while sizing either region. |
| + */ |
| + if (unlikely(check_mul_overflow(len, sizeof(*kmp->prefix_tbl), |
| + &prefix_tbl_len) || |
| + check_add_overflow(sizeof(*kmp), (size_t)len, &priv_size) || |
| + check_add_overflow(priv_size, prefix_tbl_len, &priv_size))) |
| + return ERR_PTR(-EINVAL); |
| |
| conf = alloc_ts_config(priv_size, gfp_mask); |
| if (IS_ERR(conf)) |