Linux s390 Architecture development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Claudio Imbrenda" <imbrenda@linux.ibm.com>
Cc: "Alexander Gordeev" <agordeev@linux.ibm.com>,
	kvm@vger.kernel.org,
	"Christian Borntraeger" <borntraeger@linux.ibm.vom>,
	"Vasily Gorbik" <gor@linux.ibm.com>,
	"Heiko Carstens" <hca@linux.ibm.com>,
	linux-s390@vger.kernel.org
Subject: Re: [PATCH v2 4/9] KVM: s390: Fix dirty marking in adapter_indicators_set*()
Date: Wed, 12 Aug 2026 11:00:58 +0000	[thread overview]
Message-ID: <20260812110058.EBD3D1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260812104436.109741-5-imbrenda@linux.ibm.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Replacing set_page_dirty_lock() with set_page_dirty() on GUP-pinned pages introduces a Use-After-Free vulnerability due to a race with file truncation.
- [High] Ordering mark_page_dirty() before memory modification creates a race condition with dirty log harvesting, risking lost updates during live migration.
--

--- Patch [4]: [PATCH v2 4/9] KVM: s390: Fix dirty marking in adapter_indicators_set*() ---
commit 8bb6adeda8416869b198540515723990915f8390
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>

KVM: s390: Fix dirty marking in adapter_indicators_set*()

This commit updates dirty page marking for adapter indicators in KVM s390.
It adds missing calls to set_page_dirty() and mark_page_dirty() in the fast
path and reorganizes the slow path, replacing set_page_dirty_lock() with
set_page_dirty() for pinned pages.

> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index 608ff95d53bac..e79f636c7544d 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
[ ... ]
> @@ -2997,21 +2999,20 @@ static int adapter_indicators_set(struct kvm *kvm,
>  		ind_page = pin_map_page(kvm, adapter_int->ind_addr, 0);
>  		if (!ind_page)
>  			return -1;
> -		idx = srcu_read_lock(&kvm->srcu);
>  		map = page_address(ind_page);
>  		bit = get_ind_bit(adapter_int->ind_addr,
>  				  adapter_int->ind_offset, adapter->swap);
>  		set_bit(bit, map);
> -		mark_page_dirty(kvm, adapter_int->ind_gaddr >> PAGE_SHIFT);
> -		set_page_dirty_lock(ind_page);
> -		srcu_read_unlock(&kvm->srcu, idx);
> +		set_page_dirty(ind_page);

[Severity: High]
Is it safe to replace set_page_dirty_lock() with set_page_dirty() here?

For short-term GUP-pinned memory like this ind_page, the memory can be backed
by any filesystem. Without the folio lock, a concurrent file truncation could
unmap the folio and free the mapping.

If set_page_dirty() reads folio->mapping concurrently, could it dereference
freed memory when calling mapping->a_ops->dirty_folio()?

>  		unpin_user_page(ind_page);
>  	} else {
>  		map = page_address(ind_info->page);
>  		bit = get_ind_bit(ind_info->addr, adapter_int->ind_offset, adapter->swap);
>  		set_bit(bit, map);
> +		set_page_dirty(ind_info->page);
>  		spin_unlock_irqrestore(&adapter->maps_lock, flags);
>  	}
> +	mark_page_dirty(kvm, gpa_to_gfn(adapter_int->ind_gaddr));
>  
>  	spin_lock_irqsave(&adapter->maps_lock, flags);
>  	summary_info = get_map_info(adapter, adapter_int->summary_addr);
> @@ -3020,22 +3021,21 @@ static int adapter_indicators_set(struct kvm *kvm,
>  		summary_page = pin_map_page(kvm, adapter_int->summary_addr, 0);
>  		if (WARN_ON_ONCE(!summary_page))
>  			return -1;
> -		idx = srcu_read_lock(&kvm->srcu);
>  		map = page_address(summary_page);
>  		bit = get_ind_bit(adapter_int->summary_addr,
>  				  adapter_int->summary_offset, adapter->swap);
>  		summary_set = test_and_set_bit(bit, map);
> -		mark_page_dirty(kvm, adapter_int->summary_gaddr >> PAGE_SHIFT);
> -		set_page_dirty_lock(summary_page);
> -		srcu_read_unlock(&kvm->srcu, idx);
> +		set_page_dirty(summary_page);

[Severity: High]
Similarly, could calling set_page_dirty() instead of set_page_dirty_lock() on
the GUP-pinned summary_page lead to a use-after-free if the file is truncated
concurrently?

>  		unpin_user_page(summary_page);
>  	} else {
>  		map = page_address(summary_info->page);
>  		bit = get_ind_bit(summary_info->addr, adapter_int->summary_offset,
>  				  adapter->swap);
>  		summary_set = test_and_set_bit(bit, map);
> +		set_page_dirty(summary_info->page);
>  		spin_unlock_irqrestore(&adapter->maps_lock, flags);
>  	}
> +	mark_page_dirty(kvm, gpa_to_gfn(adapter_int->summary_gaddr));
>  
>  	return summary_set ? 0 : 1;
>  }
> @@ -3045,26 +3045,30 @@ static int adapter_indicators_set_fast(struct kvm *kvm,
>  				       struct kvm_s390_adapter_int *adapter_int,
>  				       int setbit)
>  {
[ ... ]
>  	map = page_address(ind_info->page);
>  	bit = get_ind_bit(ind_info->addr, adapter_int->ind_offset, adapter->swap);
> -	if (setbit)
> +	if (setbit) {
> +		mark_page_dirty(kvm, gpa_to_gfn(adapter_int->ind_gaddr));
> +		set_page_dirty(ind_info->page);
>  		set_bit(bit, map);
> +	}

[Severity: High]
Does calling mark_page_dirty() before actually modifying the memory with
set_bit() create a race condition with dirty log harvesting?

If userspace harvests the KVM dirty log between mark_page_dirty() and
set_bit(), it might clear the dirty bit in KVM's tracking and read the old
unmodified page.

When set_bit() then executes, the page would no longer be marked dirty, and
the change wouldn't be migrated to the destination.

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

  reply	other threads:[~2026-08-12 11:00 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-12 10:44 [PATCH v2 0/9] KVM: s390: And then... even more fixes again Claudio Imbrenda
2026-08-12 10:44 ` [PATCH v2 1/9] KVM: s390: Properly handle NULL pointer in dat_cond_set_storage_key() Claudio Imbrenda
2026-08-12 10:55   ` sashiko-bot
2026-08-12 10:44 ` [PATCH v2 2/9] KVM: s390: Use srcu in kvm_arch_vcpu_unlocked_ioctl() Claudio Imbrenda
2026-08-12 10:58   ` sashiko-bot
2026-08-12 11:02   ` Christoph Schlameuss
2026-08-12 10:44 ` [PATCH v2 3/9] KVM: s390: Fix get_all_floating_irqs() Claudio Imbrenda
2026-08-12 10:55   ` Christian Borntraeger
2026-08-12 10:55   ` sashiko-bot
2026-08-12 14:06   ` Christoph Schlameuss
2026-08-12 10:44 ` [PATCH v2 4/9] KVM: s390: Fix dirty marking in adapter_indicators_set*() Claudio Imbrenda
2026-08-12 11:00   ` sashiko-bot [this message]
2026-08-12 11:03   ` Christian Borntraeger
2026-08-12 11:37     ` Claudio Imbrenda
2026-08-12 10:44 ` [PATCH v2 5/9] KVM: s390: Fix pgste_get_trylock_multiple() Claudio Imbrenda
2026-08-12 10:50   ` sashiko-bot
2026-08-12 11:11   ` Christoph Schlameuss
2026-08-12 10:44 ` [PATCH v2 6/9] KVM: s390: Fix IRQ injection with SIGP Stop and Store Status Claudio Imbrenda
2026-08-12 10:53   ` sashiko-bot
2026-08-12 12:59   ` Christoph Schlameuss
2026-08-12 13:11     ` Claudio Imbrenda
2026-08-12 13:23       ` Christoph Schlameuss
2026-08-12 10:44 ` [PATCH v2 7/9] KVM: s390: Fix kvm_s390_clear_pv_state() Claudio Imbrenda
2026-08-12 10:53   ` sashiko-bot
2026-08-12 13:02   ` Christoph Schlameuss
2026-08-12 10:44 ` [PATCH v2 8/9] KVM: s390: Fix potential tiny kernel stack leak Claudio Imbrenda
2026-08-12 10:53   ` sashiko-bot
2026-08-12 13:14   ` Christoph Schlameuss
2026-08-12 10:44 ` [PATCH v2 9/9] KVM: s390: Fix _gaccess_shadow_fault() Claudio Imbrenda
2026-08-12 11:47   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260812110058.EBD3D1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=agordeev@linux.ibm.com \
    --cc=borntraeger@linux.ibm.vom \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox