Linux s390 Architecture development
 help / color / mirror / Atom feed
* [PATCH 0/4] s390: Reintroduce support for DCACHE_WORD_ACCESS
@ 2026-07-16 14:14 Heiko Carstens
  2026-07-16 14:14 ` [PATCH 1/4] KVM: s390: pv: Use VM_SPARSE area for guest variable storage area Heiko Carstens
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Heiko Carstens @ 2026-07-16 14:14 UTC (permalink / raw)
  To: Alexander Gordeev, Sven Schnelle, Vasily Gorbik,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	David Hildenbrand
  Cc: linux-s390, kvm, linux-kernel

Support for DCACHE_WORD_ACCESS was recently removed [1] since it caused
problems with the incomplete handling of secure storage access
exceptions. It looked like fixing the exception handler would be a larger
effort; therefore support for DCACHE_WORD_ACCESS was removed as a work
around.

Address the potential problems that exist with secure storage access
exceptions and add support for DCACHE_WORD_ACCESS again.

In particular address the following problems:

- Reading the guest variable storage area via the /proc/kcore interface
  results in short reads. Address this by using a VM_SPARSE area for the
  guest variable storage area. VM_SPARSE areas will be handled like
  memory holes (zeros will be read).

- Fix handling of secure storage access exceptions in vmalloc area.

- Remove folio handling for secure storage access exceptions to avoid
  potential data corruption.

[1] 37540b8c287f ("s390: Revert support for DCACHE_WORD_ACCESS")

Heiko Carstens (4):
  KVM: s390: pv: Use VM_SPARSE area for guest variable storage area
  s390/mm: Fix handling of secure storage access exceptions in vmalloc area
  s390/mm: Remove folio handling for secure storage access exceptions
  s390: Add support for DCACHE_WORD_ACCESS (again)

 arch/s390/Kconfig                      |  1 +
 arch/s390/include/asm/asm-extable.h    |  4 ++
 arch/s390/include/asm/uv.h             |  2 +
 arch/s390/include/asm/word-at-a-time.h | 22 ++++++++++
 arch/s390/kernel/uv.c                  | 59 ++++++++++++++++++++++++++
 arch/s390/kvm/pv.c                     |  6 +--
 arch/s390/mm/extable.c                 | 18 ++++++++
 arch/s390/mm/fault.c                   | 10 ++---
 8 files changed, 112 insertions(+), 10 deletions(-)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] KVM: s390: pv: Use VM_SPARSE area for guest variable storage area
  2026-07-16 14:14 [PATCH 0/4] s390: Reintroduce support for DCACHE_WORD_ACCESS Heiko Carstens
@ 2026-07-16 14:14 ` Heiko Carstens
  2026-07-16 14:33   ` sashiko-bot
  2026-07-16 14:14 ` [PATCH 2/4] s390/mm: Fix handling of secure storage access exceptions in vmalloc area Heiko Carstens
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Heiko Carstens @ 2026-07-16 14:14 UTC (permalink / raw)
  To: Alexander Gordeev, Sven Schnelle, Vasily Gorbik,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	David Hildenbrand
  Cc: linux-s390, kvm, linux-kernel

The guest variable storage area is allocated with vmalloc and then
donated to the ultravisor. Any kernel access to that area will result
in a secure storage access exception (aka fault).

This is a problem if such a memory area is read via /proc/kcore. This
causes an exception via vread_iter() and results in an unexpected short
read. Avoid this by allocating a custom VM_SPARSE area. If such an area
is read, vread_iter() returns zeroes for the entire area.

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
 arch/s390/include/asm/uv.h |  2 ++
 arch/s390/kernel/uv.c      | 59 ++++++++++++++++++++++++++++++++++++++
 arch/s390/kvm/pv.c         |  6 ++--
 3 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
index d919e69662f5..153fed63adda 100644
--- a/arch/s390/include/asm/uv.h
+++ b/arch/s390/include/asm/uv.h
@@ -635,6 +635,8 @@ int s390_wiggle_split_folio(struct mm_struct *mm, struct folio *folio);
 int __make_folio_secure(struct folio *folio, struct uv_cb_header *uvcb);
 int uv_convert_from_secure(unsigned long paddr);
 int uv_convert_from_secure_folio(struct folio *folio);
+void *uv_alloc_stor_var(unsigned long size);
+void uv_free_stor_var(void *stor_var);
 
 void setup_uv(void);
 
diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c
index a284f98d9716..98a7f988fc69 100644
--- a/arch/s390/kernel/uv.c
+++ b/arch/s390/kernel/uv.c
@@ -16,6 +16,7 @@
 #include <linux/swap.h>
 #include <linux/pagewalk.h>
 #include <linux/backing-dev.h>
+#include <linux/vmalloc.h>
 #include <asm/facility.h>
 #include <asm/sections.h>
 #include <asm/uv.h>
@@ -209,6 +210,64 @@ int uv_convert_from_secure_pte(pte_t pte)
 	return uv_convert_from_secure_folio(pfn_folio(pte_pfn(pte)));
 }
 
+static int uv_free_range_cb(pte_t *ptep, unsigned long addr, void *data)
+{
+	pte_t pte = ptep_get(ptep);
+
+	if (!pte_present(pte))
+		return 0;
+	__free_page(pte_page(pte));
+	return 0;
+}
+
+void uv_free_stor_var(void *stor_var)
+{
+	unsigned long addr, size;
+	struct vm_struct *area;
+
+	if (!stor_var)
+		return;
+	area = find_vm_area(stor_var);
+	if (WARN_ON_ONCE(!area || !(area->flags & VM_SPARSE)))
+		return;
+	size = get_vm_area_size(area);
+	addr = (unsigned long)area->addr;
+	apply_to_existing_page_range(&init_mm, addr, size, uv_free_range_cb, NULL);
+	free_vm_area(area);
+}
+EXPORT_SYMBOL_FOR_MODULES(uv_free_stor_var, "kvm");
+
+static int uv_alloc_range_cb(pte_t *ptep, unsigned long addr, void *data)
+{
+	struct page *page;
+	pte_t pte;
+
+	page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
+	if (!page)
+		return -ENOMEM;
+	pte = __pte(page_to_phys(page) | pgprot_val(PAGE_KERNEL));
+	set_pte(ptep, pte);
+	return 0;
+}
+
+void *uv_alloc_stor_var(unsigned long size)
+{
+	struct vm_struct *area;
+	unsigned long addr;
+
+	area = get_vm_area(size, VM_SPARSE);
+	if (!area)
+		return NULL;
+	addr = (unsigned long)area->addr;
+	if (apply_to_page_range(&init_mm, addr, size, uv_alloc_range_cb, NULL))
+		goto out;
+	return area->addr;
+out:
+	uv_free_stor_var(area->addr);
+	return NULL;
+}
+EXPORT_SYMBOL_FOR_MODULES(uv_alloc_stor_var, "kvm");
+
 /*
  * Calculate the expected ref_count for a folio that would otherwise have no
  * further pins. This was cribbed from similar functions in other places in
diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c
index 1beacc841ca8..dc5ac29b4c31 100644
--- a/arch/s390/kvm/pv.c
+++ b/arch/s390/kvm/pv.c
@@ -337,7 +337,7 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
 /* only free resources when the destroy was successful */
 static void kvm_s390_pv_dealloc_vm(struct kvm *kvm)
 {
-	vfree(kvm->arch.pv.stor_var);
+	uv_free_stor_var(kvm->arch.pv.stor_var);
 	free_pages(kvm->arch.pv.stor_base,
 		   get_order(uv_info.guest_base_stor_len));
 	kvm_s390_clear_pv_state(kvm);
@@ -369,7 +369,7 @@ static int kvm_s390_pv_alloc_vm(struct kvm *kvm)
 	/* Allocate variable storage */
 	vlen = ALIGN(virt * ((npages * PAGE_SIZE) / HPAGE_SIZE), PAGE_SIZE);
 	vlen += uv_info.guest_virt_base_stor_len;
-	kvm->arch.pv.stor_var = vzalloc(vlen);
+	kvm->arch.pv.stor_var = uv_alloc_stor_var(vlen);
 	if (!kvm->arch.pv.stor_var)
 		goto out_err;
 	return 0;
@@ -414,7 +414,7 @@ static int kvm_s390_pv_dispose_one_leftover(struct kvm *kvm,
 	 */
 	free_pages(leftover->stor_base, get_order(uv_info.guest_base_stor_len));
 	free_pages(leftover->old_gmap_table, CRST_ALLOC_ORDER);
-	vfree(leftover->stor_var);
+	uv_free_stor_var(leftover->stor_var);
 done_fast:
 	atomic_dec(&kvm->mm->context.protected_count);
 	return 0;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] s390/mm: Fix handling of secure storage access exceptions in vmalloc area
  2026-07-16 14:14 [PATCH 0/4] s390: Reintroduce support for DCACHE_WORD_ACCESS Heiko Carstens
  2026-07-16 14:14 ` [PATCH 1/4] KVM: s390: pv: Use VM_SPARSE area for guest variable storage area Heiko Carstens
@ 2026-07-16 14:14 ` Heiko Carstens
  2026-07-16 14:14 ` [PATCH 3/4] s390/mm: Remove folio handling for secure storage access exceptions Heiko Carstens
  2026-07-16 14:14 ` [PATCH 4/4] s390: Add support for DCACHE_WORD_ACCESS (again) Heiko Carstens
  3 siblings, 0 replies; 7+ messages in thread
From: Heiko Carstens @ 2026-07-16 14:14 UTC (permalink / raw)
  To: Alexander Gordeev, Sven Schnelle, Vasily Gorbik,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	David Hildenbrand
  Cc: linux-s390, kvm, linux-kernel

Secure storage access exceptions in vmalloc area need to be handled
separately since folio_try_get() or virt_to_phys() do not work on such
addresses. Given that there cannot be a valid access let such exceptions
fail immediately. The kernel will either fixup or crash.

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
 arch/s390/mm/fault.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 028aeb9c48d6..392e46742039 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -438,6 +438,8 @@ void do_secure_storage_access(struct pt_regs *regs)
 		panic("Unexpected PGM 0x3d with TEID bit 61=0");
 	}
 	if (is_kernel_fault(regs)) {
+		if (is_vmalloc_addr((void *)addr))
+			return handle_fault_error_nolock(regs, 0);
 		folio = virt_to_folio((void *)addr);
 		if (unlikely(!folio_try_get(folio)))
 			return;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] s390/mm: Remove folio handling for secure storage access exceptions
  2026-07-16 14:14 [PATCH 0/4] s390: Reintroduce support for DCACHE_WORD_ACCESS Heiko Carstens
  2026-07-16 14:14 ` [PATCH 1/4] KVM: s390: pv: Use VM_SPARSE area for guest variable storage area Heiko Carstens
  2026-07-16 14:14 ` [PATCH 2/4] s390/mm: Fix handling of secure storage access exceptions in vmalloc area Heiko Carstens
