From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qk1-f174.google.com (mail-qk1-f174.google.com [209.85.222.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3B852232395 for ; Sat, 11 Jul 2026 14:34:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783780469; cv=none; b=GFFvnnNqsobzyD8HqDQ80wqHKITCHF8rJEjXNz5NcDdYurmcCsxPXHyWkonScqZJlVN3sCTbUqT72mX126r52MvrsJfaCbavnQ7hNKhvLrdj/1f8ao5HL3NCQv+s5oO6MJoAw+ebFMVHt97LwTtz0AytfrdeeefdJgoNC6rxIgQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783780469; c=relaxed/simple; bh=bQr/gKG784YvrFnbwt/kf8g6gtfGyF/YGcN6QmQ0+Ck=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=ux20ja0ffx2rEDFRg0XlHNd2mhI7NIWm/IYozBISDgFPsEDHiGdPbyV9fhldW+MWTMoE3N+CnUcmptG1BJAI0RQWEwDuqpjLM4RmZ+l5VE380XHsoy4v00CnMV3Ad452vHbmeVL+itVHRFfVJtUEow2dYtsxNqpWt38kjmnp8Kc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=LGDjOj3c; arc=none smtp.client-ip=209.85.222.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="LGDjOj3c" Received: by mail-qk1-f174.google.com with SMTP id af79cd13be357-92e533aacf2so95050985a.2 for ; Sat, 11 Jul 2026 07:34:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783780467; x=1784385267; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=Pn3TuWsy7LPK2Mh7RYsHyafjd2c/ye1pFlJPL8EwT/Q=; b=LGDjOj3cYlXADMQF61qDlgRzvrzhqg0No8NQCp/AW0GAoC80OC6vdWcV5Xr/ZFYkzh 1MXKRL9PpxuqUBwhcHgkb7FKVuDhqjRjAg4j4KXpJ2hKJBjDtRpyBeTkPzpWQvpxXg/I 2qSZK1ZJY+C9/FNan/QRiT1ZcUIA7KZ6XPspfBBVaBWbXkEeOHj1kexxLgVnwVBmIt+2 kKYtFCbPW9JckjUw6G8Rfhcb6dlUb+1d6W6xGB8TdjD/Jx7bqaUhyaZlDHFXRPY2Swjn MCoCAMcR18abTi0b7jiPNsWnpu2FI5LYvZBMq2nMO+TD3pG9ZCBh60K5/kqNnryXhwwe K0cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783780467; x=1784385267; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Pn3TuWsy7LPK2Mh7RYsHyafjd2c/ye1pFlJPL8EwT/Q=; b=gr17dwdxZStl63ykRK9TOHA2fkcqoKlKVZGl1SlzIjSWnu2AmqLL5lzYhNVZnGo1Lk uxKa/lC0Qrr9n8wxuA5MNajET7GRj69TntTKxBcjXpC4i9Lj9m/Nzam/oJyeEs+gYPuS PxlexHoI22QTgmuX/P3DuIPyDXkcx4YL0pXR4G6qBjDU2OKoGzwGZa5e06Lj1/uBlHCX h9LZXS3FhQWgR7Ww2j82m1kEfXDJaz915T2fV/KCGPoWxUcCrkzWH2QANBXXi+elrdOy GFNBH1H6MSkcfLby0Zw9k/ztm8KqDXsgdlUBPNk1cOwM0b1bsJMJbDcAs4v7OoJYx3Xn I7VA== X-Forwarded-Encrypted: i=1; AHgh+RowYa2hNuiUAQFR7Mwd0pVS2uVO5Cu1QQO73qkIkbIW8k1l5ms8/jqlvotMj3flFEa/N5xfYFDLmDlziUw=@vger.kernel.org X-Gm-Message-State: AOJu0YxJfeXzcEjLvfgN4xQJ/zEFvtd84qJlNhIGcIfXnWxHIUATLuqd sTIcTLRqy27i4cfVOYLsghJkpXOIdx5Gsn/WsYt6yuFKnoo01AmqPzx+ X-Gm-Gg: AfdE7ckAns2WygxloGD/2V2OQQ6/WUHpdQ0rHYLP94MJCTgyIjl5amgif22w1ShYCZl OlqHvNezh6Mud6ElIzf/YT24fEYp0q7EIMAKKkaH/AJTk6BYYsLdx9DSYINXtg0r/nY8oHal8FN kfNxksFdzK4NPnB2B4a8M08UQOESvgDRH4AWZ1jewTXlP07yxjGTtTr/vytDg07sytXpX3oFgZI kr+EXxfG9grxyxsynTFrJ1a3D6e3NUpShn9L3kcL957vt2kwjRb8CydRBSlRFRFAl6N8ncXLjol uhmhhUnOaTPMZqqJDhtNu50TTUShGgtBEtbX36tKOwtfQZTsc81PMevD/OynGi/u/f7In7A2QL6 dRmJla3x9D+iHwqwq6yZkmVKLaaxjwvd8s/C6hVQ/QSFxM4OFDIjoFNTleP6hgIZtY4czGzv0pj E3vMjAN1xCmtsGCHfALDgaauRH0RFYib1i05XXEeQymACRjHJdfiux0gLw6Qjl9sGl1W2dvWq2f BZo+THtycSFNIRpkl2V X-Received: by 2002:a05:620a:258c:b0:92e:54b1:2881 with SMTP id af79cd13be357-92ef2bb787bmr329664185a.16.1783780466845; Sat, 11 Jul 2026 07:34:26 -0700 (PDT) Received: from server0 (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-92ee5d375fesm461652085a.37.2026.07.11.07.34.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jul 2026 07:34:26 -0700 (PDT) From: Michael Bommarito To: Gao Xiang , Chao Yu Cc: Yue Hu , Jeffle Xu , Sandeep Dhavale , Hongbo Li , Chunhai Guo , linux-erofs@lists.ozlabs.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH v2] erofs: cap LZMA stream pool size Date: Sat, 11 Jul 2026 10:34:19 -0400 Message-ID: <20260711143419.2762894-1-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 7bit fs/erofs/decompressor_lzma.c sizes the module-global MicroLZMA stream pool from num_possible_cpus() or the lzma_streams module parameter, then z_erofs_load_lzma_config() preallocates one image-supplied dictionary per stream, accepting dictionaries up to 8 MiB. On high-CPU systems, a small EROFS image can pin hundreds of MiB of vmalloc-backed decoder state until the erofs module is unloaded. Impact: an attacker-supplied EROFS image mounted by the system can pin up to 8 MiB times the LZMA stream count of kernel vmalloc memory. Bound the LZMA stream pool by a new CONFIG_EROFS_FS_ZIP_LZMA_MAX_STREAMS option, default 16. The default keeps the worst-case preallocated dictionary pool at 128 MiB while preserving the existing per-image dictionary limit; memory-constrained systems can lower it and large servers can raise it. Fixes: 622ceaddb764 ("erofs: lzma compression support") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito --- v2: bound the pool with a Kconfig option (CONFIG_EROFS_FS_ZIP_LZMA_MAX_STREAMS, default 16) instead of a hardcoded 16, per Gao Xiang's review, so memory-constrained and server deployments can size it. Kept the EROFS_FS_ZIP_ prefix of the sibling options. v1: https://lore.kernel.org/linux-erofs/20260710023036.3745254-1-michael.bommarito@gmail.com/ fs/erofs/Kconfig | 20 ++++++++++++++++++++ fs/erofs/decompressor_lzma.c | 7 +++++++ 2 files changed, 27 insertions(+) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 4789b1077d8ce..3e4731dd03e7c 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -131,6 +131,26 @@ config EROFS_FS_ZIP_LZMA Say N if you want to disable LZMA compression support. +config EROFS_FS_ZIP_LZMA_MAX_STREAMS + int "EROFS LZMA maximum decompression stream pool size" + depends on EROFS_FS_ZIP_LZMA + range 1 1024 + default 16 + help + EROFS preallocates a pool of MicroLZMA decoder streams, one per + possible CPU by default, or as set by the lzma_streams module + parameter. Each stream can hold a dictionary of up to 8 MiB taken + from the mounted image, so on systems with a large number of CPUs a + single small image can pin a large amount of vmalloc memory until the + erofs module is unloaded. + + This bounds the number of preallocated streams. The worst-case + preallocated dictionary memory is 8 MiB times this value. Lower it on + memory-constrained or embedded systems; raise it on large servers that + decompress many EROFS images in parallel. + + If unsure, keep the default of 16. + config EROFS_FS_ZIP_DEFLATE bool "EROFS DEFLATE compressed data support" depends on EROFS_FS_ZIP diff --git a/fs/erofs/decompressor_lzma.c b/fs/erofs/decompressor_lzma.c index f6692d0f2f04d..882684c663f47 100644 --- a/fs/erofs/decompressor_lzma.c +++ b/fs/erofs/decompressor_lzma.c @@ -52,6 +52,13 @@ static int __init z_erofs_lzma_init(void) /* by default, use # of possible CPUs instead */ if (!z_erofs_lzma_nstrms) z_erofs_lzma_nstrms = num_possible_cpus(); + /* + * Each stream can pin an 8 MiB image-supplied dictionary, so bound the + * module-global pool to keep the worst-case preallocation in check on + * systems with many CPUs (or a large lzma_streams request). + */ + z_erofs_lzma_nstrms = min_t(unsigned int, z_erofs_lzma_nstrms, + CONFIG_EROFS_FS_ZIP_LZMA_MAX_STREAMS); for (i = 0; i < z_erofs_lzma_nstrms; ++i) { struct z_erofs_lzma *strm = kzalloc_obj(*strm); -- 2.53.0