All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: Oliver Upton <oliver.upton@linux.dev>
Cc: kvmarm@lists.linux.dev, Marc Zyngier <maz@kernel.org>,
	 James Morse <james.morse@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	 Zenghui Yu <yuzenghui@huawei.com>,
	Eric Auger <eric.auger@redhat.com>,
	 Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [PATCH 01/20] KVM: Treat the device list as an rculist
Date: Wed, 28 Feb 2024 11:13:52 -0800	[thread overview]
Message-ID: <Zd-F8F9OTehNoQiq@google.com> (raw)
In-Reply-To: <Zd92fobEy4HFOb24@linux.dev>

On Wed, Feb 28, 2024, Oliver Upton wrote:
> On Wed, Feb 28, 2024 at 09:18:28AM -0800, Sean Christopherson wrote:
> > On Tue, Feb 27, 2024, Oliver Upton wrote:
> > > A subsequent change to KVM/arm64 will necessitate walking the device
> > > list outside of the kvm->lock. Prepare by converting to an rculist.
> > > Note that this has zero effect the destruction path, as every reader
> > > should be protected by a valid reference on the KVM struct.
> > 
> > This should leave the destruction path alone then.  Simply using list_del_rcu()
> > doesn't convert this to an rculist, you need to actually synchronize against RCU
> > for this to have any meaning/protection.
> 
> Did anything about this diff give you the impression this wasn't
> thoroughly understood?

I'm taking exception to the "Prepare by converting to an rculist." statement.
This is not an RCU-protected list, it's a list that abuses rcu_list_add() and
list_for_each_rcu() to allow readers to run concurrently with insertion.  E.g.
IIUC, if it weren't for PROVE_RCU, the rcu_read_(un)lock() in the reader could
be omitted and everything would work just fine.

Ah, but it's a moot point, because kvm_device_release() does delete from the list,
and does not do so in an RCU-safe manner.  So that needs to be fixed, and then
this is indeed an RCU-protected list.

  static int kvm_device_release(struct inode *inode, struct file *filp)
  {
	struct kvm_device *dev = filp->private_data;
	struct kvm *kvm = dev->kvm;

	if (dev->ops->release) {
		mutex_lock(&kvm->lock);
		list_del(&dev->vm_node);
		dev->ops->release(dev);
		mutex_unlock(&kvm->lock);
	}

	kvm_put_kvm(kvm);
	return 0;
  }

> > The above alludes to this, and the
> > comment in kvm_destroy_devices() helps a little, but the code itself is actively
> > misleading.
> 
> Which is what comments are for. I deliberately chose to use a consistent
> programming model (albeit unnecessary to anyone who actually understands
> how this works) with the hope that _if_ someone comes along and needs to
> delete from the list later on they consider the requirements of RCU
> protection.

Ya, I see where you're coming from.

> list_del() or list_del_rcu() will fail in an equally-miserable manner if
> the previously stated expectation of readers is violated. Poisoning the
> forward pointer would be nice from a debugging POV, but readers could
> still hit a use-after-free.

My primary concern is not what happens on failure, I'm concerned about misleading
readers by implying that this is a proper RCU-protected list.  But as above, that's
a moot point.

As far as the failure mode, my preference is to poison the forward pointer.  It's
not just debug friendly; hitting a fault (#GP on x86) is a "safer" failure mode
than UAF, e.g. UAF could result in data corruption if the freed memory is
re-allocated before the rogue write happens.

> > I don't know how I feel about using list_add_rcu() in combination with list_del(),
> > but I like it a lot better than using list_del_rcu() in a way that is blatantly
> > wrong.
> > 
> > So if we don't have a better option, I would much rather do only the list_add_rcu(),
> > and add a comment _there_ explaining why KVM inserts with RCU protection, but
> > frees using regular ol' list_del().
> 
> Describing our destruction rules on the insertion path?

I was advocating we document the insertion rules.  The destruction rules for devices
aren't novel, they follow all of KVM's existing rules for destroying a VM. 

But again, moot point, because I was looking at this from the perspetive of a
list that isn't truly RCU-protected.  With this being a true RCU-protected list,
I agree that adding a comment to the insertion path would be redundant/unnecessary.

> I feel like that borders on contempt for the reader.

IMO, RCU is one of the most difficult things to use _safely_.  (Ab)Using RCU in
a way that _looks_ unsafe is setting people up to fail.

Bug once again, moot point :-)