@ 2026-07-16 14:14 ` Heiko Carstens
  2026-07-16 14:19   ` David Hildenbrand (Arm)
  2026-07-16 14:14 ` [PATCH 4/4] s390: Add support for DCACHE_WORD_ACCESS (again) Heiko Carstens
  3 siblings, 1 reply; 7+ messages in thread
From: Heiko Carstens @ 2026-07-16 14:14 UTC (permalink / raw)
  To: Alexander Gordeev, Sven Schnelle, Vasily Gorbik,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	David Hildenbrand
  Cc: linux-s390, kvm, linux-kernel

Remove folio handling for secure storage access exceptions that happen
via the kernel mapping. Using folio_try_get() for exceptions via the
kernel mapping is racy: for example such an exception may happen on one
CPU, while a different CPU frees the corresponding page. Subsequently the
page can be part of a folio of different size, before the faulting CPU
executes folio_try_get(). This may lead to data corruption.

As of now this scenario does not seem to be possible, however with the
upcoming load_unaligned_zeropad() this is possible.

As a side effect PG_arch_1 is not cleared anymore for such faults via the
kernel mapping. However given that this bit is over-indicating it
shouldn't matter.

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
 arch/s390/mm/fault.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 392e46742039..db77c8c0023e 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -440,13 +440,7 @@ void do_secure_storage_access(struct pt_regs *regs)
 	if (is_kernel_fault(regs)) {
 		if (is_vmalloc_addr((void *)addr))
 			return handle_fault_error_nolock(regs, 0);
-		folio = virt_to_folio((void *)addr);
-		if (unlikely(!folio_try_get(folio)))
-			return;
-		rc = uv_convert_from_secure(folio_to_phys(folio));
-		if (!rc)
-			clear_bit(PG_arch_1, &folio->flags.f);
-		folio_put(folio);
+		rc = uv_convert_from_secure(__pa(addr));
 		/*
 		 * There are some valid fixup types for kernel
 		 * accesses to donated secure memory. zeropad is one
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] s390: Add support for DCACHE_WORD_ACCESS (again)
  2026-07-16 14:14 [PATCH 0/4] s390: Reintroduce support for DCACHE_WORD_ACCESS Heiko Carstens
                   ` (2 preceding siblings ...)
  2026-07-16 14:14 ` [PATCH 3/4] s390/mm: Remove folio handling for secure storage access exceptions Heiko Carstens
@ 2026-07-16 14:14 ` Heiko Carstens
  3 siblings, 0 replies; 7+ messages in thread
From: Heiko Carstens @ 2026-07-16 14:14 UTC (permalink / raw)
  To: Alexander Gordeev, Sven Schnelle, Vasily Gorbik,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	David Hildenbrand
  Cc: linux-s390, kvm, linux-kernel

Implement load_unaligned_zeropad() and enable DCACHE_WORD_ACCESS to
speed up string operations in fs/dcache.c and fs/namei.c.

With the secure storage access exception cases addressed, add support
for DCACHE_WORD_ACCESS again.

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
 arch/s390/Kconfig                      |  1 +
 arch/s390/include/asm/asm-extable.h    |  4 ++++
 arch/s390/include/asm/word-at-a-time.h | 22 ++++++++++++++++++++++
 arch/s390/mm/extable.c                 | 18 ++++++++++++++++++
 4 files changed, 45 insertions(+)

diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 84404e6778d5..fe81c539ef2f 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -163,6 +163,7 @@ config S390
 	select ARCH_WANTS_THP_SWAP
 	select BUILDTIME_TABLE_SORT
 	select CLONE_BACKWARDS2
+	select DCACHE_WORD_ACCESS if !KMSAN
 	select DYNAMIC_FTRACE if FUNCTION_TRACER
 	select FUNCTION_ALIGNMENT_8B if CC_IS_GCC
 	select FUNCTION_ALIGNMENT_16B if !CC_IS_GCC
diff --git a/arch/s390/include/asm/asm-extable.h b/arch/s390/include/asm/asm-extable.h
index 99748c20e767..d23ea0c94e4e 100644
--- a/arch/s390/include/asm/asm-extable.h
+++ b/arch/s390/include/asm/asm-extable.h
@@ -12,6 +12,7 @@
 #define EX_TYPE_UA_FAULT	3
 #define EX_TYPE_UA_LOAD_REG	5
 #define EX_TYPE_UA_LOAD_REGPAIR	6
+#define EX_TYPE_ZEROPAD		7
 #define EX_TYPE_FPC		8
 #define EX_TYPE_UA_MVCOS_TO	9
 #define EX_TYPE_UA_MVCOS_FROM	10
@@ -79,6 +80,9 @@
 #define EX_TABLE_UA_LOAD_REGPAIR(_fault, _target, _regerr, _regzero)	\
 	__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REGPAIR, _regerr, _regzero, 0)
 
+#define EX_TABLE_ZEROPAD(_fault, _target, _regdata, _regaddr)		\
+	__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_ZEROPAD, _regdata, _regaddr, 0)
+
 #define EX_TABLE_FPC(_fault, _target)					\
 	__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FPC, __stringify(%%r0), __stringify(%%r0), 0)
 
diff --git a/arch/s390/include/asm/word-at-a-time.h b/arch/s390/include/asm/word-at-a-time.h
index e9287036392d..eaa19dee7699 100644
--- a/arch/s390/include/asm/word-at-a-time.h
+++ b/arch/s390/include/asm/word-at-a-time.h
@@ -4,6 +4,7 @@
 
 #include <linux/bitops.h>
 #include <linux/wordpart.h>
+#include <asm/asm-extable.h>
 #include <asm/bitsperlong.h>
 
 struct word_at_a_time {
@@ -40,4 +41,25 @@ static inline unsigned long zero_bytemask(unsigned long data)
 	return ~1UL << data;
 }
 
