From: Andreas Hindborg <a.hindborg@kernel.org>
To: "Younes Akhouayri via B4 Relay"
<devnull+git.younes.io@kernel.org>,
"Breno Leitao" <leitao@debian.org>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Onur Özkan" <work@onurozkan.dev>
Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
Younes Akhouayri <git@younes.io>
Subject: Re: [PATCH v3] rust: configfs: fix object initialization cleanup
Date: Wed, 23 Sep 2026 11:54:27 +0200 [thread overview]
Message-ID: <87ld8s2sz0.fsf@t14s.mail-host-address-is-not-set> (raw)
In-Reply-To: <20260818-fix-rust-configfs-registration-state-v1-v3-1-28b5cbfe0a72@younes.io>
Younes Akhouayri via B4 Relay <devnull+git.younes.io@kernel.org> writes:
> From: Younes Akhouayri <git@younes.io>
>
> Subsystem::new() calls configfs_register_subsystem() at the end of its
> pin initializer. If registration returns an error, release the config
> item's initial reference and destroy the initialized mutex before
> returning. Otherwise, long subsystem names allocated by
> config_item_set_name() leak.
>
> The initial reference also remains after a successful subsystem is
> unregistered. Release it from PinnedDrop before the Rust container is
> destroyed.
>
> Initialize driver data before the C configfs object in Subsystem::new()
> and Group::new(). Then failure while initializing driver data cannot
> leave an initialized config group, and its allocated name, behind.
>
> Keeping registration inside try_pin_init! also means PinnedDrop is
> installed only after registration succeeds. A duplicate name therefore
> returns -EEXIST without attempting to unregister a subsystem whose
> ci_dentry was never set.
>
> Fixes: 446cafc295bf ("rust: configfs: introduce rust support for configfs")
> Signed-off-by: Younes Akhouayri <git@younes.io>
> ---
> Changes in v3:
> - Initialize driver data before configfs groups.
> - Release the initial group reference after registration failure and unregister.
> - Link to v2: https://patch.msgid.link/20260818-fix-rust-configfs-registration-state-v1-v2-1-9acedd3070f7@younes.io
>
> Changes in v2:
> - Register the subsystem at the end of try_pin_init!.
> - Destroy su_mutex when registration fails.
> - Remove the registered flag.
> - Link to v1: https://patch.msgid.link/20260818-fix-rust-configfs-registration-state-v1-v1-1-c929990bc8ef@younes.io
>
> To: Andreas Hindborg <a.hindborg@kernel.org>
> To: Breno Leitao <leitao@debian.org>
> To: Miguel Ojeda <ojeda@kernel.org>
> To: Boqun Feng <boqun@kernel.org>
> To: Gary Guo <gary@garyguo.net>
> To: Björn Roy Baron <bjorn3_gh@protonmail.com>
> To: Benno Lossin <lossin@kernel.org>
> To: Alice Ryhl <aliceryhl@google.com>
> To: Trevor Gross <tmgross@umich.edu>
> To: Danilo Krummrich <dakr@kernel.org>
> To: Daniel Almeida <daniel.almeida@collabora.com>
> To: Tamir Duberstein <tamird@kernel.org>
> To: Alexandre Courbot <acourbot@nvidia.com>
> To: Onur Özkan <work@onurozkan.dev>
> Cc: rust-for-linux@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
> rust/kernel/configfs.rs | 35 +++++++++++++++++++++++++----------
> 1 file changed, 25 insertions(+), 10 deletions(-)
>
> diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
> index cd082b83e9e7..d28ac9a648f1 100644
> --- a/rust/kernel/configfs.rs
> +++ b/rust/kernel/configfs.rs
> @@ -150,6 +150,7 @@ pub fn new(
> data: impl PinInit<Data, Error>,
> ) -> impl PinInit<Self, Error> {
> try_pin_init!(Self {
> + data <- data,
> subsystem <- pin_init::init_zeroed().chain(
> |place: &mut Opaque<bindings::configfs_subsystem>| {
> // SAFETY: We initialized the required fields of `place.group` above.
> @@ -172,13 +173,23 @@ pub fn new(
> Ok(())
> }
> ),
> - data <- data,
> - })
> - .pin_chain(|this| {
> - crate::error::to_result(
> - // SAFETY: We initialized `this.subsystem` according to C API contract above.
> - unsafe { bindings::configfs_register_subsystem(this.subsystem.get()) },
> - )
> + _: {
> + let result = crate::error::to_result(
> + // SAFETY: We initialized `subsystem` according to the C API contract above.
> + unsafe { bindings::configfs_register_subsystem(subsystem.get()) },
> + );
> + if result.is_err() {
> + // SAFETY: The group and mutex were initialized above, and registration
> + // failed, so configfs does not hold references to the group.
> + unsafe {
> + bindings::config_item_put(
I think this should be `config_group_put`, although it does make a
difference in practice right now.
> + &raw mut (*subsystem.get()).su_group.cg_item,
> + );
> + bindings::mutex_destroy(&raw mut (*subsystem.get()).su_mutex);
> + }
> + }
> + result?
> + }
> })
> }
> }
> @@ -188,8 +199,12 @@ impl<Data> PinnedDrop for Subsystem<Data> {
> fn drop(self: Pin<&mut Self>) {
> // SAFETY: We registered `self.subsystem` in the initializer returned by `Self::new`.
> unsafe { bindings::configfs_unregister_subsystem(self.subsystem.get()) };
> - // SAFETY: We initialized the mutex in `Subsystem::new`.
> - unsafe { bindings::mutex_destroy(&raw mut (*self.subsystem.get()).su_mutex) };
> + // SAFETY: Unregistering drops configfs's references to the group, so it is safe to drop
> + // the initial group reference and destroy the initialized mutex.
> + unsafe {
> + bindings::config_item_put(&raw mut (*self.subsystem.get()).su_group.cg_item);
Similar, should be `config_group_put`.
> + bindings::mutex_destroy(&raw mut (*self.subsystem.get()).su_mutex);
> + }
> }
> }
>
> @@ -260,6 +275,7 @@ pub fn new(
> data: impl PinInit<Data, Error>,
> ) -> impl PinInit<Self, Error> {
> try_pin_init!(Self {
> + data <- data,
> group <- pin_init::init_zeroed().chain(|v: &mut Opaque<bindings::config_group>| {
> let place = v.get();
> let name = name.to_bytes_with_nul().as_ptr();
> @@ -269,7 +285,6 @@ pub fn new(
> };
> Ok(())
> }),
> - data <- data,
Without adding a `PinnedDrop` implementation, this change has no effect.
We should add `PinnedDrop` that does `config_group_put` on `group`,
right?
We could also consider adding `SubsystemInner` and `GroupInner` and
implement `PinnedDrop` on those, to handle the C interface. We would
then have fields of type `SubsystemInner` in `Subsystem` instead of
`Opaque<_>` and similar for `Group<_>`. Then we would not have to
consider the initialization ordering with respect to the `data` field of
`Subsystem` and `Group`. What do you think?
Best regards,
Andreas Hindborg
prev parent reply other threads:[~2026-09-23 9:54 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 21:50 [PATCH v3] rust: configfs: fix object initialization cleanup Younes Akhouayri via B4 Relay
2026-09-23 9:54 ` Andreas Hindborg [this message]
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=87ld8s2sz0.fsf@t14s.mail-host-address-is-not-set \
--to=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=devnull+git.younes.io@kernel.org \
--cc=gary@garyguo.net \
--cc=git@younes.io \
--cc=leitao@debian.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tamird@kernel.org \
--cc=tmgross@umich.edu \
--cc=work@onurozkan.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