From nobody Mon Apr 6 09:10:08 2026 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (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 EF57339903C for ; Thu, 19 Mar 2026 21:06:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773954369; cv=none; b=O74oJgh6iPMNrjthL0pQsPISXG36QpigqWvTKMM7eaMPKekD0MM83AkSxQ+L8yQIHzlg0umNa6cZsb+BG23GJSxe3GcCPYrtCd+smVFS2qjt3CpXeOvt+J+1ZmzaAG3/hDCSBp4bS1XVnBRIHiKzEQO85Mkz82i6t90NigBBmK8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773954369; c=relaxed/simple; bh=eGNbh+Z5Blv2XE1NHLeBBAh984eYjI+gMSQaulvZ378=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=Nqlng3F5TG/4W8W7hyOI1/jKiCI7FOKMqbdqmMuNjun7/UClXbLLRsz3+O3REfER4td7xqev03hJ+FAvc2d3nH1aGcR7gru7jf7SGqdlrtSvXifUB3jWMBXzfg06cdtwecPV8CMsU6cyjpnNdnWeQ/dlCTjAmQZs62CXo438go0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--elver.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=eCGUiXWX; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--elver.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="eCGUiXWX" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-4837b6f6b93so15756705e9.3 for ; Thu, 19 Mar 2026 14:06:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1773954366; x=1774559166; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=smcAMeBF3eFvC+OZUcjPasWlZlCzzD66XLXM7VGnv/E=; b=eCGUiXWXa/mL0k08votMZTK/hLBtpjCtRjSNfURAXdcIBUF9Cm861DIUSKGPMK2Gtb vhxWqqPRu/+kXYZa1WlyFujH08qGRlYDIaxDdJ2jKiKUwwrBK2l2a5kdGEqu/bAoRLYw BmoIKZNpmvduzG3KS6Q/2nrxZSTObkzm1VwKI5GV1NhCKMGi6U4heGzXHGyoEWCdUD1o +TUm/Hu1/vNjf8UwdHMmUppNBYRd1PFVvnKHo5rrfHGoKEHpbkUXlguNDN3E//UNQQ1o RBT3rrf0W2JMXezsCKUAAiFO1RLHSfxVGoXWvmb+kIH9xO/GGyGLUQ6KWawTEPXOg5A5 jC6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773954366; x=1774559166; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=smcAMeBF3eFvC+OZUcjPasWlZlCzzD66XLXM7VGnv/E=; b=iFMNUuDc3Mbh0VqwIneIhgGBQmvkTAxeEfpaOSPt/aNL2DeyEsEe+E2SVQhS7oyIiN iFIibdny7mESbm8HTfmBGDoYjTt+/x+QEjdXUhnbuwHs9zz8TpaDltQU7JUBme8tr7SN B3SjSFXAinV/zPqZieL8hkoV3PfkBd4UaMEiOgp+fYVVV3z6gAIwTjhxp6N32pEPex9e XZfOIhyU3vNFpP1L4Vq9JWUUAGIbAn/YJwAaN3G83d72pohHs40JDi53Ce9nRKM6SdbL 0bdzHoN2vpQ6XgAPKWrLZydcCxslJcMIeZtLJgqcn+SBGcbDCCUk5W0+xRo5a76f20T9 abNA== X-Forwarded-Encrypted: i=1; AJvYcCV60rkndLYlZqgreIwAHpeimBu3W7WOF8KdakyyQ88849Kcu0NWe/syhZUbioYfmy3Tsj/+80Tit8zkMk0=@vger.kernel.org X-Gm-Message-State: AOJu0Yw1Ns3EhZHFDuU22bBizCexFiqHXa4Ej6ZoznhbK/4/HC+PBjIN nc5jrSvt4Xdvd/4do5AhoMYu28FSCusLLaY9w5g7VxDvwrjLFGSoj8mdEEOwAzbkLPtZ6XiR+3N PdA== X-Received: from wmjk5.prod.google.com ([2002:a7b:c305:0:b0:485:2e9a:31b4]) (user=elver job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:468b:b0:477:54f9:6ac2 with SMTP id 5b1f17b1804b1-486feb5f9c1mr10150515e9.0.1773954366292; Thu, 19 Mar 2026 14:06:06 -0700 (PDT) Date: Thu, 19 Mar 2026 22:03:53 +0100 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260319210528.1694513-2-elver@google.com> Subject: [PATCH v2] kho: use checked arithmetic in deserialize_bitmap() From: Marco Elver To: elver@google.com Cc: Alexander Graf , Mike Rapoport , Pasha Tatashin , Pratyush Yadav , kexec@lists.infradead.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The function deserialize_bitmap() calculates the reservation size using: int sz =3D 1 << (order + PAGE_SHIFT); If a corrupted KHO image provides an order >=3D 20 (on systems with 4KB pages), the shift amount becomes >=3D 32, which overflows the 32-bit integer. This results in a zero-size memory reservation. Furthermore, the physical address calculation: phys_addr_t phys =3D elm->phys_start + (bit << (order + PAGE_SHIFT)); can also overflow and wrap around if the order is large. This allows a corrupt KHO image to cause out-of-bounds updates to page->private of arbitrary physical pages during early boot. Fix this by changing 'sz' to 'unsigned long' and using checked add and shift to safely calculate the shift amount, size, and physical address, skipping malformed chunks. This allows preserving memory with an order larger than MAX_PAGE_ORDER. Fixes: fc33e4b44b27 ("kexec: enable KHO support for memory preservation") Signed-off-by: Marco Elver --- v2: * Switch to unsigned long and use checked shift and add (Mike). v1: https://lore.kernel.org/all/20260214010013.3027519-1-elver@google.com/ --- kernel/liveupdate/kexec_handover.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index cc68a3692905..0d8417dcd3ff 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -461,15 +462,29 @@ static void __init deserialize_bitmap(unsigned int or= der, struct khoser_mem_bitmap_ptr *elm) { struct kho_mem_phys_bits *bitmap =3D KHOSER_LOAD_PTR(elm->bitmap); + unsigned int shift; unsigned long bit; + unsigned long sz; + + if (check_add_overflow(order, PAGE_SHIFT, &shift) || + check_shl_overflow(1UL, shift, &sz)) { + pr_warn("invalid order %u for preserved bitmap\n", order); + return; + } =20 for_each_set_bit(bit, bitmap->preserve, PRESERVE_BITS) { - int sz =3D 1 << (order + PAGE_SHIFT); - phys_addr_t phys =3D - elm->phys_start + (bit << (order + PAGE_SHIFT)); - struct page *page =3D phys_to_page(phys); + phys_addr_t offset, phys; + struct page *page; union kho_page_info info; =20 + if (check_shl_overflow((phys_addr_t)bit, shift, &offset) || + check_add_overflow(elm->phys_start, offset, &phys)) { + pr_warn("invalid phys layout for preserved bitmap\n"); + return; + } + + page =3D phys_to_page(phys); + memblock_reserve(phys, sz); memblock_reserved_mark_noinit(phys, sz); info.magic =3D KHO_PAGE_MAGIC; --=20 2.53.0.1018.g2bb0e51243-goog