+/*
+ * Load an unaligned word from kernel space.
+ *
+ * In the (very unlikely) case of the word being a page-crosser
+ * and the next page not being mapped, take the exception and
+ * return zeroes in the non-existing part.
+ */
+static inline unsigned long load_unaligned_zeropad(const void *addr)
+{
+	unsigned long data;
+
+	asm_inline volatile(
+		"0:	lg	%[data],0(%[addr])\n"
+		"1:	nopr	%%r7\n"
+		EX_TABLE_ZEROPAD(0b, 1b, %[data], %[addr])
+		EX_TABLE_ZEROPAD(1b, 1b, %[data], %[addr])
+		: [data] "=d" (data)
+		: [addr] "a" (addr), "m" (*(unsigned long *)addr));
+	return data;
+}
+
 #endif /* _ASM_WORD_AT_A_TIME_H */
diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c
index 063b4346742d..7498e858c401 100644
--- a/arch/s390/mm/extable.c
+++ b/arch/s390/mm/extable.c
@@ -50,6 +50,22 @@ static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex,
 	return true;
 }
 
+static bool ex_handler_zeropad(const struct exception_table_entry *ex, struct pt_regs *regs)
+{
+	unsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
+	unsigned int reg_data = FIELD_GET(EX_DATA_REG_ERR, ex->data);
+	unsigned long data, addr, offset;
+
+	addr = regs->gprs[reg_addr];
+	offset = addr & (sizeof(unsigned long) - 1);
+	addr &= ~(sizeof(unsigned long) - 1);
+	data = *(unsigned long *)addr;
+	data <<= BITS_PER_BYTE * offset;
+	regs->gprs[reg_data] = data;
+	regs->psw.addr = extable_fixup(ex);
+	return true;
+}
+
 static bool ex_handler_fpc(const struct exception_table_entry *ex, struct pt_regs *regs)
 {
 	fpu_sfpc(0);
@@ -118,6 +134,8 @@ bool fixup_exception(struct pt_regs *regs)
 		return ex_handler_ua_load_reg(ex, false, regs);
 	case EX_TYPE_UA_LOAD_REGPAIR:
 		return ex_handler_ua_load_reg(ex, true, regs);
+	case EX_TYPE_ZEROPAD:
+		return ex_handler_zeropad(ex, regs);
 	case EX_TYPE_FPC:
 		return ex_handler_fpc(ex, regs);
 	case EX_TYPE_UA_MVCOS_TO:
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/4] s390/mm: Remove folio handling for secure storage access exceptions
  2026-07-16 14:14 ` [PATCH 3/4] s390/mm: Remove folio handling for secure storage access exceptions Heiko Carstens
@ 2026-07-16 14:19   ` David Hildenbrand (Arm)
  0 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-16 14:19 UTC (permalink / raw)
  To: Heiko Carstens, Alexander Gordeev, Sven Schnelle, Vasily Gorbik,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda
  Cc: linux-s390, kvm, linux-kernel

On 7/16/26 16:14, Heiko Carstens wrote:
> Remove folio handling for secure storage access exceptions that happen
> via the kernel mapping. Using folio_try_get() for exceptions via the
> kernel mapping is racy: for example such an exception may happen on one
> CPU, while a different CPU frees the corresponding page. Subsequently the
> page can be part of a folio of different size, before the faulting CPU
> executes folio_try_get(). This may lead to data corruption.

Right, that's why one would have to re-verify whether the page is still part of
the folio afterwards.

-- 
Cheers,