> I'm happy to leave list_del() as-is but I'm going to insist on documenting
> destructor behavior in the destructor.

Ya.

  reply	other threads:[~2024-02-28 19:13 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-27 22:42 [PATCH 00/20] KVM: arm64: Transition to a per-ITS translation cache Oliver Upton
2024-02-27 22:42 ` [PATCH 01/20] KVM: Treat the device list as an rculist Oliver Upton
2024-02-28 13:33   ` Paolo Bonzini
2024-02-28 17:18   ` Sean Christopherson
2024-02-28 18:07     ` Oliver Upton
2024-02-28 19:13       ` Sean Christopherson [this message]
2024-02-28 19:31         ` Oliver Upton
2024-02-28 20:23           ` Paolo Bonzini
2024-02-28 21:07             ` Oliver Upton
2024-02-27 22:42 ` [PATCH 02/20] KVM: arm64: vgic-its: Walk LPI xarray in its_sync_lpi_pending_table() Oliver Upton
2024-02-27 22:42 ` [PATCH 03/20] KVM: arm64: vgic-its: Walk LPI xarray in vgic_its_invall() Oliver Upton
2024-02-27 22:42 ` [PATCH 04/20] KVM: arm64: vgic-its: Walk LPI xarray in vgic_its_cmd_handle_movall() Oliver Upton
2024-02-27 22:42 ` [PATCH 05/20] KVM: arm64: vgic-debug: Use an xarray mark for debug iterator Oliver Upton
2024-02-27 22:42 ` [PATCH 06/20] KVM: arm64: vgic-its: Get rid of vgic_copy_lpi_list() Oliver Upton
2024-02-27 22:42 ` [PATCH 07/20] KVM: arm64: vgic-its: Scope translation cache invalidations to an ITS Oliver Upton
2024-02-27 22:42 ` [PATCH 08/20] KVM: arm64: vgic-its: Spin off helper for finding ITS by doorbell addr Oliver Upton
2024-02-27 22:42 ` [PATCH 09/20] KVM: arm64: vgic-its: Maintain a translation cache per ITS Oliver Upton
2024-02-27 22:42 ` [PATCH 10/20] KVM: arm64: vgic-its: Use the per-ITS translation cache for injection Oliver Upton
2024-02-27 22:42 ` [PATCH 11/20] KVM: arm64: vgic-its: Rip out the global translation cache Oliver Upton
2024-02-27 22:42 ` [PATCH 12/20] KVM: arm64: vgic-its: Get rid of the lpi_list_lock Oliver Upton
2024-02-27 22:42 ` [PATCH 13/20] KVM: selftests: Align with kernel's GIC definitions Oliver Upton
2024-02-27 22:42 ` [PATCH 14/20] KVM: selftests: Standardise layout of GIC frames Oliver Upton
2024-02-27 22:42 ` [PATCH 15/20] KVM: selftests: Add quadword MMIO accessors Oliver Upton
2024-02-27 22:42 ` [PATCH 16/20] KVM: selftests: Add a minimal library for interacting with an ITS Oliver Upton
2024-02-27 22:42 ` [PATCH 17/20] KVM: selftests: Add helper for enabling LPIs on a redistributor Oliver Upton
2024-02-27 22:42 ` [PATCH 18/20] KVM: selftests: Use MPIDR_HWID_BITMASK from cputype.h Oliver Upton
2024-02-27 22:42 ` [PATCH 19/20] KVM: selftests: Hack in support for aligned page allocations Oliver Upton
2024-02-27 22:42 ` [PATCH 20/20] KVM: selftests: Add stress test for LPI injection Oliver Upton

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=Zd-F8F9OTehNoQiq@google.com \
    --to=seanjc@google.com \
    --cc=eric.auger@redhat.com \
    --cc=james.morse@arm.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=maz@kernel.org \
    --cc=oliver.upton@linux.dev \
    --cc=pbonzini@redhat.com \
    --cc=suzuki.poulose@arm.com \
    --cc=yuzenghui@huawei.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.