From nobody Mon Feb 9 03:16:38 2026 Received: from mail-yx1-f51.google.com (mail-yx1-f51.google.com [74.125.224.51]) (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 AF2AD2DC76B for ; Tue, 23 Dec 2025 14:01:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766498509; cv=none; b=kJ/pRkUIf+ORK5BPYdkXAxSX54nVUYwpOypj14RYOAJmX7D3P3x979uO49peMfQNQ/R8FDkuhQYi5wyiceFdBKvVBAdnSdf/48A5Cm9JpG2MiYBUBqfD4hTMJxCO623iSGpD2YFbgZvGneZ4jYvp8novt9ywxrNVAkhbSbDIiqk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766498509; c=relaxed/simple; bh=NHaye/YCxEKK2itQlpWw5VOtt7oH/Pr0eloBfvtHfbk=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=slkSHOJ2NafYgga0IkOtPLVli16hLVkwBrnH0RG2WaEVa90bO/1FWQobG5nJ7OvvIqhVrQS0GjysSLlsQb5B9iZ7WWeh/3evcO7baVIDSi6QdITFQGAfeeO/Wo9ZmwTCuK2/noe5+rx/gZYQiJuq5E4FKDGae03vyFzNRAUuE7M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=bwNLkpeO; arc=none smtp.client-ip=74.125.224.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="bwNLkpeO" Received: by mail-yx1-f51.google.com with SMTP id 956f58d0204a3-64455a2a096so3989784d50.3 for ; Tue, 23 Dec 2025 06:01:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1766498506; x=1767103306; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=vshIKu39IbphKk1hyt1uS5BaulPgmjMjuk5AnSSvw9w=; b=bwNLkpeOvS4UNObErBxG3FrjveyFhjiafZ6CnGlPAIRbM/lb5mgJPJtZxrqxe2NgC1 m2sAyt93WM3VPfEzyjhM/Bapl1qgDMa85yO/6UuVSTZqDVdbk0p4eozANSNCXu7rPjJz m0xnxzeN+yGw/v0r2fbSQWx8xCZ524TqinA9YYvzY1BTIC6NSkeRwJn5pVQl0p7GWcdK jM8IlXsrfzyo+pbfmC6m9B5d6A6yEEXv+mWesO2e2nLjNOh1ZlYSSdiZhmBhCc5HtVmc mEd6cA+6/5izsTdqavWMLhF2jaHPCzMJOCBmM/3StAdFmx0sTosQ3bBxTCWv0T7AZbev KtAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766498506; x=1767103306; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=vshIKu39IbphKk1hyt1uS5BaulPgmjMjuk5AnSSvw9w=; b=W2J2EwF6z3hmksT3ymPFnc105p3GkmmuROubbu1JO8LLVcvYNBygkQ+6wETNgoqMxS YIRA94KkbBiiEV456zct2oDwhveLRTirt+xhP9F8F+c2tCWXFrJjLA2+hjU+V4uM24Wm Rq+hAbgILgaZ+NVhSxXPYCVghMFQzuDeowZtefK5R3U1ZiX1hNOhfivLha4SFJZjldx8 oChNVRWd1Uf/cmowBMyZj3cJqh+/2L4G5YxO5nbeRKM8R3BvRleHofqfXHSo4X24p6U1 tOSFdPT4yWdjU8rLsQ2XIDqKWD6YW6XLYIo6/ACbU/+T5GYa4YT1yJrbCPda99cghU6T 7Mdg== X-Forwarded-Encrypted: i=1; AJvYcCVjTmx+RK+MxLKeDzi48VT39r2b6bVvAaBgBnEWsfVoE5g1i5rn0gdrLEWmicFvF82/zhN/GB3JVgz75yk=@vger.kernel.org X-Gm-Message-State: AOJu0YzBeI6MHObWuvwERWA/tAwfVPTscd9ZGqcRaPkpfMTxInyhWVHK Ha83nQzu/PelOXzmQzviDexxkeFJn537Xd+gMhNpGjOcsTHMBHj1sNF5bJ3fEnucxWs= X-Gm-Gg: AY/fxX51K7FqSZqXSQHqqMai+knFur9+xdWIdvwQAFoeZNKn6wMGreh65u3rnadbmqL wG8E97vMUyxMfSdXVfn+HnDULxPGcvMneUexJ8GUuz5sCOBUmz1Cm8DBAqu7d4Kev1gUJ9cimf2 DB0c7GCawqwZYmcXbMQBOEXZiKcYFp3mGElGjcYTklnfkpAUq82m/QX/XykxROn2QV9MrbYYBrR spXzaa9SezKuvfJeC48SsIe8x93doXfEr1U5Zf6BWmrCD149WOvCcD3WKS5gOjPLTf9LqPqhAXh GUpqD0cra3Ns2QA2prYdDw8tCjx5ySKRgM61JxuIXVU8/2n6H6zy1ylhxsHuvIw435V3BUrbzYN bK7QMXSdpBnnPxXL0kqQiNdthK/6wOBpskUEa+1hDDZ034LW/Be/RqmTElDhHjLFLUSDy9BgH/7 t1jTBN0eDsOAKea/pMBrIDPG1c+BxhGEGpHFy0PsWly8bBgsw2QxXIBcjWjSYfDgbeIvSUFs88x Bi8jBJwjCUEyYVrJwVmG2ps/32VX456zOIzrg== X-Google-Smtp-Source: AGHT+IH5CPaJf1hFF18a7CLmrmSafeqmgYVCXu6LIDTysGZNKbl/h5bcqgxuwkcD9gwaFkH2YgNd4A== X-Received: by 2002:a05:690c:4b88:b0:78c:6664:3104 with SMTP id 00721157ae682-78fb3f05364mr244887467b3.5.1766498506252; Tue, 23 Dec 2025 06:01:46 -0800 (PST) Received: from soleen.c.googlers.com.com (182.221.85.34.bc.googleusercontent.com. [34.85.221.182]) by smtp.gmail.com with ESMTPSA id 00721157ae682-78ffebd2690sm1244367b3.15.2025.12.23.06.01.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Dec 2025 06:01:45 -0800 (PST) From: Pasha Tatashin To: akpm@linux-foundation.org, pasha.tatashin@soleen.com, rppt@kernel.org, graf@amazon.com, linux-kernel@vger.kernel.org, kexec@lists.infradead.org, linux-mm@kvack.org, pratyush@kernel.org, ricardo.neri-calderon@linux.intel.com Subject: [PATCH v4] kho: validate preserved memory map during population Date: Tue, 23 Dec 2025 09:01:40 -0500 Message-ID: <20251223140140.2090337-1-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.52.0.351.gbe84eed79e-goog Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" If the previous kernel enabled KHO but did not call kho_finalize() (e.g., CONFIG_LIVEUPDATE=3Dn or userspace skipped the finalization step), the 'preserved-memory-map' property in the FDT remains empty/zero. Previously, kho_populate() would succeed regardless of the memory map's state, reserving the incoming scratch regions in memblock. However, kho_memory_init() would later fail to deserialize the empty map. By that time, the scratch regions were already registered, leading to partial initialization and subsequent list corruption (freeing scratch area twice) during kho_init(). Move the validation of the preserved memory map earlier into kho_populate(). If the memory map is empty/NULL: 1. Abort kho_populate() immediately with -ENOENT. 2. Do not register or reserve the incoming scratch memory, allowing the new kernel to reclaim those pages as standard free memory. 3. Leave the global 'kho_in' state uninitialized. Consequently, kho_memory_init() sees no active KHO context (kho_in.mem_chunks_phys is 0) and falls back to kho_reserve_scratch(), allocating fresh scratch memory as if it were a standard cold boot. Fixes: de51999e687c ("kho: allow memory preservation state updates after fi= nalization") Reported-by: Ricardo Neri Closes: https://lore.kernel.org/all/20251218215613.GA17304@ranerica-svr.sc.= intel.com Signed-off-by: Pasha Tatashin Reviewed-by: Mike Rapoport (Microsoft) Tested-by: Ricardo Neri Reviewed-by: Pratyush Yadav --- Changes v4: - Addressed Tested-by - Addressed review comments from Pratyush. kernel/liveupdate/kexec_handover.c | 37 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index 9dc51fab604f..d4482b6e3cae 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -460,27 +460,23 @@ static void __init deserialize_bitmap(unsigned int or= der, } } =20 -/* Return true if memory was deserizlied */ -static bool __init kho_mem_deserialize(const void *fdt) +/* Returns physical address of the preserved memory map from FDT */ +static phys_addr_t __init kho_get_mem_map_phys(const void *fdt) { - struct khoser_mem_chunk *chunk; const void *mem_ptr; - u64 mem; int len; =20 mem_ptr =3D fdt_getprop(fdt, 0, PROP_PRESERVED_MEMORY_MAP, &len); if (!mem_ptr || len !=3D sizeof(u64)) { pr_err("failed to get preserved memory bitmaps\n"); - return false; + return 0; } =20 - mem =3D get_unaligned((const u64 *)mem_ptr); - chunk =3D mem ? phys_to_virt(mem) : NULL; - - /* No preserved physical pages were passed, no deserialization */ - if (!chunk) - return false; + return get_unaligned((const u64 *)mem_ptr); +} =20 +static void __init kho_mem_deserialize(struct khoser_mem_chunk *chunk) +{ while (chunk) { unsigned int i; =20 @@ -489,8 +485,6 @@ static bool __init kho_mem_deserialize(const void *fdt) &chunk->bitmaps[i]); chunk =3D KHOSER_LOAD_PTR(chunk->hdr.next); } - - return true; } =20 /* @@ -1253,6 +1247,7 @@ bool kho_finalized(void) struct kho_in { phys_addr_t fdt_phys; phys_addr_t scratch_phys; + phys_addr_t mem_map_phys; struct kho_debugfs dbg; }; =20 @@ -1434,12 +1429,10 @@ static void __init kho_release_scratch(void) =20 void __init kho_memory_init(void) { - if (kho_in.scratch_phys) { + if (kho_in.mem_map_phys) { kho_scratch =3D phys_to_virt(kho_in.scratch_phys); kho_release_scratch(); - - if (!kho_mem_deserialize(kho_get_fdt())) - kho_in.fdt_phys =3D 0; + kho_mem_deserialize(phys_to_virt(kho_in.mem_map_phys)); } else { kho_reserve_scratch(); } @@ -1448,8 +1441,9 @@ void __init kho_memory_init(void) void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len, phys_addr_t scratch_phys, u64 scratch_len) { - void *fdt =3D NULL; struct kho_scratch *scratch =3D NULL; + phys_addr_t mem_map_phys; + void *fdt =3D NULL; int err =3D 0; unsigned int scratch_cnt =3D scratch_len / sizeof(*kho_scratch); =20 @@ -1475,6 +1469,12 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 f= dt_len, goto out; } =20 + mem_map_phys =3D kho_get_mem_map_phys(fdt); + if (!mem_map_phys) { + err =3D -ENOENT; + goto out; + } + scratch =3D early_memremap(scratch_phys, scratch_len); if (!scratch) { pr_warn("setup: failed to memremap scratch (phys=3D0x%llx, len=3D%lld)\n= ", @@ -1515,6 +1515,7 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fd= t_len, =20 kho_in.fdt_phys =3D fdt_phys; kho_in.scratch_phys =3D scratch_phys; + kho_in.mem_map_phys =3D mem_map_phys; kho_scratch_cnt =3D scratch_cnt; pr_info("found kexec handover data.\n"); =20 base-commit: cc3aa43b44bdb43dfbac0fcb51c56594a11338a8 --=20 2.52.0.351.gbe84eed79e-goog