David

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/4] KVM: s390: pv: Use VM_SPARSE area for guest variable storage area
  2026-07-16 14:14 ` [PATCH 1/4] KVM: s390: pv: Use VM_SPARSE area for guest variable storage area Heiko Carstens
@ 2026-07-16 14:33   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-16 14:33 UTC (permalink / raw)
  To: Heiko Carstens
  Cc: linux-s390, Heiko Carstens, Alexander Gordeev, Vasily Gorbik, kvm

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Physical pages are freed to the buddy allocator before their corresponding page table entries are cleared and the TLB is flushed, creating a Use-After-Free vulnerability window.
- [High] Passing an unaligned `size` to `uv_alloc_stor_var()` causes an infinite loop in the kernel page table walker.
--

--- Patch [1]: [PATCH 1/4] KVM: s390: pv: Use VM_SPARSE area for guest variable storage area ---
commit fd3cc6954f3085a22cae9f0932705a2913ea0050
Author: Heiko Carstens <hca@linux.ibm.com>

KVM: s390: pv: Use VM_SPARSE area for guest variable storage area

The guest variable storage area is allocated with vmalloc and then
donated to the ultravisor. This patch allocates it via a custom
VM_SPARSE area to avoid unexpected short reads via /proc/kcore.

> diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c
> index a284f98d97168..98a7f988fc691 100644
> --- a/arch/s390/kernel/uv.c
> +++ b/arch/s390/kernel/uv.c

[ ... ]

> @@ -209,6 +210,64 @@ int uv_convert_from_secure_pte(pte_t pte)
>  	return uv_convert_from_secure_folio(pfn_folio(pte_pfn(pte)));
>  }
>  
> +static int uv_free_range_cb(pte_t *ptep, unsigned long addr, void *data)
> +{
> +	pte_t pte = ptep_get(ptep);
> +
> +	if (!pte_present(pte))
> +		return 0;
> +	__free_page(pte_page(pte));
> +	return 0;
> +}
> +
> +void uv_free_stor_var(void *stor_var)
> +{
> +	unsigned long addr, size;
> +	struct vm_struct *area;
> +
> +	if (!stor_var)
> +		return;
> +	area = find_vm_area(stor_var);
> +	if (WARN_ON_ONCE(!area || !(area->flags & VM_SPARSE)))
> +		return;
> +	size = get_vm_area_size(area);
> +	addr = (unsigned long)area->addr;
> +	apply_to_existing_page_range(&init_mm, addr, size, uv_free_range_cb, NULL);
> +	free_vm_area(area);

[Severity: High]
Does this create a Use-After-Free window during VM teardown?

In uv_free_stor_var(), we call apply_to_existing_page_range() which invokes
uv_free_range_cb() for each page. The callback frees the physical page
directly to the buddy allocator via __free_page() while the PTE remains
fully present and writable in the init_mm page tables.

After all pages are freed, free_vm_area() is called to clear the PTEs and
flush the TLB. If a freed page is immediately reallocated to another
subsystem, can concurrent accesses via the stale vmalloc alias read or
overwrite the newly reallocated page before free_vm_area() completes?

> +}
> +EXPORT_SYMBOL_FOR_MODULES(uv_free_stor_var, "kvm");

[ ... ]

> +void *uv_alloc_stor_var(unsigned long size)
> +{
> +	struct vm_struct *area;
> +	unsigned long addr;
> +
> +	area = get_vm_area(size, VM_SPARSE);
> +	if (!area)
> +		return NULL;
> +	addr = (unsigned long)area->addr;
> +	if (apply_to_page_range(&init_mm, addr, size, uv_alloc_range_cb, NULL))

[Severity: High]
If an unaligned size is passed to uv_alloc_stor_var(), could this cause an
infinite loop in the page table walker?

The size parameter is passed directly to apply_to_page_range(). The internal
page table walker loop relies on the end boundary being exactly page-aligned
to terminate:

	do {
		...
	} while (pte++, addr += PAGE_SIZE, addr != end);

If size is not a multiple of PAGE_SIZE, addr will increment past end without
matching it, looping indefinitely over the page tables.

Should we pass the page-aligned size of the allocated VM area instead, perhaps
by using get_vm_area_size(area) or explicitly aligning size beforehand?

> +		goto out;
> +	return area->addr;
> +out:
> +	uv_free_stor_var(area->addr);
> +	return NULL;
> +}
> +EXPORT_SYMBOL_FOR_MODULES(uv_alloc_stor_var, "kvm");

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260716141436.2125703-1-hca@linux.ibm.com?part=1

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-07-16 14:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16 14:14 [PATCH 0/4] s390: Reintroduce support for DCACHE_WORD_ACCESS Heiko Carstens
2026-07-16 14:14 ` [PATCH 1/4] KVM: s390: pv: Use VM_SPARSE area for guest variable storage area Heiko Carstens
2026-07-16 14:33   ` sashiko-bot
2026-07-16 14:14 ` [PATCH 2/4] s390/mm: Fix handling of secure storage access exceptions in vmalloc area Heiko Carstens
2026-07-16 14:14 ` [PATCH 3/4] s390/mm: Remove folio handling for secure storage access exceptions Heiko Carstens
2026-07-16 14:19   ` David Hildenbrand (Arm)
2026-07-16 14:14 ` [PATCH 4/4] s390: Add support for DCACHE_WORD_ACCESS (again) Heiko Carstens

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox