* Re: [PATCH] xfrm: kill xfrm_dev_{state,policy}_flush_secctx_check()
From: Tetsuo Handa @ 2026-02-04 13:57 UTC (permalink / raw)
To: Paul Moore, SELinux, linux-security-module
Cc: Steffen Klassert, Herbert Xu, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Network Development
In-Reply-To: <74a70504-8ff8-4d97-b35f-774364779889@I-love.SAKURA.ne.jp>
On 2026/02/04 19:15, Tetsuo Handa wrote:
> On 2026/02/04 7:40, Paul Moore wrote:
>> This is not an unusual request for such a proposed change, and
>> is something that I would expect a LSM maintainer to do without much
>> hesitation. If you are unwilling to investigate this, can you explain
>> why?
>
> Because I'm not familiar with how XFRM works; I'm not a user of LSM XFRM hooks.
>
> I can't judge whether the current code is COMPREHENSIVELY GATING;
> I can't imagine what the state you call COMPREHENSIVELY GATING is.
Steffen Klassert worried that killing xfrm_dev_state_flush_secctx_check() and
xfrm_dev_policy_flush_secctx_check() might violate a LSM policy and you agreed
( https://lkml.kernel.org/r/CAHC9VhQ54LRD7k_x6tUju2kPVBEHcdgBh46_hBN8btG0vhfy_w@mail.gmail.com ),
but the reality is that nobody in the world has enforced an LSM policy for almost 9 years
that makes xfrm_dev_{state,policy}_flush() no-op. That is, xfrm_dev_state_flush_secctx_check()
and xfrm_dev_policy_flush_secctx_check() had been effectively unused.
Killing xfrm_dev_state_flush_secctx_check() and xfrm_dev_policy_flush_secctx_check()
increases "system's stability" without sacrificing "authorization".
It is up to SELinux developers to discuss what actions to take as a compensation for
killing xfrm_dev_state_flush_secctx_check() and xfrm_dev_policy_flush_secctx_check().
The compensation might be to add LSM hooks to immediately before the point of no return.
But I wonder why you want to authorize deleting resources which are going to be "deleted by
cascade" due to deleting a dependent resource...
>
>
>
> P.S. For your investigation, I attach a new report that syzbot found today, and
> I'll drop "xfrm: always fail xfrm_dev_{state,policy}_flush_secctx_check()"
> because these three reports will be sufficient for people to understand that
> we need to kill xfrm_dev_{state,policy}_flush_secctx_check() calls.
^ permalink raw reply
* Re: [PATCH] evm: check return values of crypto_shash functions
From: Roberto Sassu @ 2026-02-04 12:50 UTC (permalink / raw)
To: Daniel Hodges, zohar, roberto.sassu
Cc: dmitry.kasatkin, eric.snowberg, paul, jmorris, serge,
linux-integrity, linux-security-module, linux-kernel
In-Reply-To: <20260131182233.2365157-1-hodgesd@meta.com>
On Sat, 2026-01-31 at 10:22 -0800, Daniel Hodges wrote:
> The crypto_shash_update() and crypto_shash_final() functions can fail
> and return error codes, but their return values were being ignored in
> several places in evm_crypto.c:
>
> - hmac_add_misc(): ignores returns from crypto_shash_update() and
> crypto_shash_final()
> - evm_calc_hmac_or_hash(): ignores returns from crypto_shash_update()
> - evm_init_hmac(): ignores returns from crypto_shash_update()
>
> If these hash operations fail silently, the resulting HMAC could be
> invalid or incomplete. This could potentially allow integrity
> verification to pass with incorrect HMACs, weakening EVM's security
> guarantees.
>
> Fix this by:
> - Changing hmac_add_misc() from void to int return type
> - Checking and propagating error codes from all crypto_shash calls
> - Updating all callers to check the return values
>
> Fixes: 66dbc325afce ("evm: re-release")
> Signed-off-by: Daniel Hodges <hodgesd@meta.com>
> ---
> security/integrity/evm/evm_crypto.c | 45 +++++++++++++++++++----------
> 1 file changed, 30 insertions(+), 15 deletions(-)
>
> diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
> index a5e730ffda57..286f23a1a26b 100644
> --- a/security/integrity/evm/evm_crypto.c
> +++ b/security/integrity/evm/evm_crypto.c
> @@ -132,58 +132,65 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo)
> }
> return desc;
> }
>
> /* Protect against 'cutting & pasting' security.evm xattr, include inode
> * specific info.
> *
> * (Additional directory/file metadata needs to be added for more complete
> * protection.)
> */
> -static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
> - char type, char *digest)
> +static int hmac_add_misc(struct shash_desc *desc, struct inode *inode,
> + char type, char *digest)
> {
> struct h_misc {
> unsigned long ino;
> __u32 generation;
> uid_t uid;
> gid_t gid;
> umode_t mode;
> } hmac_misc;
> + int ret;
>
> memset(&hmac_misc, 0, sizeof(hmac_misc));
> /* Don't include the inode or generation number in portable
> * signatures
> */
> if (type != EVM_XATTR_PORTABLE_DIGSIG) {
> hmac_misc.ino = inode->i_ino;
> hmac_misc.generation = inode->i_generation;
> }
> /* The hmac uid and gid must be encoded in the initial user
> * namespace (not the filesystems user namespace) as encoding
> * them in the filesystems user namespace allows an attack
> * where first they are written in an unprivileged fuse mount
> * of a filesystem and then the system is tricked to mount the
> * filesystem for real on next boot and trust it because
> * everything is signed.
> */
> hmac_misc.uid = from_kuid(&init_user_ns, inode->i_uid);
> hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
> hmac_misc.mode = inode->i_mode;
> - crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc));
> + ret = crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc));
> + if (ret)
> + return ret;
> if ((evm_hmac_attrs & EVM_ATTR_FSUUID) &&
> - type != EVM_XATTR_PORTABLE_DIGSIG)
> - crypto_shash_update(desc, (u8 *)&inode->i_sb->s_uuid, UUID_SIZE);
> - crypto_shash_final(desc, digest);
> + type != EVM_XATTR_PORTABLE_DIGSIG) {
> + ret = crypto_shash_update(desc, (u8 *)&inode->i_sb->s_uuid, UUID_SIZE);
> + if (ret)
> + return ret;
> + }
> + ret = crypto_shash_final(desc, digest);
Maybe we should also indicate if an error occurred, with a separate
error message, or adding the result in the message below.
Thanks
Roberto
> pr_debug("hmac_misc: (%zu) [%*phN]\n", sizeof(struct h_misc),
> (int)sizeof(struct h_misc), &hmac_misc);
> + return ret;
> }
>
> /*
> * Dump large security xattr values as a continuous ascii hexadecimal string.
> * (pr_debug is limited to 64 bytes.)
> */
> static void dump_security_xattr_l(const char *prefix, const void *src,
> size_t count)
> {
> #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> @@ -253,23 +260,24 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
>
> /*
> * Skip non-enabled xattrs for locally calculated
> * signatures/HMACs.
> */
> if (type != EVM_XATTR_PORTABLE_DIGSIG && !xattr->enabled)
> continue;
>
> if ((req_xattr_name && req_xattr_value)
> && !strcmp(xattr->name, req_xattr_name)) {
> - error = 0;
> - crypto_shash_update(desc, (const u8 *)req_xattr_value,
> - req_xattr_value_len);
> + error = crypto_shash_update(desc, (const u8 *)req_xattr_value,
> + req_xattr_value_len);
> + if (error)
> + goto out;
> if (is_ima)
> ima_present = true;
>
> dump_security_xattr(req_xattr_name,
> req_xattr_value,
> req_xattr_value_len);
> continue;
> }
> size = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, xattr->name,
> &xattr_value, xattr_size, GFP_NOFS);
> @@ -279,29 +287,32 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
> }
> if (size < 0)
> continue;
>
> user_space_size = vfs_getxattr(&nop_mnt_idmap, dentry,
> xattr->name, NULL, 0);
> if (user_space_size != size)
> pr_debug("file %s: xattr %s size mismatch (kernel: %d, user: %d)\n",
> dentry->d_name.name, xattr->name, size,
> user_space_size);
> - error = 0;
> xattr_size = size;
> - crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
> + error = crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
> + if (error)
> + goto out;
> if (is_ima)
> ima_present = true;
>
> dump_security_xattr(xattr->name, xattr_value, xattr_size);
> }
> - hmac_add_misc(desc, inode, type, data->digest);
> + error = hmac_add_misc(desc, inode, type, data->digest);
> + if (error)
> + goto out;
>
> if (inode != d_backing_inode(dentry) && iint) {
> if (IS_I_VERSION(inode))
> i_version = inode_query_iversion(inode);
> integrity_inode_attrs_store(&iint->metadata_inode, i_version,
> inode);
> }
>
> /* Portable EVM signatures must include an IMA hash */
> if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present)
> @@ -394,37 +405,41 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
> rc = __vfs_removexattr(&nop_mnt_idmap, dentry, XATTR_NAME_EVM);
> }
> return rc;
> }
>
> int evm_init_hmac(struct inode *inode, const struct xattr *xattrs,
> char *hmac_val)
> {
> struct shash_desc *desc;
> const struct xattr *xattr;
> + int ret;
>
> desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1);
> if (IS_ERR(desc)) {
> pr_info("init_desc failed\n");
> return PTR_ERR(desc);
> }
>
> for (xattr = xattrs; xattr->name; xattr++) {
> if (!evm_protected_xattr(xattr->name))
> continue;
>
> - crypto_shash_update(desc, xattr->value, xattr->value_len);
> + ret = crypto_shash_update(desc, xattr->value, xattr->value_len);
> + if (ret)
> + goto out;
> }
>
> - hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val);
> + ret = hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val);
> +out:
> kfree(desc);
> - return 0;
> + return ret;
> }
>
> /*
> * Get the key from the TPM for the SHA1-HMAC
> */
> int evm_init_key(void)
> {
> struct key *evm_key;
> struct encrypted_key_payload *ekp;
> int rc;
^ permalink raw reply
* Re: [PATCH v5 2/3] ima: Make integrity_inode_attrs_changed() call into vfs
From: Roberto Sassu @ 2026-02-04 12:34 UTC (permalink / raw)
To: Frederick Lawler, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Paul Moore, James Morris, Serge E. Hallyn,
Darrick J. Wong, Christian Brauner, Josef Bacik, Jeff Layton
Cc: linux-kernel, linux-integrity, linux-security-module, kernel-team
In-Reply-To: <20260130-xfs-ima-fixup-v5-2-57e84ea91712@cloudflare.com>
On Fri, 2026-01-30 at 16:39 -0600, Frederick Lawler wrote:
> Align integrity_inode_attrs_changed() to ima_check_last_writer()'s
> semantics when detecting changes.
>
> For IMA, stacked file systems that do not set kstat.change_cookie,
> integrity_inode_attrs_changed() will compare zero to zero, thus no
I setup overlay with two xfs filesystems, kept the file I want to be
audited in the lower filesystem.
Without this patch set, if I modify the lower file, changes are
detected, because actually the i_version is incremented.
In which situation there is a comparison zero to zero?
Thanks
Roberto
> change detected. This is not dissimilar to what
> ima_check_last_writer() does.
>
> No logical change intended for EVM.
>
> Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> ---
> include/linux/integrity.h | 28 ++++++++++++++++++++++++----
> security/integrity/evm/evm_main.c | 5 ++---
> security/integrity/ima/ima_main.c | 5 ++---
> 3 files changed, 28 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> index beb9ab19fa6257e79266b58bcb5f55b0c5445828..382c783f0fa3ae4a938cdf9559291ba1903a378e 100644
> --- a/include/linux/integrity.h
> +++ b/include/linux/integrity.h
> @@ -9,6 +9,7 @@
>
> #include <linux/fs.h>
> #include <linux/iversion.h>
> +#include <linux/kernel.h>
>
> enum integrity_status {
> INTEGRITY_PASS = 0,
> @@ -62,14 +63,33 @@ integrity_inode_attrs_stat_changed
>
> /*
> * On stacked filesystems detect whether the inode or its content has changed.
> + *
> + * Must be called in process context.
> */
> static inline bool
> integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
> - const struct inode *inode)
> + struct file *file, struct inode *inode)
> {
> - return (inode->i_sb->s_dev != attrs->dev ||
> - inode->i_ino != attrs->ino ||
> - !inode_eq_iversion(inode, attrs->version));
> + struct kstat stat;
> +
> + might_sleep();
> +
> + if (inode->i_sb->s_dev != attrs->dev || inode->i_ino != attrs->ino)
> + return true;
> +
> + /*
> + * EVM currently relies on backing inode i_version. While IS_I_VERSION
> + * is not a good indicator of i_version support, this still retains
> + * the logic such that a re-evaluation should still occur for EVM, and
> + * only for IMA if vfs_getattr_nosec() fails.
> + */
> + if (!file || vfs_getattr_nosec(&file->f_path, &stat,
> + STATX_CHANGE_COOKIE,
> + AT_STATX_SYNC_AS_STAT))
> + return !IS_I_VERSION(inode) ||
> + !inode_eq_iversion(inode, attrs->version);
> +
> + return integrity_inode_attrs_stat_changed(attrs, &stat);
> }
>
>
> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index 73d500a375cb37a54f295b0e1e93fd6e5d9ecddc..6a4e0e246005246d5700b1db590c1759242b9cb6 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -752,9 +752,8 @@ bool evm_metadata_changed(struct inode *inode, struct inode *metadata_inode)
> bool ret = false;
>
> if (iint) {
> - ret = (!IS_I_VERSION(metadata_inode) ||
> - integrity_inode_attrs_changed(&iint->metadata_inode,
> - metadata_inode));
> + ret = integrity_inode_attrs_changed(&iint->metadata_inode,
> + NULL, metadata_inode);
> if (ret)
> iint->evm_status = INTEGRITY_UNKNOWN;
> }
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 6570ad10887b9ea1172c78274cf62482350e87ff..8cb17c9d446caaa5a98f5ec8f027c17ba7babca8 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -328,9 +328,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
> real_inode = d_real_inode(file_dentry(file));
> if (real_inode != inode &&
> (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
> - if (!IS_I_VERSION(real_inode) ||
> - integrity_inode_attrs_changed(&iint->real_inode,
> - real_inode)) {
> + if (integrity_inode_attrs_changed(&iint->real_inode,
> + file, real_inode)) {
> iint->flags &= ~IMA_DONE_MASK;
> iint->measured_pcrs = 0;
> }
>
^ permalink raw reply
* Re: [PATCH v5 3/3] ima: Use kstat.ctime as a fallback change detection for stacked fs
From: Roberto Sassu @ 2026-02-04 12:36 UTC (permalink / raw)
To: Frederick Lawler, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Paul Moore, James Morris, Serge E. Hallyn,
Darrick J. Wong, Christian Brauner, Josef Bacik, Jeff Layton
Cc: linux-kernel, linux-integrity, linux-security-module, kernel-team
In-Reply-To: <20260130-xfs-ima-fixup-v5-3-57e84ea91712@cloudflare.com>
On Fri, 2026-01-30 at 16:39 -0600, Frederick Lawler wrote:
> IMA performs unnecessary measurements on files in stacked file systems
> that do not set kstat.change_cookie to an inode's i_version.
>
> For example: TMPFS (upper) is stacked onto XFS (lower).
> Actions files result in re-measurement because commit 1cf7e834a6fb
> ("xfs: switch to multigrain timestamps") introduced multigrain
> timestamps into XFS which changed the kstat.change_cookie semantics
> to no longer supply an i_version to compare against in
> integrity_inode_attributes_changed(). Once the inode is in TMPFS,
> the change detection behavior operates as normal because TMPFS updates
> kstat.change_cookie to the i_version.
>
> Instead, fall back onto a ctime comparison. This also gives file systems
> that do not support i_version an opportunity avoid the same behavior,
> as they're more likely to have ctime support.
>
> timespec64_to_ns() is chosen to avoid adding extra storage to
> integrity_inode_attributes by leveraging the existing version field.
Correct me if I'm wrong, but this issue seems to me xfs-specific. In
that case, maybe it is better to remove the stacked filesystem part,
which might be misleading.
Thanks
Roberto
> Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> Fixes: 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> Suggested-by: Jeff Layton <jlayton@kernel.org>
> Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> ---
> include/linux/integrity.h | 6 +++++-
> security/integrity/ima/ima_api.c | 11 ++++++++---
> security/integrity/ima/ima_main.c | 2 +-
> 3 files changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> index 382c783f0fa3ae4a938cdf9559291ba1903a378e..ec2c94907f417c4a71ecce29ac79edac9bc2c6f8 100644
> --- a/include/linux/integrity.h
> +++ b/include/linux/integrity.h
> @@ -10,6 +10,7 @@
> #include <linux/fs.h>
> #include <linux/iversion.h>
> #include <linux/kernel.h>
> +#include <linux/time64.h>
>
> enum integrity_status {
> INTEGRITY_PASS = 0,
> @@ -58,6 +59,9 @@ integrity_inode_attrs_stat_changed
> if (stat->result_mask & STATX_CHANGE_COOKIE)
> return stat->change_cookie != attrs->version;
>
> + if (stat->result_mask & STATX_CTIME)
> + return timespec64_to_ns(&stat->ctime) != (s64)attrs->version;
> +
> return true;
> }
>
> @@ -84,7 +88,7 @@ integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
> * only for IMA if vfs_getattr_nosec() fails.
> */
> if (!file || vfs_getattr_nosec(&file->f_path, &stat,
> - STATX_CHANGE_COOKIE,
> + STATX_CHANGE_COOKIE | STATX_CTIME,
> AT_STATX_SYNC_AS_STAT))
> return !IS_I_VERSION(inode) ||
> !inode_eq_iversion(inode, attrs->version);
> diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> index c35ea613c9f8d404ba4886e3b736c3bab29d1668..e47d6281febc15a0ac1bd2ea1d28fea4d0cd5c58 100644
> --- a/security/integrity/ima/ima_api.c
> +++ b/security/integrity/ima/ima_api.c
> @@ -272,10 +272,15 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> * to an initial measurement/appraisal/audit, but was modified to
> * assume the file changed.
> */
> - result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
> + result = vfs_getattr_nosec(&file->f_path, &stat,
> + STATX_CHANGE_COOKIE | STATX_CTIME,
> AT_STATX_SYNC_AS_STAT);
> - if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
> - i_version = stat.change_cookie;
> + if (!result) {
> + if (stat.result_mask & STATX_CHANGE_COOKIE)
> + i_version = stat.change_cookie;
> + else if (stat.result_mask & STATX_CTIME)
> + i_version = timespec64_to_ns(&stat.ctime);
> + }
> hash.hdr.algo = algo;
> hash.hdr.length = hash_digest_size[algo];
>
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 8cb17c9d446caaa5a98f5ec8f027c17ba7babca8..776db158b0bd8a0d053729ac0cc15af8b6020a98 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -199,7 +199,7 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
> &iint->atomic_flags);
> if ((iint->flags & IMA_NEW_FILE) ||
> vfs_getattr_nosec(&file->f_path, &stat,
> - STATX_CHANGE_COOKIE,
> + STATX_CHANGE_COOKIE | STATX_CTIME,
> AT_STATX_SYNC_AS_STAT) ||
> integrity_inode_attrs_stat_changed(&iint->real_inode,
> &stat)) {
>
^ permalink raw reply
* [PATCH v14 9/9] rust: page: add `from_raw()`
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg, Andreas Hindborg
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
Add a method to `Page` that allows construction of an instance from `struct
page` pointer.
Signed-off-by: Andreas Hindborg <a.hindborg@samsung.com>
---
rust/kernel/page.rs | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs
index 4591b7b01c3d2..803f3e3d76b22 100644
--- a/rust/kernel/page.rs
+++ b/rust/kernel/page.rs
@@ -191,6 +191,17 @@ pub fn nid(&self) -> i32 {
unsafe { bindings::page_to_nid(self.as_ptr()) }
}
+ /// Create a `&Page` from a raw `struct page` pointer
+ ///
+ /// # Safety
+ ///
+ /// `ptr` must be valid for use as a reference for the duration of `'a`.
+ pub unsafe fn from_raw<'a>(ptr: *const bindings::page) -> &'a Self {
+ // SAFETY: By function safety requirements, ptr is not null and is
+ // valid for use as a reference.
+ unsafe { &*Opaque::cast_from(ptr).cast::<Self>() }
+ }
+
/// Runs a piece of code with this page mapped to an address.
///
/// The page is unmapped when this call returns.
--
2.51.2
^ permalink raw reply related
* [PATCH v14 2/9] rust: rename `AlwaysRefCounted` to `RefCounted`.
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg, Oliver Mangold
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
From: Oliver Mangold <oliver.mangold@pm.me>
There are types where it may both be reference counted in some cases and
owned in others. In such cases, obtaining `ARef<T>` from `&T` would be
unsound as it allows creation of `ARef<T>` copy from `&Owned<T>`.
Therefore, we split `AlwaysRefCounted` into `RefCounted` (which `ARef<T>`
would require) and a marker trait to indicate that the type is always
reference counted (and not `Ownable`) so the `&T` -> `ARef<T>` conversion
is possible.
- Rename `AlwaysRefCounted` to `RefCounted`.
- Add a new unsafe trait `AlwaysRefCounted`.
- Implement the new trait `AlwaysRefCounted` for the newly renamed
`RefCounted` implementations. This leaves functionality of existing
implementers of `AlwaysRefCounted` intact.
Original patch by Oliver Mangold <oliver.mangold@pm.me> [1].
Link: https://lore.kernel.org/r/20251117-unique-ref-v13-2-b5b243df1250@pm.me [1]
Suggested-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/auxiliary.rs | 7 +++++-
rust/kernel/block/mq/request.rs | 15 +++++++------
rust/kernel/cred.rs | 13 ++++++++++--
rust/kernel/device.rs | 10 ++++++---
rust/kernel/device/property.rs | 7 +++++-
rust/kernel/drm/device.rs | 10 ++++++---
rust/kernel/drm/gem/mod.rs | 8 ++++---
rust/kernel/fs/file.rs | 16 ++++++++++----
rust/kernel/i2c.rs | 16 +++++++++-----
rust/kernel/mm.rs | 15 +++++++++----
rust/kernel/mm/mmput_async.rs | 9 ++++++--
rust/kernel/opp.rs | 10 ++++++---
rust/kernel/owned.rs | 2 +-
rust/kernel/pci.rs | 10 ++++++++-
rust/kernel/pid_namespace.rs | 12 +++++++++--
rust/kernel/platform.rs | 7 +++++-
rust/kernel/sync/aref.rs | 47 ++++++++++++++++++++++++++---------------
rust/kernel/task.rs | 10 ++++++---
rust/kernel/types.rs | 3 ++-
19 files changed, 164 insertions(+), 63 deletions(-)
diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index be76f11aecb7e..c410dcfc7b6f7 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -11,6 +11,7 @@
driver,
error::{from_result, to_result, Result},
prelude::*,
+ sync::aref::{AlwaysRefCounted, RefCounted},
types::Opaque,
ThisModule,
};
@@ -283,7 +284,7 @@ unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx>
kernel::impl_device_context_into_aref!(Device);
// SAFETY: Instances of `Device` are always reference-counted.
-unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
+unsafe impl RefCounted for Device {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
unsafe { bindings::get_device(self.as_ref().as_raw()) };
@@ -302,6 +303,10 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Device>` from a
+// `&Device`.
+unsafe impl AlwaysRefCounted for Device {}
+
impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
fn as_ref(&self) -> &device::Device<Ctx> {
// SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
index ce3e30c81cb5e..cf013b9e2cacf 100644
--- a/rust/kernel/block/mq/request.rs
+++ b/rust/kernel/block/mq/request.rs
@@ -9,7 +9,7 @@
block::mq::Operations,
error::Result,
sync::{
- aref::{ARef, AlwaysRefCounted},
+ aref::{ARef, AlwaysRefCounted, RefCounted},
atomic::Relaxed,
Refcount,
},
@@ -229,11 +229,10 @@ unsafe impl<T: Operations> Send for Request<T> {}
// mutate `self` are internally synchronized`
unsafe impl<T: Operations> Sync for Request<T> {}
-// SAFETY: All instances of `Request<T>` are reference counted. This
-// implementation of `AlwaysRefCounted` ensure that increments to the ref count
-// keeps the object alive in memory at least until a matching reference count
-// decrement is executed.
-unsafe impl<T: Operations> AlwaysRefCounted for Request<T> {
+// SAFETY: All instances of `Request<T>` are reference counted. This implementation of `RefCounted`
+// ensure that increments to the ref count keeps the object alive in memory at least until a
+// matching reference count decrement is executed.
+unsafe impl<T: Operations> RefCounted for Request<T> {
fn inc_ref(&self) {
self.wrapper_ref().refcount().inc();
}
@@ -255,3 +254,7 @@ unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
}
}
}
+
+// SAFETY: We currently do not implement `Ownable`, thus it is okay to obtain an `ARef<Request>`
+// from a `&Request` (but this will change in the future).
+unsafe impl<T: Operations> AlwaysRefCounted for Request<T> {}
diff --git a/rust/kernel/cred.rs b/rust/kernel/cred.rs
index ffa156b9df377..20ef0144094be 100644
--- a/rust/kernel/cred.rs
+++ b/rust/kernel/cred.rs
@@ -8,7 +8,12 @@
//!
//! Reference: <https://www.kernel.org/doc/html/latest/security/credentials.html>
-use crate::{bindings, sync::aref::AlwaysRefCounted, task::Kuid, types::Opaque};
+use crate::{
+ bindings,
+ sync::aref::RefCounted,
+ task::Kuid,
+ types::{AlwaysRefCounted, Opaque},
+};
/// Wraps the kernel's `struct cred`.
///
@@ -76,7 +81,7 @@ pub fn euid(&self) -> Kuid {
}
// SAFETY: The type invariants guarantee that `Credential` is always ref-counted.
-unsafe impl AlwaysRefCounted for Credential {
+unsafe impl RefCounted for Credential {
#[inline]
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
@@ -90,3 +95,7 @@ unsafe fn dec_ref(obj: core::ptr::NonNull<Credential>) {
unsafe { bindings::put_cred(obj.cast().as_ptr()) };
}
}
+
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Credential>` from a
+// `&Credential`.
+unsafe impl AlwaysRefCounted for Credential {}
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 031720bf5d8ca..e09dad5f9afea 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -7,8 +7,8 @@
use crate::{
bindings, fmt,
prelude::*,
- sync::aref::ARef,
- types::{ForeignOwnable, Opaque},
+ sync::aref::{ARef, RefCounted},
+ types::{AlwaysRefCounted, ForeignOwnable, Opaque},
};
use core::{any::TypeId, marker::PhantomData, ptr};
@@ -492,7 +492,7 @@ pub fn fwnode(&self) -> Option<&property::FwNode> {
kernel::impl_device_context_into_aref!(Device);
// SAFETY: Instances of `Device` are always reference-counted.
-unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
+unsafe impl RefCounted for Device {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
unsafe { bindings::get_device(self.as_raw()) };
@@ -504,6 +504,10 @@ unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Device>` from a
+// `&Device`.
+unsafe impl AlwaysRefCounted for Device {}
+
// SAFETY: As by the type invariant `Device` can be sent to any thread.
unsafe impl Send for Device {}
diff --git a/rust/kernel/device/property.rs b/rust/kernel/device/property.rs
index 3a332a8c53a9e..a8bb824ad0ec1 100644
--- a/rust/kernel/device/property.rs
+++ b/rust/kernel/device/property.rs
@@ -14,6 +14,7 @@
fmt,
prelude::*,
str::{CStr, CString},
+ sync::aref::{AlwaysRefCounted, RefCounted},
types::{ARef, Opaque},
};
@@ -359,7 +360,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
// SAFETY: Instances of `FwNode` are always reference-counted.
-unsafe impl crate::types::AlwaysRefCounted for FwNode {
+unsafe impl RefCounted for FwNode {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the
// refcount is non-zero.
@@ -373,6 +374,10 @@ unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<FwNode>` from a
+// `&FwNode`.
+unsafe impl AlwaysRefCounted for FwNode {}
+
enum Node<'a> {
Borrowed(&'a FwNode),
Owned(ARef<FwNode>),
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 3ce8f62a00569..38ce7f389ed00 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -11,8 +11,8 @@
error::from_err_ptr,
error::Result,
prelude::*,
- sync::aref::{ARef, AlwaysRefCounted},
- types::Opaque,
+ sync::aref::{AlwaysRefCounted, RefCounted},
+ types::{ARef, Opaque},
};
use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull};
@@ -198,7 +198,7 @@ fn deref(&self) -> &Self::Target {
// SAFETY: DRM device objects are always reference counted and the get/put functions
// satisfy the requirements.
-unsafe impl<T: drm::Driver> AlwaysRefCounted for Device<T> {
+unsafe impl<T: drm::Driver> RefCounted for Device<T> {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
unsafe { bindings::drm_dev_get(self.as_raw()) };
@@ -213,6 +213,10 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Device>` from a
+// `&Device`.
+unsafe impl<T: drm::Driver> AlwaysRefCounted for Device<T> {}
+
impl<T: drm::Driver> AsRef<device::Device> for Device<T> {
fn as_ref(&self) -> &device::Device {
// SAFETY: `bindings::drm_device::dev` is valid as long as the DRM device itself is valid,
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index a7f682e95c018..ad6840a440165 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -10,8 +10,7 @@
drm::driver::{AllocImpl, AllocOps},
error::{to_result, Result},
prelude::*,
- sync::aref::{ARef, AlwaysRefCounted},
- types::Opaque,
+ types::{ARef, AlwaysRefCounted, Opaque},
};
use core::{ops::Deref, ptr::NonNull};
@@ -253,7 +252,7 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
}
// SAFETY: Instances of `Object<T>` are always reference-counted.
-unsafe impl<T: DriverObject> crate::types::AlwaysRefCounted for Object<T> {
+unsafe impl<T: DriverObject> crate::types::RefCounted for Object<T> {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
unsafe { bindings::drm_gem_object_get(self.as_raw()) };
@@ -267,6 +266,9 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
unsafe { bindings::drm_gem_object_put(obj.as_raw()) }
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Device>` from a
+// `&Object`.
+unsafe impl<T: DriverObject> crate::types::AlwaysRefCounted for Object<T> {}
impl<T: DriverObject> super::private::Sealed for Object<T> {}
diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs
index 23ee689bd2400..06e457d62a939 100644
--- a/rust/kernel/fs/file.rs
+++ b/rust/kernel/fs/file.rs
@@ -12,8 +12,8 @@
cred::Credential,
error::{code::*, to_result, Error, Result},
fmt,
- sync::aref::{ARef, AlwaysRefCounted},
- types::{NotThreadSafe, Opaque},
+ sync::aref::RefCounted,
+ types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque},
};
use core::ptr;
@@ -197,7 +197,7 @@ unsafe impl Sync for File {}
// SAFETY: The type invariants guarantee that `File` is always ref-counted. This implementation
// makes `ARef<File>` own a normal refcount.
-unsafe impl AlwaysRefCounted for File {
+unsafe impl RefCounted for File {
#[inline]
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
@@ -212,6 +212,10 @@ unsafe fn dec_ref(obj: ptr::NonNull<File>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<File>` from a
+// `&File`.
+unsafe impl AlwaysRefCounted for File {}
+
/// Wraps the kernel's `struct file`. Not thread safe.
///
/// This type represents a file that is not known to be safe to transfer across thread boundaries.
@@ -233,7 +237,7 @@ pub struct LocalFile {
// SAFETY: The type invariants guarantee that `LocalFile` is always ref-counted. This implementation
// makes `ARef<LocalFile>` own a normal refcount.
-unsafe impl AlwaysRefCounted for LocalFile {
+unsafe impl RefCounted for LocalFile {
#[inline]
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
@@ -249,6 +253,10 @@ unsafe fn dec_ref(obj: ptr::NonNull<LocalFile>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<LocalFile>` from a
+// `&LocalFile`.
+unsafe impl AlwaysRefCounted for LocalFile {}
+
impl LocalFile {
/// Constructs a new `struct file` wrapper from a file descriptor.
///
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
index 39b0a9a207fda..b5e3c236a5c16 100644
--- a/rust/kernel/i2c.rs
+++ b/rust/kernel/i2c.rs
@@ -17,8 +17,10 @@
of,
prelude::*,
types::{
+ ARef,
AlwaysRefCounted,
- Opaque, //
+ Opaque,
+ RefCounted, //
}, //
};
@@ -31,8 +33,6 @@
}, //
};
-use kernel::types::ARef;
-
/// An I2C device id table.
#[repr(transparent)]
#[derive(Clone, Copy)]
@@ -416,7 +416,7 @@ pub fn get(index: i32) -> Result<ARef<Self>> {
kernel::impl_device_context_into_aref!(I2cAdapter);
// SAFETY: Instances of `I2cAdapter` are always reference-counted.
-unsafe impl crate::types::AlwaysRefCounted for I2cAdapter {
+unsafe impl crate::types::RefCounted for I2cAdapter {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
unsafe { bindings::i2c_get_adapter(self.index()) };
@@ -427,6 +427,9 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
unsafe { bindings::i2c_put_adapter(obj.as_ref().as_raw()) }
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Device>` from an
+// `&I2cAdapter`.
+unsafe impl AlwaysRefCounted for I2cAdapter {}
/// The i2c board info representation
///
@@ -492,7 +495,7 @@ unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for I2cClient<C
kernel::impl_device_context_into_aref!(I2cClient);
// SAFETY: Instances of `I2cClient` are always reference-counted.
-unsafe impl AlwaysRefCounted for I2cClient {
+unsafe impl RefCounted for I2cClient {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
unsafe { bindings::get_device(self.as_ref().as_raw()) };
@@ -503,6 +506,9 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
unsafe { bindings::put_device(&raw mut (*obj.as_ref().as_raw()).dev) }
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Device>` from an
+// `&I2cClient`.
+unsafe impl AlwaysRefCounted for I2cClient {}
impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for I2cClient<Ctx> {
fn as_ref(&self) -> &device::Device<Ctx> {
diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs
index 4764d7b68f2a7..dd9e3969e7206 100644
--- a/rust/kernel/mm.rs
+++ b/rust/kernel/mm.rs
@@ -13,8 +13,8 @@
use crate::{
bindings,
- sync::aref::{ARef, AlwaysRefCounted},
- types::{NotThreadSafe, Opaque},
+ sync::aref::RefCounted,
+ types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque},
};
use core::{ops::Deref, ptr::NonNull};
@@ -55,7 +55,7 @@ unsafe impl Send for Mm {}
unsafe impl Sync for Mm {}
// SAFETY: By the type invariants, this type is always refcounted.
-unsafe impl AlwaysRefCounted for Mm {
+unsafe impl RefCounted for Mm {
#[inline]
fn inc_ref(&self) {
// SAFETY: The pointer is valid since self is a reference.
@@ -69,6 +69,9 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Mm>` from a `&Mm`.
+unsafe impl AlwaysRefCounted for Mm {}
+
/// A wrapper for the kernel's `struct mm_struct`.
///
/// This type is like [`Mm`], but with non-zero `mm_users`. It can only be used when `mm_users` can
@@ -91,7 +94,7 @@ unsafe impl Send for MmWithUser {}
unsafe impl Sync for MmWithUser {}
// SAFETY: By the type invariants, this type is always refcounted.
-unsafe impl AlwaysRefCounted for MmWithUser {
+unsafe impl RefCounted for MmWithUser {
#[inline]
fn inc_ref(&self) {
// SAFETY: The pointer is valid since self is a reference.
@@ -105,6 +108,10 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<MmWithUser>` from a
+// `&MmWithUser`.
+unsafe impl AlwaysRefCounted for MmWithUser {}
+
// Make all `Mm` methods available on `MmWithUser`.
impl Deref for MmWithUser {
type Target = Mm;
diff --git a/rust/kernel/mm/mmput_async.rs b/rust/kernel/mm/mmput_async.rs
index b8d2f051225c7..aba4ce675c860 100644
--- a/rust/kernel/mm/mmput_async.rs
+++ b/rust/kernel/mm/mmput_async.rs
@@ -10,7 +10,8 @@
use crate::{
bindings,
mm::MmWithUser,
- sync::aref::{ARef, AlwaysRefCounted},
+ sync::aref::RefCounted,
+ types::{ARef, AlwaysRefCounted},
};
use core::{ops::Deref, ptr::NonNull};
@@ -34,7 +35,7 @@ unsafe impl Send for MmWithUserAsync {}
unsafe impl Sync for MmWithUserAsync {}
// SAFETY: By the type invariants, this type is always refcounted.
-unsafe impl AlwaysRefCounted for MmWithUserAsync {
+unsafe impl RefCounted for MmWithUserAsync {
#[inline]
fn inc_ref(&self) {
// SAFETY: The pointer is valid since self is a reference.
@@ -48,6 +49,10 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<MmWithUserAsync>`
+// from a `&MmWithUserAsync`.
+unsafe impl AlwaysRefCounted for MmWithUserAsync {}
+
// Make all `MmWithUser` methods available on `MmWithUserAsync`.
impl Deref for MmWithUserAsync {
type Target = MmWithUser;
diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
index a760fac287655..06fe2ca776a4f 100644
--- a/rust/kernel/opp.rs
+++ b/rust/kernel/opp.rs
@@ -16,8 +16,8 @@
ffi::{c_char, c_ulong},
prelude::*,
str::CString,
- sync::aref::{ARef, AlwaysRefCounted},
- types::Opaque,
+ sync::aref::RefCounted,
+ types::{ARef, AlwaysRefCounted, Opaque},
};
#[cfg(CONFIG_CPU_FREQ)]
@@ -1041,7 +1041,7 @@ unsafe impl Send for OPP {}
unsafe impl Sync for OPP {}
/// SAFETY: The type invariants guarantee that [`OPP`] is always refcounted.
-unsafe impl AlwaysRefCounted for OPP {
+unsafe impl RefCounted for OPP {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
unsafe { bindings::dev_pm_opp_get(self.0.get()) };
@@ -1053,6 +1053,10 @@ unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<OPP>` from an
+// `&OPP`.
+unsafe impl AlwaysRefCounted for OPP {}
+
impl OPP {
/// Creates an owned reference to a [`OPP`] from a valid pointer.
///
diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs
index fe30580331df9..b02edda11fcf6 100644
--- a/rust/kernel/owned.rs
+++ b/rust/kernel/owned.rs
@@ -25,7 +25,7 @@
///
/// Note: The underlying object is not required to provide internal reference counting, because it
/// represents a unique, owned reference. If reference counting (on the Rust side) is required,
-/// [`AlwaysRefCounted`](crate::types::AlwaysRefCounted) should be implemented.
+/// [`RefCounted`](crate::types::RefCounted) should be implemented.
///
/// # Safety
///
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index bea76ca9c3da5..9ee8f2bc6db9e 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -19,6 +19,10 @@
},
prelude::*,
str::CStr,
+ sync::aref::{
+ AlwaysRefCounted,
+ RefCounted, //
+ },
types::Opaque,
ThisModule, //
};
@@ -467,7 +471,7 @@ unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx>
impl crate::dma::Device for Device<device::Core> {}
// SAFETY: Instances of `Device` are always reference-counted.
-unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
+unsafe impl RefCounted for Device {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
unsafe { bindings::pci_dev_get(self.as_raw()) };
@@ -479,6 +483,10 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Device>` from a
+// `&Device`.
+unsafe impl AlwaysRefCounted for Device {}
+
impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
fn as_ref(&self) -> &device::Device<Ctx> {
// SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
diff --git a/rust/kernel/pid_namespace.rs b/rust/kernel/pid_namespace.rs
index 979a9718f153d..4f6a94540e33d 100644
--- a/rust/kernel/pid_namespace.rs
+++ b/rust/kernel/pid_namespace.rs
@@ -7,7 +7,11 @@
//! C header: [`include/linux/pid_namespace.h`](srctree/include/linux/pid_namespace.h) and
//! [`include/linux/pid.h`](srctree/include/linux/pid.h)
-use crate::{bindings, sync::aref::AlwaysRefCounted, types::Opaque};
+use crate::{
+ bindings,
+ sync::aref::RefCounted,
+ types::{AlwaysRefCounted, Opaque},
+};
use core::ptr;
/// Wraps the kernel's `struct pid_namespace`. Thread safe.
@@ -41,7 +45,7 @@ pub unsafe fn from_ptr<'a>(ptr: *const bindings::pid_namespace) -> &'a Self {
}
// SAFETY: Instances of `PidNamespace` are always reference-counted.
-unsafe impl AlwaysRefCounted for PidNamespace {
+unsafe impl RefCounted for PidNamespace {
#[inline]
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
@@ -55,6 +59,10 @@ unsafe fn dec_ref(obj: ptr::NonNull<PidNamespace>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<PidNamespace>` from
+// a `&PidNamespace`.
+unsafe impl AlwaysRefCounted for PidNamespace {}
+
// SAFETY:
// - `PidNamespace::dec_ref` can be called from any thread.
// - It is okay to send ownership of `PidNamespace` across thread boundaries.
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 35a5813ffb33f..139517c21961e 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -13,6 +13,7 @@
irq::{self, IrqRequest},
of,
prelude::*,
+ sync::aref::{AlwaysRefCounted, RefCounted},
types::Opaque,
ThisModule,
};
@@ -490,7 +491,7 @@ pub fn optional_irq_by_name(&self, name: &CStr) -> Result<IrqRequest<'_>> {
impl crate::dma::Device for Device<device::Core> {}
// SAFETY: Instances of `Device` are always reference-counted.
-unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
+unsafe impl RefCounted for Device {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
unsafe { bindings::get_device(self.as_ref().as_raw()) };
@@ -502,6 +503,10 @@ unsafe fn dec_ref(obj: NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Device>` from a
+// `&Device`.
+unsafe impl AlwaysRefCounted for Device {}
+
impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
fn as_ref(&self) -> &device::Device<Ctx> {
// SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
index e175aefe86151..61caddfd89619 100644
--- a/rust/kernel/sync/aref.rs
+++ b/rust/kernel/sync/aref.rs
@@ -19,11 +19,9 @@
use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};
-/// Types that are _always_ reference counted.
+/// Types that are internally reference counted.
///
/// It allows such types to define their own custom ref increment and decrement functions.
-/// Additionally, it allows users to convert from a shared reference `&T` to an owned reference
-/// [`ARef<T>`].
///
/// This is usually implemented by wrappers to existing structures on the C side of the code. For
/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted
@@ -40,9 +38,8 @@
/// at least until matching decrements are performed.
///
/// Implementers must also ensure that all instances are reference-counted. (Otherwise they
-/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object
-/// alive.)
-pub unsafe trait AlwaysRefCounted {
+/// won't be able to honour the requirement that [`RefCounted::inc_ref`] keep the object alive.)
+pub unsafe trait RefCounted {
/// Increments the reference count on the object.
fn inc_ref(&self);
@@ -55,11 +52,27 @@ pub unsafe trait AlwaysRefCounted {
/// Callers must ensure that there was a previous matching increment to the reference count,
/// and that the object is no longer used after its reference count is decremented (as it may
/// result in the object being freed), unless the caller owns another increment on the refcount
- /// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls
- /// [`AlwaysRefCounted::dec_ref`] once).
+ /// (e.g., it calls [`RefCounted::inc_ref`] twice, then calls [`RefCounted::dec_ref`] once).
unsafe fn dec_ref(obj: NonNull<Self>);
}
+/// Always reference-counted type.
+///
+/// It allows deriving a counted reference [`ARef<T>`] from a `&T`.
+///
+/// This provides some convenience, but it allows "escaping" borrow checks on `&T`. As it
+/// complicates attempts to ensure that a reference to T is unique, it is optional to provide for
+/// [`RefCounted`] types. See *Safety* below.
+///
+/// # Safety
+///
+/// Implementers must ensure that no safety invariants are violated by upgrading an `&T` to an
+/// [`ARef<T>`]. In particular that implies [`AlwaysRefCounted`] and [`crate::types::Ownable`]
+/// cannot be implemented for the same type, as this would allow violating the uniqueness guarantee
+/// of [`crate::types::Owned<T>`] by dereferencing it into an `&T` and obtaining an [`ARef`] from
+/// that.
+pub unsafe trait AlwaysRefCounted: RefCounted {}
+
/// An owned reference to an always-reference-counted object.
///
/// The object's reference count is automatically decremented when an instance of [`ARef`] is
@@ -70,7 +83,7 @@ pub unsafe trait AlwaysRefCounted {
///
/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In
/// particular, the [`ARef`] instance owns an increment on the underlying object's reference count.
-pub struct ARef<T: AlwaysRefCounted> {
+pub struct ARef<T: RefCounted> {
ptr: NonNull<T>,
_p: PhantomData<T>,
}
@@ -79,16 +92,16 @@ pub struct ARef<T: AlwaysRefCounted> {
// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
// `T` to be `Send` because any thread that has an `ARef<T>` may ultimately access `T` using a
// mutable reference, for example, when the reference count reaches zero and `T` is dropped.
-unsafe impl<T: AlwaysRefCounted + Sync + Send> Send for ARef<T> {}
+unsafe impl<T: RefCounted + Sync + Send> Send for ARef<T> {}
// SAFETY: It is safe to send `&ARef<T>` to another thread when the underlying `T` is `Sync`
// because it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally,
// it needs `T` to be `Send` because any thread that has a `&ARef<T>` may clone it and get an
// `ARef<T>` on that thread, so the thread may ultimately access `T` using a mutable reference, for
// example, when the reference count reaches zero and `T` is dropped.
-unsafe impl<T: AlwaysRefCounted + Sync + Send> Sync for ARef<T> {}
+unsafe impl<T: RefCounted + Sync + Send> Sync for ARef<T> {}
-impl<T: AlwaysRefCounted> ARef<T> {
+impl<T: RefCounted> ARef<T> {
/// Creates a new instance of [`ARef`].
///
/// It takes over an increment of the reference count on the underlying object.
@@ -117,12 +130,12 @@ pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
///
/// ```
/// use core::ptr::NonNull;
- /// use kernel::sync::aref::{ARef, AlwaysRefCounted};
+ /// use kernel::sync::aref::{ARef, RefCounted};
///
/// struct Empty {}
///
/// # // SAFETY: TODO.
- /// unsafe impl AlwaysRefCounted for Empty {
+ /// unsafe impl RefCounted for Empty {
/// fn inc_ref(&self) {}
/// unsafe fn dec_ref(_obj: NonNull<Self>) {}
/// }
@@ -140,7 +153,7 @@ pub fn into_raw(me: Self) -> NonNull<T> {
}
}
-impl<T: AlwaysRefCounted> Clone for ARef<T> {
+impl<T: RefCounted> Clone for ARef<T> {
fn clone(&self) -> Self {
self.inc_ref();
// SAFETY: We just incremented the refcount above.
@@ -148,7 +161,7 @@ fn clone(&self) -> Self {
}
}
-impl<T: AlwaysRefCounted> Deref for ARef<T> {
+impl<T: RefCounted> Deref for ARef<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
@@ -165,7 +178,7 @@ fn from(b: &T) -> Self {
}
}
-impl<T: AlwaysRefCounted> Drop for ARef<T> {
+impl<T: RefCounted> Drop for ARef<T> {
fn drop(&mut self) {
// SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to
// decrement.
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 49fad6de06740..0a6e38d984560 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -9,8 +9,8 @@
ffi::{c_int, c_long, c_uint},
mm::MmWithUser,
pid_namespace::PidNamespace,
- sync::aref::ARef,
- types::{NotThreadSafe, Opaque},
+ sync::aref::{AlwaysRefCounted, RefCounted},
+ types::{ARef, NotThreadSafe, Opaque},
};
use core::{
cmp::{Eq, PartialEq},
@@ -348,7 +348,7 @@ pub fn active_pid_ns(&self) -> Option<&PidNamespace> {
}
// SAFETY: The type invariants guarantee that `Task` is always refcounted.
-unsafe impl crate::sync::aref::AlwaysRefCounted for Task {
+unsafe impl RefCounted for Task {
#[inline]
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
@@ -362,6 +362,10 @@ unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
}
}
+// SAFETY: We do not implement `Ownable`, thus it is okay to obtain an `ARef<Task>` from a
+// `&Task`.
+unsafe impl AlwaysRefCounted for Task {}
+
impl Kuid {
/// Get the current euid.
#[inline]
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 4aec7b699269a..9b96aa2ebdb7e 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -18,7 +18,8 @@
},
sync::aref::{
ARef,
- AlwaysRefCounted, //
+ AlwaysRefCounted,
+ RefCounted, //
}, //
};
--
2.51.2
^ permalink raw reply related
* [PATCH v14 5/9] rust: Add `OwnableRefCounted`
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg, Oliver Mangold
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
From: Oliver Mangold <oliver.mangold@pm.me>
Types implementing one of these traits can safely convert between an
`ARef<T>` and an `Owned<T>`.
This is useful for types which generally are accessed through an `ARef`
but have methods which can only safely be called when the reference is
unique, like e.g. `block::mq::Request::end_ok()`.
Original patch by Oliver Mangold <oliver.mangold@pm.me> [1].
Link: https://lore.kernel.org/r/20251117-unique-ref-v13-4-b5b243df1250@pm.me [1]
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/owned.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++---
rust/kernel/sync/aref.rs | 15 ++++-
rust/kernel/types.rs | 1 +
3 files changed, 150 insertions(+), 9 deletions(-)
diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs
index b02edda11fcf6..85251c57f86c6 100644
--- a/rust/kernel/owned.rs
+++ b/rust/kernel/owned.rs
@@ -14,18 +14,24 @@
pin::Pin,
ptr::NonNull, //
};
+use kernel::{
+ sync::aref::ARef,
+ types::RefCounted, //
+};
/// Types that specify their own way of performing allocation and destruction. Typically, this trait
/// is implemented on types from the C side.
///
-/// Implementing this trait allows types to be referenced via the [`Owned<Self>`] pointer type. This
-/// is useful when it is desirable to tie the lifetime of the reference to an owned object, rather
-/// than pass around a bare reference. [`Ownable`] types can define custom drop logic that is
-/// executed when the owned reference [`Owned<Self>`] pointing to the object is dropped.
+/// Implementing this trait allows types to be referenced via the [`Owned<Self>`] pointer type.
+/// - This is useful when it is desirable to tie the lifetime of an object reference to an owned
+/// object, rather than pass around a bare reference.
+/// - [`Ownable`] types can define custom drop logic that is executed when the owned reference
+/// of type [`Owned<_>`] pointing to the object is dropped.
///
/// Note: The underlying object is not required to provide internal reference counting, because it
/// represents a unique, owned reference. If reference counting (on the Rust side) is required,
-/// [`RefCounted`](crate::types::RefCounted) should be implemented.
+/// [`RefCounted`] should be implemented. [`OwnableRefCounted`] should be implemented if conversion
+/// between unique and shared (reference counted) ownership is needed.
///
/// # Safety
///
@@ -63,8 +69,7 @@
/// Foo {},
/// flags::GFP_KERNEL,
/// )?;
-/// let result = NonNull::new(KBox::into_raw(result))
-/// .expect("Raw pointer to newly allocation KBox is null, this should never happen.");
+/// let result = NonNull::new(KBox::into_raw(result)).ok_or(ENOMEM)?;
/// // Count new allocation
/// *FOO_ALLOC_COUNT.lock() += 1;
/// // SAFETY: We just allocated the `Self`, thus it is valid and there cannot be any other
@@ -88,11 +93,12 @@
/// }
///
/// {
-/// let foo = Foo::new().expect("Failed to allocate a Foo. This shouldn't happen");
+/// let foo = Foo::new()?;
/// assert!(*FOO_ALLOC_COUNT.lock() == 1);
/// }
/// // `foo` is out of scope now, so we expect no live allocations.
/// assert!(*FOO_ALLOC_COUNT.lock() == 0);
+/// # Ok::<(), Error>(())
/// ```
pub unsafe trait Ownable {
/// Releases the object.
@@ -194,3 +200,124 @@ fn drop(&mut self) {
unsafe { T::release(self.ptr) };
}
}
+
+/// A trait for objects that can be wrapped in either one of the reference types [`Owned`] and
+/// [`ARef`].
+///
+/// # Examples
+///
+/// A minimal example implementation of [`OwnableRefCounted`], [`Ownable`] and its usage with
+/// [`ARef`] and [`Owned`] looks like this:
+///
+/// ```
+/// # #![expect(clippy::disallowed_names)]
+/// # use core::cell::Cell;
+/// # use core::ptr::NonNull;
+/// # use kernel::alloc::{flags, kbox::KBox, AllocError};
+/// # use kernel::sync::aref::{ARef, RefCounted};
+/// # use kernel::types::{Owned, Ownable, OwnableRefCounted};
+///
+/// // An internally refcounted struct for demonstration purposes.
+/// //
+/// // # Invariants
+/// //
+/// // - `refcount` is always non-zero for a valid object.
+/// // - `refcount` is >1 if there is more than one Rust reference to it.
+/// //
+/// struct Foo {
+/// refcount: Cell<usize>,
+/// }
+///
+/// impl Foo {
+/// fn new() -> Result<Owned<Self>> {
+/// // We are just using a `KBox` here to handle the actual allocation, as our `Foo` is
+/// // not actually a C-allocated object.
+/// let result = KBox::new(
+/// Foo {
+/// refcount: Cell::new(1),
+/// },
+/// flags::GFP_KERNEL,
+/// )?;
+/// let result = NonNull::new(KBox::into_raw(result)).ok_or(ENOMEM)?;
+/// // SAFETY: We just allocated the `Self`, thus it is valid and there cannot be any other
+/// // Rust references. Calling `into_raw()` makes us responsible for ownership and
+/// // we won't use the raw pointer anymore, thus we can transfer ownership to the `Owned`.
+/// Ok(unsafe { Owned::from_raw(result) })
+/// }
+/// }
+///
+/// // SAFETY: We increment and decrement each time the respective function is called and only free
+/// // the `Foo` when the refcount reaches zero.
+/// unsafe impl RefCounted for Foo {
+/// fn inc_ref(&self) {
+/// self.refcount.replace(self.refcount.get() + 1);
+/// }
+///
+/// unsafe fn dec_ref(this: NonNull<Self>) {
+/// // SAFETY: By requirement on calling this function, the refcount is non-zero,
+/// // implying the underlying object is valid.
+/// let refcount = unsafe { &this.as_ref().refcount };
+/// let new_refcount = refcount.get() - 1;
+/// if new_refcount == 0 {
+/// // The `Foo` will be dropped when `KBox` goes out of scope.
+/// // SAFETY: The [`KBox<Foo>`] is still alive as the old refcount is 1. We can pass
+/// // ownership to the [`KBox`] as by requirement on calling this function,
+/// // the `Self` will no longer be used by the caller.
+/// unsafe { KBox::from_raw(this.as_ptr()) };
+/// } else {
+/// refcount.replace(new_refcount);
+/// }
+/// }
+/// }
+///
+/// impl OwnableRefCounted for Foo {
+/// fn try_from_shared(this: ARef<Self>) -> Result<Owned<Self>, ARef<Self>> {
+/// if this.refcount.get() == 1 {
+/// // SAFETY: The `Foo` is still alive and has no other Rust references as the refcount
+/// // is 1.
+/// Ok(unsafe { Owned::from_raw(ARef::into_raw(this)) })
+/// } else {
+/// Err(this)
+/// }
+/// }
+/// }
+///
+/// // SAFETY: This implementation of `release()` is safe for any valid `Self`.
+/// unsafe impl Ownable for Foo {
+/// unsafe fn release(this: NonNull<Self>) {
+/// // SAFETY: Using `dec_ref()` from [`RefCounted`] to release is okay, as the refcount is
+/// // always 1 for an [`Owned<Foo>`].
+/// unsafe{ Foo::dec_ref(this) };
+/// }
+/// }
+///
+/// let foo = Foo::new()?;
+/// let mut foo = ARef::from(foo);
+/// {
+/// let bar = foo.clone();
+/// assert!(Owned::try_from(bar).is_err());
+/// }
+/// assert!(Owned::try_from(foo).is_ok());
+/// # Ok::<(), Error>(())
+/// ```
+pub trait OwnableRefCounted: RefCounted + Ownable + Sized {
+ /// Checks if the [`ARef`] is unique and converts it to an [`Owned`] if that is the case.
+ /// Otherwise it returns again an [`ARef`] to the same underlying object.
+ fn try_from_shared(this: ARef<Self>) -> Result<Owned<Self>, ARef<Self>>;
+
+ /// Converts the [`Owned`] into an [`ARef`].
+ fn into_shared(this: Owned<Self>) -> ARef<Self> {
+ // SAFETY: Safe by the requirements on implementing the trait.
+ unsafe { ARef::from_raw(Owned::into_raw(this)) }
+ }
+}
+
+impl<T: OwnableRefCounted> TryFrom<ARef<T>> for Owned<T> {
+ type Error = ARef<T>;
+ /// Tries to convert the [`ARef`] to an [`Owned`] by calling
+ /// [`try_from_shared()`](OwnableRefCounted::try_from_shared). In case the [`ARef`] is not
+ /// unique, it returns again an [`ARef`] to the same underlying object.
+ fn try_from(b: ARef<T>) -> Result<Owned<T>, Self::Error> {
+ T::try_from_shared(b)
+ }
+}
diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
index 3c63c9a5fb9be..77f6c8dc411eb 100644
--- a/rust/kernel/sync/aref.rs
+++ b/rust/kernel/sync/aref.rs
@@ -23,6 +23,10 @@
ops::Deref,
ptr::NonNull, //
};
+use kernel::types::{
+ OwnableRefCounted,
+ Owned, //
+};
/// Types that are internally reference counted.
///
@@ -35,7 +39,10 @@
/// Note: Implementing this trait allows types to be wrapped in an [`ARef<Self>`]. It requires an
/// internal reference count and provides only shared references. If unique references are required
/// [`Ownable`](crate::types::Ownable) should be implemented which allows types to be wrapped in an
-/// [`Owned<Self>`](crate::types::Owned).
+/// [`Owned<Self>`](crate::types::Owned). Implementing the trait
+/// [`OwnableRefCounted`] allows to convert between unique and
+/// shared references (i.e. [`Owned<Self>`](crate::types::Owned) and
+/// [`ARef<Self>`](crate::types::Owned)).
///
/// # Safety
///
@@ -185,6 +192,12 @@ fn from(b: &T) -> Self {
}
}
+impl<T: OwnableRefCounted> From<Owned<T>> for ARef<T> {
+ fn from(b: Owned<T>) -> Self {
+ T::into_shared(b)
+ }
+}
+
impl<T: RefCounted> Drop for ARef<T> {
fn drop(&mut self) {
// SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 9b96aa2ebdb7e..f43c091eeb8b7 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -14,6 +14,7 @@
pub use crate::{
owned::{
Ownable,
+ OwnableRefCounted,
Owned, //
},
sync::aref::{
--
2.51.2
^ permalink raw reply related
* [PATCH v14 4/9] rust: aref: update formatting of use statements
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
Update formatting if use statements in preparation for next commit.
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/sync/aref.rs | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
index efe16a7fdfa5d..3c63c9a5fb9be 100644
--- a/rust/kernel/sync/aref.rs
+++ b/rust/kernel/sync/aref.rs
@@ -17,7 +17,12 @@
//! [`Arc`]: crate::sync::Arc
//! [`Arc<T>`]: crate::sync::Arc
-use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};
+use core::{
+ marker::PhantomData,
+ mem::ManuallyDrop,
+ ops::Deref,
+ ptr::NonNull, //
+};
/// Types that are internally reference counted.
///
--
2.51.2
^ permalink raw reply related
* [PATCH v14 7/9] rust: page: convert to `Ownable`
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg, Asahi Lina
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
From: Asahi Lina <lina+kernel@asahilina.net>
This allows Page references to be returned as borrowed references,
without necessarily owning the struct page.
Original patch by Asahi Lina <lina@asahilina.net> [1].
Link: https://lore.kernel.org/rust-for-linux/20250202-rust-page-v1-2-e3170d7fe55e@asahilina.net/ [1]
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/page.rs | 34 +++++++++++++++++++++++-----------
1 file changed, 23 insertions(+), 11 deletions(-)
diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs
index bf3bed7e2d3fe..4591b7b01c3d2 100644
--- a/rust/kernel/page.rs
+++ b/rust/kernel/page.rs
@@ -10,6 +10,11 @@
bindings,
error::code::*,
error::Result,
+ types::{
+ Opaque,
+ Ownable,
+ Owned, //
+ },
uaccess::UserSliceReader, //
};
use core::{
@@ -83,7 +88,7 @@ pub const fn page_align(addr: usize) -> usize {
///
/// [`VBox`]: kernel::alloc::VBox
/// [`Vmalloc`]: kernel::alloc::allocator::Vmalloc
-pub struct BorrowedPage<'a>(ManuallyDrop<Page>, PhantomData<&'a Page>);
+pub struct BorrowedPage<'a>(ManuallyDrop<Owned<Page>>, PhantomData<&'a Owned<Page>>);
impl<'a> BorrowedPage<'a> {
/// Constructs a [`BorrowedPage`] from a raw pointer to a `struct page`.
@@ -93,7 +98,9 @@ impl<'a> BorrowedPage<'a> {
/// - `ptr` must point to a valid `bindings::page`.
/// - `ptr` must remain valid for the entire lifetime `'a`.
pub unsafe fn from_raw(ptr: NonNull<bindings::page>) -> Self {
- let page = Page { page: ptr };
+ let page: Owned<Page> =
+ // SAFETY: By function safety requirements `ptr` is non null and valid for 'a.
+ unsafe { Owned::from_raw(NonNull::new_unchecked(ptr.as_ptr().cast())) };
// INVARIANT: The safety requirements guarantee that `ptr` is valid for the entire lifetime
// `'a`.
@@ -126,8 +133,9 @@ pub trait AsPageIter {
/// # Invariants
///
/// The pointer is valid, and has ownership over the page.
+#[repr(transparent)]
pub struct Page {
- page: NonNull<bindings::page>,
+ page: Opaque<bindings::page>,
}
// SAFETY: Pages have no logic that relies on them staying on a given thread, so moving them across
@@ -161,19 +169,20 @@ impl Page {
/// # Ok::<(), kernel::alloc::AllocError>(())
/// ```
#[inline]
- pub fn alloc_page(flags: Flags) -> Result<Self, AllocError> {
+ pub fn alloc_page(flags: Flags) -> Result<Owned<Self>, AllocError> {
// SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it
// is always safe to call this method.
let page = unsafe { bindings::alloc_pages(flags.as_raw(), 0) };
let page = NonNull::new(page).ok_or(AllocError)?;
- // INVARIANT: We just successfully allocated a page, so we now have ownership of the newly
- // allocated page. We transfer that ownership to the new `Page` object.
- Ok(Self { page })
+ // SAFETY: We just successfully allocated a page, so we now have ownership of the newly
+ // allocated page. We transfer that ownership to the new `Owned<Page>` object.
+ // Since `Page` is transparent, we can cast the pointer directly.
+ Ok(unsafe { Owned::from_raw(page.cast()) })
}
/// Returns a raw pointer to the page.
pub fn as_ptr(&self) -> *mut bindings::page {
- self.page.as_ptr()
+ Opaque::cast_into(&self.page)
}
/// Get the node id containing this page.
@@ -348,10 +357,13 @@ pub unsafe fn copy_from_user_slice_raw(
}
}
-impl Drop for Page {
+// SAFETY: `Owned<Page>` objects returned by Page::alloc_page() follow the requirements of
+// the Ownable abstraction.
+unsafe impl Ownable for Page {
#[inline]
- fn drop(&mut self) {
+ unsafe fn release(this: NonNull<Self>) {
// SAFETY: By the type invariants, we have ownership of the page and can free it.
- unsafe { bindings::__free_pages(self.page.as_ptr(), 0) };
+ // Since Page is transparent, we can cast the raw pointer directly.
+ unsafe { bindings::__free_pages(this.cast().as_ptr(), 0) };
}
}
--
2.51.2
^ permalink raw reply related
* [PATCH v14 1/9] rust: types: Add Ownable/Owned types
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg, Asahi Lina
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
From: Asahi Lina <lina+kernel@asahilina.net>
By analogy to `AlwaysRefCounted` and `ARef`, an `Ownable` type is a
(typically C FFI) type that *may* be owned by Rust, but need not be. Unlike
`AlwaysRefCounted`, this mechanism expects the reference to be unique
within Rust, and does not allow cloning.
Conceptually, this is similar to a `KBox<T>`, except that it delegates
resource management to the `T` instead of using a generic allocator.
This change is a derived work based on work by Asahi Lina
<lina+kernel@asahilina.net> [1] and Oliver Mangold <oliver.mangold@pm.me>.
Link: https://lore.kernel.org/rust-for-linux/20250202-rust-page-v1-1-e3170d7fe55e@asahilina.net/ [1]
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/lib.rs | 1 +
rust/kernel/owned.rs | 196 +++++++++++++++++++++++++++++++++++++++++++++++
rust/kernel/sync/aref.rs | 5 ++
rust/kernel/types.rs | 11 ++-
4 files changed, 212 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index f812cf1200428..96a3fadc3377a 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -119,6 +119,7 @@
pub mod of;
#[cfg(CONFIG_PM_OPP)]
pub mod opp;
+pub mod owned;
pub mod page;
#[cfg(CONFIG_PCI)]
pub mod pci;
diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs
new file mode 100644
index 0000000000000..fe30580331df9
--- /dev/null
+++ b/rust/kernel/owned.rs
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Unique owned pointer types for objects with custom drop logic.
+//!
+//! These pointer types are useful for C-allocated objects which by API-contract
+//! are owned by Rust, but need to be freed through the C API.
+
+use core::{
+ mem::ManuallyDrop,
+ ops::{
+ Deref,
+ DerefMut, //
+ },
+ pin::Pin,
+ ptr::NonNull, //
+};
+
+/// Types that specify their own way of performing allocation and destruction. Typically, this trait
+/// is implemented on types from the C side.
+///
+/// Implementing this trait allows types to be referenced via the [`Owned<Self>`] pointer type. This
+/// is useful when it is desirable to tie the lifetime of the reference to an owned object, rather
+/// than pass around a bare reference. [`Ownable`] types can define custom drop logic that is
+/// executed when the owned reference [`Owned<Self>`] pointing to the object is dropped.
+///
+/// Note: The underlying object is not required to provide internal reference counting, because it
+/// represents a unique, owned reference. If reference counting (on the Rust side) is required,
+/// [`AlwaysRefCounted`](crate::types::AlwaysRefCounted) should be implemented.
+///
+/// # Safety
+///
+/// Implementers must ensure that the [`release()`](Self::release) function frees the underlying
+/// object in the correct way for a valid, owned object of this type.
+///
+/// # Examples
+///
+/// A minimal example implementation of [`Ownable`] and its usage with [`Owned`] looks like
+/// this:
+///
+/// ```
+/// # #![expect(clippy::disallowed_names)]
+/// # use core::cell::Cell;
+/// # use core::ptr::NonNull;
+/// # use kernel::sync::global_lock;
+/// # use kernel::alloc::{flags, kbox::KBox, AllocError};
+/// # use kernel::types::{Owned, Ownable};
+///
+/// // Let's count the allocations to see if freeing works.
+/// kernel::sync::global_lock! {
+/// // SAFETY: we call `init()` right below, before doing anything else.
+/// unsafe(uninit) static FOO_ALLOC_COUNT: Mutex<usize> = 0;
+/// }
+/// // SAFETY: We call `init()` only once, here.
+/// unsafe { FOO_ALLOC_COUNT.init() };
+///
+/// struct Foo;
+///
+/// impl Foo {
+/// fn new() -> Result<Owned<Self>> {
+/// // We are just using a `KBox` here to handle the actual allocation, as our `Foo` is
+/// // not actually a C-allocated object.
+/// let result = KBox::new(
+/// Foo {},
+/// flags::GFP_KERNEL,
+/// )?;
+/// let result = NonNull::new(KBox::into_raw(result))
+/// .expect("Raw pointer to newly allocation KBox is null, this should never happen.");
+/// // Count new allocation
+/// *FOO_ALLOC_COUNT.lock() += 1;
+/// // SAFETY: We just allocated the `Self`, thus it is valid and there cannot be any other
+/// // Rust references. Calling `into_raw()` makes us responsible for ownership and we won't
+/// // use the raw pointer anymore. Thus we can transfer ownership to the `Owned`.
+/// Ok(unsafe { Owned::from_raw(result) })
+/// }
+/// }
+///
+/// // SAFETY: The implementation of `release` in this trait implementation correctly frees the
+/// // owned `Foo`.
+/// unsafe impl Ownable for Foo {
+/// unsafe fn release(this: NonNull<Self>) {
+/// // SAFETY: The [`KBox<Self>`] is still alive. We can pass ownership to the [`KBox`], as
+/// // by requirement on calling this function, the `Self` will no longer be used by the
+/// // caller.
+/// drop(unsafe { KBox::from_raw(this.as_ptr()) });
+/// // Count released allocation
+/// *FOO_ALLOC_COUNT.lock() -= 1;
+/// }
+/// }
+///
+/// {
+/// let foo = Foo::new().expect("Failed to allocate a Foo. This shouldn't happen");
+/// assert!(*FOO_ALLOC_COUNT.lock() == 1);
+/// }
+/// // `foo` is out of scope now, so we expect no live allocations.
+/// assert!(*FOO_ALLOC_COUNT.lock() == 0);
+/// ```
+pub unsafe trait Ownable {
+ /// Releases the object.
+ ///
+ /// # Safety
+ ///
+ /// Callers must ensure that:
+ /// - `this` points to a valid `Self`.
+ /// - `*this` is no longer used after this call.
+ unsafe fn release(this: NonNull<Self>);
+}
+
+/// A mutable reference to an owned `T`.
+///
+/// The [`Ownable`] is automatically freed or released when an instance of [`Owned`] is
+/// dropped.
+///
+/// # Invariants
+///
+/// - The [`Owned<T>`] has exclusive access to the instance of `T`.
+/// - The instance of `T` will stay alive at least as long as the [`Owned<T>`] is alive.
+pub struct Owned<T: Ownable> {
+ ptr: NonNull<T>,
+}
+
+impl<T: Ownable> Owned<T> {
+ /// Creates a new instance of [`Owned`].
+ ///
+ /// This function takes over ownership of the underlying object.
+ ///
+ /// # Safety
+ ///
+ /// Callers must ensure that:
+ /// - `ptr` points to a valid instance of `T`.
+ /// - Ownership of the underlying `T` can be transferred to the `Self<T>` (i.e. operations
+ /// which require ownership will be safe).
+ /// - An `Owned<T>` is a mutable reference to the underlying object. As such,
+ /// the object must not be accessed (read or mutated) through any pointer
+ /// other than the created `Owned<T>`. Opt-out is still possible similar to
+ /// a mutable reference (e.g. by using [`Opaque`]).
+ ///
+ /// [`Opaque`]: kernel::types::Opaque
+ pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
+ // INVARIANT: By function safety requirement:
+ // - The resulting object has exclusive access to the `T` pointed to by `ptr`.
+ // - The `T` object pointed to by `ptr` is alive at least as long as the returned `Self`.
+ Self { ptr }
+ }
+
+ /// Consumes the [`Owned`], returning a raw pointer.
+ ///
+ /// This function does not drop the underlying `T`. When this function returns, ownership of the
+ /// underlying `T` is with the caller.
+ pub fn into_raw(me: Self) -> NonNull<T> {
+ ManuallyDrop::new(me).ptr
+ }
+
+ /// Get a pinned mutable reference to the data owned by this `Owned<T>`.
+ pub fn get_pin_mut(&mut self) -> Pin<&mut T> {
+ // SAFETY: The type invariants guarantee that the object is valid, and that we can safely
+ // return a mutable reference to it.
+ let unpinned = unsafe { self.ptr.as_mut() };
+
+ // SAFETY: We never hand out unpinned mutable references to the data in
+ // `Self`, unless the contained type is `Unpin`.
+ unsafe { Pin::new_unchecked(unpinned) }
+ }
+}
+
+// SAFETY: It is safe to send an [`Owned<T>`] to another thread when the underlying `T` is [`Send`],
+// because of the ownership invariant. Sending an [`Owned<T>`] is equivalent to sending the `T`.
+unsafe impl<T: Ownable + Send> Send for Owned<T> {}
+
+// SAFETY: It is safe to send [`&Owned<T>`] to another thread when the underlying `T` is [`Sync`],
+// because of the ownership invariant. Sending an [`&Owned<T>`] is equivalent to sending the `&T`.
+unsafe impl<T: Ownable + Sync> Sync for Owned<T> {}
+
+impl<T: Ownable> Deref for Owned<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ // SAFETY: The type invariants guarantee that the object is valid.
+ unsafe { self.ptr.as_ref() }
+ }
+}
+
+impl<T: Ownable + Unpin> DerefMut for Owned<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ // SAFETY: The type invariants guarantee that the object is valid, and that we can safely
+ // return a mutable reference to it.
+ unsafe { self.ptr.as_mut() }
+ }
+}
+
+impl<T: Ownable> Drop for Owned<T> {
+ fn drop(&mut self) {
+ // SAFETY: The type invariants guarantee that the `Owned` owns the object we're about to
+ // release.
+ unsafe { T::release(self.ptr) };
+ }
+}
diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
index 0d24a0432015d..e175aefe86151 100644
--- a/rust/kernel/sync/aref.rs
+++ b/rust/kernel/sync/aref.rs
@@ -29,6 +29,11 @@
/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted
/// instances of a type.
///
+/// Note: Implementing this trait allows types to be wrapped in an [`ARef<Self>`]. It requires an
+/// internal reference count and provides only shared references. If unique references are required
+/// [`Ownable`](crate::types::Ownable) should be implemented which allows types to be wrapped in an
+/// [`Owned<Self>`](crate::types::Owned).
+///
/// # Safety
///
/// Implementers must ensure that increments to the reference count keep the object alive in memory
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 9c5e7dbf16323..4aec7b699269a 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -11,7 +11,16 @@
};
use pin_init::{PinInit, Wrapper, Zeroable};
-pub use crate::sync::aref::{ARef, AlwaysRefCounted};
+pub use crate::{
+ owned::{
+ Ownable,
+ Owned, //
+ },
+ sync::aref::{
+ ARef,
+ AlwaysRefCounted, //
+ }, //
+};
/// Used to transfer ownership to and from foreign (non-Rust) languages.
///
--
2.51.2
^ permalink raw reply related
* [PATCH v14 8/9] rust: implement `ForeignOwnable` for `Owned`
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
Implement `ForeignOwnable` for `Owned<T>`. This allows use of `Owned<T>` in
places such as the `XArray`.
Note that `T` does not need to implement `ForeignOwnable` for `Owned<T>` to
implement `ForeignOwnable`.
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/owned.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 44 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/owned.rs b/rust/kernel/owned.rs
index 85251c57f86c6..0b22de4aaf584 100644
--- a/rust/kernel/owned.rs
+++ b/rust/kernel/owned.rs
@@ -16,7 +16,10 @@
};
use kernel::{
sync::aref::ARef,
- types::RefCounted, //
+ types::{
+ ForeignOwnable, //
+ RefCounted,
+ }, //
};
/// Types that specify their own way of performing allocation and destruction. Typically, this trait
@@ -120,6 +123,7 @@ pub unsafe trait Ownable {
///
/// - The [`Owned<T>`] has exclusive access to the instance of `T`.
/// - The instance of `T` will stay alive at least as long as the [`Owned<T>`] is alive.
+#[repr(transparent)]
pub struct Owned<T: Ownable> {
ptr: NonNull<T>,
}
@@ -201,6 +205,45 @@ fn drop(&mut self) {
}
}
+// SAFETY: We derive the pointer to `T` from a valid `T`, so the returned
+// pointer satisfy alignment requirements of `T`.
+unsafe impl<T: Ownable + 'static> ForeignOwnable for Owned<T> {
+ const FOREIGN_ALIGN: usize = core::mem::align_of::<Owned<T>>();
+
+ type Borrowed<'a> = &'a T;
+ type BorrowedMut<'a> = Pin<&'a mut T>;
+
+ fn into_foreign(self) -> *mut kernel::ffi::c_void {
+ let ptr = self.ptr.as_ptr().cast();
+ core::mem::forget(self);
+ ptr
+ }
+
+ unsafe fn from_foreign(ptr: *mut kernel::ffi::c_void) -> Self {
+ Self {
+ // SAFETY: By function safety contract, `ptr` came from
+ // `into_foreign` and cannot be null.
+ ptr: unsafe { NonNull::new_unchecked(ptr.cast()) },
+ }
+ }
+
+ unsafe fn borrow<'a>(ptr: *mut kernel::ffi::c_void) -> Self::Borrowed<'a> {
+ // SAFETY: By function safety requirements, `ptr` is valid for use as a
+ // reference for `'a`.
+ unsafe { &*ptr.cast() }
+ }
+
+ unsafe fn borrow_mut<'a>(ptr: *mut kernel::ffi::c_void) -> Self::BorrowedMut<'a> {
+ // SAFETY: By function safety requirements, `ptr` is valid for use as a
+ // unique reference for `'a`.
+ let inner = unsafe { &mut *ptr.cast() };
+
+ // SAFETY: We never move out of inner, and we do not hand out mutable
+ // references when `T: !Unpin`.
+ unsafe { Pin::new_unchecked(inner) }
+ }
+}
+
/// A trait for objects that can be wrapped in either one of the reference types [`Owned`] and
/// [`ARef`].
///
--
2.51.2
^ permalink raw reply related
* [PATCH v14 0/9] rust: add `Ownable` trait and `Owned` type
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg, Asahi Lina, Oliver Mangold, Andreas Hindborg
Add a new trait `Ownable` and type `Owned` for types that specify their
own way of performing allocation and destruction. This is useful for
types from the C side.
Add the trait `OwnableRefCounted` that allows conversion between
`ARef` and `Owned`. This is analogous to conversion between `Arc` and
`UniqueArc`.
Patch 2 is difficult to merge since it requires a change everywhere
`AlwaysRefCounted` is implemented prior to application. We had new
implementations of this trait for the last few releases, so we are
probably going to have some when these patches are applied. Sorry for
that. I would ask maintainers of all affected areas to ACK these patches
as soon as possible.
This series has been underway a very long time. The work was started
off by Asahi Lina, then picked up by Oliver Mangold and is now being
finalized by Andreas Hindborg. For series like this, it is difficult to
track what contributions came from what authors at what time. I'm going
to leave authorship of the patches with the person originally submitting
the patch. I will not track changes by each individual on each patch.
Instead, I will leave a link to the original patch in the commit message
of these multi-contributor patches.
As I cannot reach out to everyone to ask if they will sign off on
the changes I have made, I will remove their tags, as these require
approval.
With this approach, checkpatch.pl is complaining about missing
Signed-off-by from patch author. I am not sure if we can keep it like
this, if I need to change the author, or if I need to hunt down the
original author to get an ACK for keeping the Signed-off-by tag?
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
Changes in v14:
- Rebase on v6.19-rc7.
- Rewrite cover letter.
- Update documentation and safety comments based on v13 feedback.
- Update commit messages.
- Reorder implementation blocks in owned.rs.
- Update example in owned.rs to use try operator rather than `expect`.
- Reformat use statements.
- Add patch: rust: page: convert to `Ownable`.
- Add patch: rust: implement `ForeignOwnable` for `Owned`.
- Add patch: rust: page: add `from_raw()`.
- Link to v13: https://lore.kernel.org/r/20251117-unique-ref-v13-0-b5b243df1250@pm.me
Changes in v13:
- Rebase onto v6.18-rc1 (Andreas's work).
- Documentation and style fixes contributed by Andreas
- Link to v12: https://lore.kernel.org/r/20251001-unique-ref-v12-0-fa5c31f0c0c4@pm.me
Changes in v12:
-
- Rebase onto v6.17-rc1 (Andreas's work).
- moved kernel/types/ownable.rs to kernel/owned.rs
- Drop OwnableMut, make DerefMut depend on Unpin instead. I understood
ML discussion as that being okay, but probably needs further scrunity.
- Lots of more documentation changes suggested by reviewers.
- Usage example for Ownable/Owned.
- Link to v11: https://lore.kernel.org/r/20250618-unique-ref-v11-0-49eadcdc0aa6@pm.me
Changes in v11:
- Rework of documentation. I tried to honor all requests for changes "in
spirit" plus some clearifications and corrections of my own.
- Dropping `SimpleOwnedRefCounted` by request from Alice, as it creates a
potentially problematic blanket implementation (which a derive macro that
could be created later would not have).
- Dropping Miguel's "kbuild: provide `RUSTC_HAS_DO_NOT_RECOMMEND` symbol"
patch, as it is not needed anymore after dropping `SimpleOwnedRefCounted`.
(I can add it again, if it is considered useful anyway).
- Link to v10: https://lore.kernel.org/r/20250502-unique-ref-v10-0-25de64c0307f@pm.me
Changes in v10:
- Moved kernel/ownable.rs to kernel/types/ownable.rs
- Fixes in documentation / comments as suggested by Andreas Hindborg
- Added Reviewed-by comment for Andreas Hindborg
- Fix rustfmt of pid_namespace.rs
- Link to v9: https://lore.kernel.org/r/20250325-unique-ref-v9-0-e91618c1de26@pm.me
Changes in v9:
- Rebase onto v6.14-rc7
- Move Ownable/OwnedRefCounted/Ownable, etc., into separate module
- Documentation fixes to Ownable/OwnableMut/OwnableRefCounted
- Add missing SAFETY documentation to ARef example
- Link to v8: https://lore.kernel.org/r/20250313-unique-ref-v8-0-3082ffc67a31@pm.me
Changes in v8:
- Fix Co-developed-by and Suggested-by tags as suggested by Miguel and Boqun
- Some small documentation fixes in Owned/Ownable patch
- removing redundant trait constraint on DerefMut for Owned as suggested by Boqun Feng
- make SimpleOwnedRefCounted no longer implement RefCounted as suggested by Boqun Feng
- documentation for RefCounted as suggested by Boqun Feng
- Link to v7: https://lore.kernel.org/r/20250310-unique-ref-v7-0-4caddb78aa05@pm.me
Changes in v7:
- Squash patch to make Owned::from_raw/into_raw public into parent
- Added Signed-off-by to other people's commits
- Link to v6: https://lore.kernel.org/r/20250310-unique-ref-v6-0-1ff53558617e@pm.me
Changes in v6:
- Changed comments/formatting as suggested by Miguel Ojeda
- Included and used new config flag RUSTC_HAS_DO_NOT_RECOMMEND,
thus no changes to types.rs will be needed when the attribute
becomes available.
- Fixed commit message for Owned patch.
- Link to v5: https://lore.kernel.org/r/20250307-unique-ref-v5-0-bffeb633277e@pm.me
Changes in v5:
- Rebase the whole thing on top of the Ownable/Owned traits by Asahi Lina.
- Rename AlwaysRefCounted to RefCounted and make AlwaysRefCounted a
marker trait instead to allow to obtain an ARef<T> from an &T,
which (as Alice pointed out) is unsound when combined with UniqueRef/Owned.
- Change the Trait design and naming to implement this feature,
UniqueRef/UniqueRefCounted is dropped in favor of Ownable/Owned and
OwnableRefCounted is used to provide the functions to convert
between Owned and ARef.
- Link to v4: https://lore.kernel.org/r/20250305-unique-ref-v4-1-a8fdef7b1c2c@pm.me
Changes in v4:
- Just a minor change in naming by request from Andreas Hindborg,
try_shared_to_unique() -> try_from_shared(),
unique_to_shared() -> into_shared(),
which is more in line with standard Rust naming conventions.
- Link to v3: https://lore.kernel.org/r/Z8Wuud2UQX6Yukyr@mango
---
Andreas Hindborg (4):
rust: aref: update formatting of use statements
rust: page: update formatting of `use` statements
rust: implement `ForeignOwnable` for `Owned`
rust: page: add `from_raw()`
Asahi Lina (2):
rust: types: Add Ownable/Owned types
rust: page: convert to `Ownable`
Oliver Mangold (3):
rust: rename `AlwaysRefCounted` to `RefCounted`.
rust: Add missing SAFETY documentation for `ARef` example
rust: Add `OwnableRefCounted`
rust/kernel/auxiliary.rs | 7 +-
rust/kernel/block/mq/request.rs | 15 +-
rust/kernel/cred.rs | 13 +-
rust/kernel/device.rs | 10 +-
rust/kernel/device/property.rs | 7 +-
rust/kernel/drm/device.rs | 10 +-
rust/kernel/drm/gem/mod.rs | 8 +-
rust/kernel/fs/file.rs | 16 +-
rust/kernel/i2c.rs | 16 +-
rust/kernel/lib.rs | 1 +
rust/kernel/mm.rs | 15 +-
rust/kernel/mm/mmput_async.rs | 9 +-
rust/kernel/opp.rs | 10 +-
rust/kernel/owned.rs | 366 ++++++++++++++++++++++++++++++++++++++++
rust/kernel/page.rs | 57 +++++--
rust/kernel/pci.rs | 10 +-
rust/kernel/pid_namespace.rs | 12 +-
rust/kernel/platform.rs | 7 +-
rust/kernel/sync/aref.rs | 80 ++++++---
rust/kernel/task.rs | 10 +-
rust/kernel/types.rs | 13 +-
21 files changed, 612 insertions(+), 80 deletions(-)
---
base-commit: 63804fed149a6750ffd28610c5c1c98cce6bd377
change-id: 20250305-unique-ref-29fcd675f9e9
Best regards,
--
Andreas Hindborg <a.hindborg@kernel.org>
^ permalink raw reply
* [PATCH v14 6/9] rust: page: update formatting of `use` statements
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
Update formatting in preparation for next patch
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/page.rs | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs
index 432fc0297d4a8..bf3bed7e2d3fe 100644
--- a/rust/kernel/page.rs
+++ b/rust/kernel/page.rs
@@ -3,17 +3,23 @@
//! Kernel page allocation and management.
use crate::{
- alloc::{AllocError, Flags},
+ alloc::{
+ AllocError,
+ Flags, //
+ },
bindings,
error::code::*,
error::Result,
- uaccess::UserSliceReader,
+ uaccess::UserSliceReader, //
};
use core::{
marker::PhantomData,
mem::ManuallyDrop,
ops::Deref,
- ptr::{self, NonNull},
+ ptr::{
+ self,
+ NonNull, //
+ }, //
};
/// A bitwise shift for the page size.
--
2.51.2
^ permalink raw reply related
* [PATCH v14 3/9] rust: Add missing SAFETY documentation for `ARef` example
From: Andreas Hindborg @ 2026-02-04 11:56 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Greg Kroah-Hartman, Dave Ertman, Ira Weiny, Leon Romanovsky,
Paul Moore, Serge Hallyn, Rafael J. Wysocki, David Airlie,
Simona Vetter, Alexander Viro, Christian Brauner, Jan Kara,
Igor Korotin, Daniel Almeida, Lorenzo Stoakes, Liam R. Howlett,
Viresh Kumar, Nishanth Menon, Stephen Boyd, Bjorn Helgaas,
Krzysztof Wilczyński
Cc: linux-kernel, rust-for-linux, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
Andreas Hindborg, Oliver Mangold
In-Reply-To: <20260204-unique-ref-v14-0-17cb29ebacbb@kernel.org>
From: Oliver Mangold <oliver.mangold@pm.me>
SAFETY comment in rustdoc example was just 'TODO'. Fixed.
Original patch by Oliver Mangold <oliver.mangold@pm.me> [1].
Link: https://lore.kernel.org/r/20251117-unique-ref-v13-3-b5b243df1250@pm.me [1]
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
rust/kernel/sync/aref.rs | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
index 61caddfd89619..efe16a7fdfa5d 100644
--- a/rust/kernel/sync/aref.rs
+++ b/rust/kernel/sync/aref.rs
@@ -129,12 +129,14 @@ pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
/// # Examples
///
/// ```
- /// use core::ptr::NonNull;
- /// use kernel::sync::aref::{ARef, RefCounted};
+ /// # use core::ptr::NonNull;
+ /// # use kernel::sync::aref::{ARef, RefCounted};
///
/// struct Empty {}
///
- /// # // SAFETY: TODO.
+ /// // SAFETY: The `RefCounted` implementation for `Empty` does not count references and never
+ /// // frees the underlying object. Thus we can act as owning an increment on the refcount for
+ /// // the object that we pass to the newly created `ARef`.
/// unsafe impl RefCounted for Empty {
/// fn inc_ref(&self) {}
/// unsafe fn dec_ref(_obj: NonNull<Self>) {}
@@ -142,7 +144,7 @@ pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
///
/// let mut data = Empty {};
/// let ptr = NonNull::<Empty>::new(&mut data).unwrap();
- /// # // SAFETY: TODO.
+ /// // SAFETY: We keep `data` around longer than the `ARef`.
/// let data_ref: ARef<Empty> = unsafe { ARef::from_raw(ptr) };
/// let raw_ptr: NonNull<Empty> = ARef::into_raw(data_ref);
///
--
2.51.2
^ permalink raw reply related
* Re: [PATCH v2 0/6] Landlock: Implement scope control for pathname Unix sockets
From: Günther Noack @ 2026-02-04 11:44 UTC (permalink / raw)
To: Tingmao Wang, Mickaël Salaün, Justin Suess
Cc: Günther Noack, Demi Marie Obenour, Alyssa Ross, Jann Horn,
Tahera Fahimi, linux-security-module
In-Reply-To: <e6b6b069-384c-4c45-a56b-fa54b26bc72a@maowtm.org>
On Tue, Feb 03, 2026 at 09:53:11PM +0000, Tingmao Wang wrote:
> On 2/3/26 17:54, Günther Noack wrote:
> > BTW, regarding the implementation: To have *OR* semantics for "within
> > scope" and "allow-listed path", the implementation will be
> > non-trivial, and I suspect we won't hit the merge window if we try to
> > get them both in for 7.0. But in my mind, a simple UAPI is more
> > important than trying to make it in time for the next merge window.
> >
> > (The implementation is difficult because the path-based and
> > scope-based check currently happen in different LSM hooks, and none of
> > the two hooks has enough information to make the decision alone. The
> > second hook only gets called if the first returns 0. It'll require
> > some further discussion to make it work together.)
>
> Right. In that case, would it make sense to pass sk into the new
> security_unix_find() hook, perhaps with the new argument named `struct
> sock *other`? Then we can use this hook for the scope check as well by
> using landlock_cred(other->sk_socket->file->f_cred)->domain etc.
>
> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index 227467236930..db9d279b3883 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -1223,24 +1223,24 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
>
> err = -ECONNREFUSED;
> inode = d_backing_inode(path.dentry);
> if (!S_ISSOCK(inode->i_mode))
> goto path_put;
>
> + err = -ECONNREFUSED;
> + sk = unix_find_socket_byinode(inode);
> + if (!sk)
> + goto path_put;
> +
> /*
> * We call the hook because we know that the inode is a socket
> * and we hold a valid reference to it via the path.
> */
> - err = security_unix_find(&path, type, flags);
> + err = security_unix_find(&path, sk, flags);
> if (err)
> - goto path_put;
> -
> - err = -ECONNREFUSED;
> - sk = unix_find_socket_byinode(inode);
> - if (!sk)
> - goto path_put;
> + goto sock_put;
>
> err = -EPROTOTYPE;
> if (sk->sk_type == type)
> touch_atime(&path);
> else
> goto sock_put;
>
> By doing this we won't even need to pass `type` separately anymore. The
> only change would be that now one can determine if a socket is bound or
> not even without being allowed RESOLVE_UNIX access. I'm not sure how much
> of an issue this is, but we could also call the hook anyway with a NULL in
> place of the new argument, if unix_find_socket_byinode() fails. Other
> LSMs can then decide what to do in that case (either return -ECONNREFUSED
> or -EPERM).
Thank you for the suggestion.
Small caveat is that the LSM interface is very central and we should
be careful. We have previously gotten the advice from Paul to design
the hooks in an LSM-independent way that ideally reflects the
arguments to the unix_find_bsd() function, and this would now deviate
(slightly) from that, but simplifying the implementation for us. In
my personal opinion, this might be worth doing the trade-off, if
AppArmor people also agree, but we should double check.
To keep the discussion of implementation and interface separate, I
have raised this question in the pathname-restricted-UNIX patch set
thread in [1].
[1] https://lore.kernel.org/all/aYMenaSmBkAsFowd@google.com/
> >> Furthermore, an application / Landlock config etc can always opt to not
> >> use the scope bit at all, if it "knows" all the locations where the
> >> application's sockets would be placed, and just use RESOLVE_UNIX access
> >> right (or nothing if it is not supported).
> >>
> >> (The following is a bit of a side note, not terribly relevant if we're
> >> deciding to go with the patch as is.)
> >>
> >>>> [...]
> >>>> Another way to put it is that, if FS-based and scope-based controls
> >>>> interacts in the above proposed way, both mechanisms feel like "poking
> >>>> holes" in the other. But as Mickaël said, one can think of the two
> >>>> mechanisms not as independent controls, but rather as two interfaces for
> >>>> the same control. The socket access control is "enabled" if either the
> >>>> LANDLOCK_ACCESS_FS_RESOLVE_UNIX access is handled, or the scope bit
> >>>> proposed in this patch is enabled.
> >>>>
> >>>> With that said, I can think of some alternative ways that might make this
> >>>> API look "better" (from a subjective point of view, feedback welcome),
> >>>> however it does mean more delays, and specifically, these will depend on
> >>>> LANDLOCK_ACCESS_FS_RESOLVE_UNIX:
> >>>>
> >>>> One possibility is to simply always allow a Landlock domain to connect to
> >>>> its own sockets (in the case where LANDLOCK_ACCESS_FS_RESOLVE_UNIX is
> >>>> handled, otherwise all sockets are allowed). This might be reasonable, as
> >>>> one can only connect to a socket it creates if it has the permission to
> >>>> create it in the first place, which is already controlled by
> >>>> LANDLOCK_ACCESS_FS_MAKE_SOCK, so we don't really lose any policy
> >>>> flexibility here - if for some reason the sandboxer don't want to allow
> >>>> access to any (pathname) sockets, even the sandboxed app's own ones, it
> >>>> can just not allow LANDLOCK_ACCESS_FS_MAKE_SOCK anywhere.
> >>>
> >>> LANDLOCK_ACCESS_FS_MAKE_SOCK is only required to bind/listen to a
> >>> socket, not to connect. I guess you was thinking about
> >>> LANDLOCK_ACCESS_FS_RESOLVE_UNIX in this case?
> >>
> >> In this "allow same-scope connect unconditionally" proposal, the
> >> application would still be able to (bind to and) connect to its own
> >> sockets, even if LANDLOCK_ACCESS_FS_RESOLVE_UNIX is handled and nothing is
> >> allowed to have LANDLOCK_ACCESS_FS_RESOLVE_UNIX access. But a sandboxer
> >> which for whatever reason doesn't want this "allow same scope" default can
> >> still prevent the use of (pathname) sockets by restricting
> >> LANDLOCK_ACCESS_FS_MAKE_SOCK, because if an app can't connect to any
> >> sockets it doesn't own, and can't create any sockets itself either, then
> >> it effectively can't connect to any sockets at all.
> >>
> >> (Although on second thought, I guess there could be a case where an app
> >> first creates some socket files before doing landlock_restrict_self(),
> >> then it might still be able to bind to these even without
> >> LANDLOCK_ACCESS_FS_MAKE_SOCK?)
> >
> > FWIW, I also really liked Tingmao's first of the two listed
> > possibilities in [1], where she proposed to introduce both rights
> > together. In my understanding, the arguments we have discussed so far
> > for that are:
> >
> > IN FAVOR:
> >
> > (pro1) Connecting to a UNIX socket in the same scope is always safe,
> > and it makes it possible to use named UNIX sockets between the
> > processes within a Landlock domains. (Mickaël convinced me in
> > discussion at FOSDEM that this is true.)
> >
> > If someone absolutely does not want that, they can restrict
> > LANDLOCK_ACCESS_FS_MAKE_SOCK and achieve the same effect (as
> > Tingmao said above).
> >
> > (pro2) The implementation of this is simpler.
> >
> > (I attempted to understand how the "or" semantics would be
> > implemented, and I found it non-trivial when you try to do it
> > for all layers at once. (Kernighan's Law applies, IMHO))
>
> I think the logic would basically be:
>
> 1. if any layers deny the access due to handled RESOLVE_UNIX but does not
> have the scope bit set, then we will deny rightaway, without calling
> domain_is_scoped().
>
> 2. Call domain_is_scoped() with a bitmask of "rules_covered" layers where
> there are RESOLVE_UNIX rules covering the socket being accessed, and
> essentially ignore those layers in the scope violation check.
>
> I definitely agree that it is tricky, but making same-scope access be
> allowed (i.e. the suggested idea above) would only get rid of step 1,
> which I think is the "simpler" bit. The extra logic in step 2 is still
> needed.
>
> I definitely agree with pro1 tho.
Yes, you are describing the logic for the variant where
LANDLOCK_ACCESS_FS_RESOLVE_UNIX does not implicitly permit access from
within the same scope. In that variant, there can be situations where
the first hook can deny the action immediately.
In the variant where LANDLOCK_ACCESS_FS_RESOLVE_UNIX *does* implicitly
allow access from within the same scope, that shortcutting is not
possible. On the upside however, there is no need to distinguish
whether the scope flag is set when we are in the security_unix_find()
hook, because access from within the same scope is always permitted.
(That is the simplification I meant.)
> > AGAINST:
> >
> > (con1) It would work differently than the other scoped access rights
> > that we already have.
> >
> > A speculative feature that could potentially be built with the
> > scoped access rights is that we could add a rule to permit IPC
> > to other Landlock scopes, e.g. introducing a new rule type
> >
> > struct landlock_scope_attr {
> > __u64 allowed_access; /* for "scoped" bits */
> > /* some way to identify domains */
> > }
> >
> > so that we could make IPC access to other Landlock domains
> > configurable.
> >
> > If the scoped bit and the FS RESOLVE_UNIX bit were both
> > conflated in RESOLVE_UNIX, it would not be possible to make
> > UNIX connections configurable in such a way.
>
> This exact API would no longer work, but if we give up the equivalence
> between scope bits and the landlock_scope_attr struct, then we can do
> something like:
>
> struct landlock_scope_attr {
> __u64 ptrace:1; /* Note that this is not a (user controllable) scope bit! */
> __u64 abstract_unix_socket:1;
> __u64 pathname_unix_socket:1;
> /* ... */
>
> __u64 allowed_signals;
>
> /*
> * some way to identify domains, maybe we could use the audit domain
> * ID, with 0 denoting "allow access to non-Landlocked processes?
> */
> }
Yes, it would be possible to use such a struct for that scenario where
IPC access gets allowed for other Landlock scopes. It would mean that
we would not need to introduce a scoped flag for the pathname UNIX
socket connections. But the relationship between that struct
landlock_scope_attr and the flags and access rights in struct
landlock_ruleset_attr would become less clear, which is a slight
downside, and maybe error prone for users to work with.
If we introduced an additional scoped flag, it would also be
consistent though.
(con1) was written under the assumption that we do not have an
additional scoped flag. If that is lacking, it is not possible to
express UNIX connect() access to other Landlock domains with that
struct. But as outlined in the proposal below, if we *do* (later)
introduce the additional scoped flag *in addition* to the FS access
right, this *both* stays consistent in semantics with the signal and
abstract UNIX support, *and* it starts working in a world where ICP
access can be allowed to talk to other Landlock domains.
> > (con2) Consistent behaviour between scoped flags and their
> > interactions with other access rights:
> >
> > The existing scoped access rights (signal, abstract sockets)
> > could hypothetically be extended with a related access right of
> > another type. For instance, there could be an access right type
> >
> > __u64 handled_signal_number;
> >
> > and then you could add a rule to permit the use of certain
> > signal numbers. The interaction between the scoped flags and
> > other access rights should work the same.
> >
> >
> > Constructive Proposal for consideration: Why not both?
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> I will think about the following a bit more but I'm afraid that I feel
> like it might get slightly confusing. With this, the only reason for
> having LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET is for API consistency when we
> later enable allowing access to other domains (if I understood correctly),
> in which case I personally feel like the suggestion on landlock_scope_attr
> above, where we essentially accept that it is decoupled with the scope
> bits in the ruleset, might be simpler...?
Mickaël expressed the opinion to me that he would like to APIs to stay
consistent between signals, abstract UNIX sockets, named UNIX sockets
and other future "scoped" operations, in scenarios where:
* the "scoped" (IPC) operations can be configured to give access to
other Landlock domains (and that should work for UNIX connections too)
* the existing "scoped" operations also start having matching access rights
I think with the way I proposed, that would be consistent.
> > Why not do both what Tingmao proposed in [1] **and** reserve the
> > option to add the matching "scoped flag" later?
> >
> > * Introduce LANDLOCK_ACCESS_FS_RESOLVE_UNIX.
> >
> > If it is handled, UNIX connections are allowed either:
> >
> > (1) if the connection is to a service in the same scope, or
> > (2) if the path was allow-listed with a "path beneath" rule.
> >
> > * Add LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET later, if needed.
> >
> >
> > Let's go through the arguments again:
> >
> > We have observed that it is harmless to allow connections to services
> > in the same scope (1), and that if users absolutely don't want that,
> > they can actually prohibit it through LANDLOCK_ACCESS_FS_MAKE_SOCK
> > (pro1).
> >
> > (con1): Can we still implement the feature idea where we poke a hole
> > to get UNIX-connect() access to other Landlock domains?
> >
> > I think the answer is yes. The implementation strategy is:
> >
> > * Add the scoped bit LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET
> > * The scoped bit can now be used to allow-list connections to
> > other Landlock domains.
> >
> > For users, just setting the scoped bit on its own does the same as
> > handling LANDLOCK_ACCESS_FS_RESOLVE_UNIX. That way, the kernel-side
> > implementation can also stay simple. The only reason why the scoped
> > bit is needed is because it makes it possible to allow-list
> > connections to other Landlock domains, but at the same time, it is
> > safe if libraries set the scoped bit once it exists, as it does not
> > have any bad runtime impact either.
> >
> > (con2): Consistency: Do all the scoped flags interact with their
> > corresponding access rights in the same way?
> >
> > The other scope flags do not have corresponding access rights, so
> > far.
> >
> > If we were to add corresponding access rights for the other scope
> > flags, I would argue that we could apply a consistent logic there,
> > because IPC access within the same scope is always safe:
> >
> > - A hypothetical access right type for "signal numbers" would only
> > restrict signals that go beyond the current scope.
> >
> > - A hypothetical access right type for "abstract UNIX domain socket
> > names" would only restrict connections to abstract UNIX domain
> > servers that go beyond the current scope.
> >
> > I can not come up with a scenario where this doesn't work.
> >
> >
> > In conclusion, I think the approach has significant upsides:
> >
> > * Simpler UAPI: Users only have one access bit to deal with, in the
> > near future. Once we do add a scope flag for UNIX connections, it
> > does not interact in a surprising way with the corresponding FS
> > access right, because with either of these, scoped access is
> > allowed.
> >
> > If users absolutely need to restrict scoped access, they can
> > restrict LANDLOCK_ACCESS_FS_MAKE_SOCK. It is a slightly obscure
> > API, but in line with the "make easy things easy, make hard things
> > possible" API philosophy. And needing this should be the
> > exception rather than the norm, after all.
> >
> > * Consistent behaviour between scoped flags and regular access
> > rights, also for speculative access rights affecting the existing
> > scoped flags for signals and abstract UNIX domain sockets.
> >
> > [1] https://lore.kernel.org/all/f07fe41a-96c5-4d3a-9966-35b30b3a71f1@maowtm.org/
—Günther
^ permalink raw reply
* Re: [PATCH 04/13] Apparmor: Use simple_start_creating() / simple_done_creating()
From: kernel test robot @ 2026-02-04 10:58 UTC (permalink / raw)
To: NeilBrown, Christian Brauner, Alexander Viro, David Howells,
Jan Kara, Chuck Lever, Jeff Layton, Miklos Szeredi,
Amir Goldstein, John Johansen, Paul Moore, James Morris,
Serge E. Hallyn, Stephen Smalley
Cc: oe-kbuild-all, linux-kernel, netfs, linux-fsdevel, linux-nfs,
linux-unionfs, apparmor, linux-security-module, selinux
In-Reply-To: <20260204050726.177283-5-neilb@ownmail.net>
Hi NeilBrown,
kernel test robot noticed the following build warnings:
[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on viro-vfs/for-next linus/master v6.19-rc8 next-20260203]
[cannot apply to pcmoore-selinux/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/NeilBrown/fs-proc-Don-t-lock-root-inode-when-creating-self-and-thread-self/20260204-131659
base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link: https://lore.kernel.org/r/20260204050726.177283-5-neilb%40ownmail.net
patch subject: [PATCH 04/13] Apparmor: Use simple_start_creating() / simple_done_creating()
config: arm-randconfig-r133-20260204 (https://download.01.org/0day-ci/archive/20260204/202602041851.x2RfFgKO-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260204/202602041851.x2RfFgKO-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602041851.x2RfFgKO-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
>> security/apparmor/apparmorfs.c:295:16: sparse: sparse: Using plain integer as NULL pointer
vim +295 security/apparmor/apparmorfs.c
247
248 /**
249 * aafs_create - create a dentry in the apparmorfs filesystem
250 *
251 * @name: name of dentry to create
252 * @mode: permissions the file should have
253 * @parent: parent directory for this dentry
254 * @data: data to store on inode.i_private, available in open()
255 * @link: if symlink, symlink target string
256 * @fops: struct file_operations that should be used for
257 * @iops: struct of inode_operations that should be used
258 *
259 * This is the basic "create a xxx" function for apparmorfs.
260 *
261 * Returns a pointer to a dentry if it succeeds, that must be free with
262 * aafs_remove(). Will return ERR_PTR on failure.
263 */
264 static struct dentry *aafs_create(const char *name, umode_t mode,
265 struct dentry *parent, void *data, void *link,
266 const struct file_operations *fops,
267 const struct inode_operations *iops)
268 {
269 struct dentry *dentry;
270 struct inode *dir;
271 int error;
272
273 AA_BUG(!name);
274 AA_BUG(!parent);
275
276 if (!(mode & S_IFMT))
277 mode = (mode & S_IALLUGO) | S_IFREG;
278
279 error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count);
280 if (error)
281 return ERR_PTR(error);
282
283 dir = d_inode(parent);
284
285 dentry = simple_start_creating(parent, name);
286 if (IS_ERR(dentry)) {
287 error = PTR_ERR(dentry);
288 goto fail;
289 }
290
291 error = __aafs_setup_d_inode(dir, dentry, mode, data, link, fops, iops);
292 simple_done_creating(dentry);
293 if (error)
294 goto fail;
> 295 return 0;
296 fail:
297 simple_release_fs(&aafs_mnt, &aafs_count);
298 return ERR_PTR(error);
299 }
300
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v3 1/5] lsm: Add hook security_unix_find
From: Günther Noack @ 2026-02-04 10:25 UTC (permalink / raw)
To: Günther Noack, Paul Moore, John Johansen, Tingmao Wang
Cc: Mickaël Salaün, James Morris, Serge E . Hallyn,
Justin Suess, linux-security-module, Samasth Norway Ananda,
Matthieu Buffet, Mikhail Ivanov, konstantin.meskhidze,
Demi Marie Obenour, Alyssa Ross, Jann Horn, Tahera Fahimi,
Simon Horman, netdev, Alexander Viro, Christian Brauner
In-Reply-To: <20260119203457.97676-4-gnoack3000@gmail.com>
Hello!
John:
Friendly ping; as Paul said in [1], we would appreciate a look from
the AppArmor side whether this path-based LSM hook makes sense for
you.
Everyone:
In [2], we are currently discussing how the UNIX restriction feature
would work in the bigger scheme in Landlock, and the current plan is
that long-term we would like to support semantics where a UNIX
connection attempt is allowed if EITHER:
(a) the path is allow-listed in the policy, OR
(b) the server side we connect to is part of the same Landlock
sandbox ("domain")
With the currently proposed hook, (a) can be checked in the
security_unix_find() hook, and (b) can be checked in the
security_hook_socket_connect() hook. Unfortunately, it also would
mean that if the (a) check fails, we would have to store that
information on the side (struct sock LSM blob?), return 0 from (a) and
then later use that information in hook (b), so that we can check
whether maybe the second possible condition is met.
Q: The passing of information across multiple LSM hooks is slightly
more complicated than I had hoped; is this an approach that is
recommended?
Therefore, in [2], Tingmao is suggesting that we change the
security_unix_find() hook and pass the "other" struct sock instead of
the type.
There is obviously a balance between hooks that are very generic and
usable across multiple LSMs and hooks that are convenient to use for
every LSM.
Paul:
You have previously said that you would like hooks to be generic and
ideally reflect the arguments of the same function that they are
called from [3].
Q: Would it be acceptable to change the hook arguments, if we can then
avoid passing additional data between hooks through that side-storage?
You can see Tingmao's proposal for that in [2]. TL;DR: It moves the
call to security_unix_find() just after the place where the sk
variable ("other"-side socket) is looked up and then calls the hook
with the sk as argument instead of with the type. That way, we can do
both check (a) and (b) from above in the same hook and do not need to
store data on the side. Is that an acceptable trade-off for the LSM
interface?
Thanks,
—Günther
[1] https://lore.kernel.org/all/CAHC9VhQZ_J9316Us0squV_f-MjYXPcex34BnJ14vEBxS9Jyjbg@mail.gmail.com/
[2] https://lore.kernel.org/all/e6b6b069-384c-4c45-a56b-fa54b26bc72a@maowtm.org/
[3] https://lore.kernel.org/all/CAHC9VhQ234xihpndTs4e5ToNJ3tGCsP7AVtXuz8GajG-_jn3Ow@mail.gmail.com/
^ permalink raw reply
* Re: [PATCH] xfrm: kill xfrm_dev_{state,policy}_flush_secctx_check()
From: Tetsuo Handa @ 2026-02-04 10:15 UTC (permalink / raw)
To: Paul Moore, SELinux, linux-security-module
Cc: Steffen Klassert, Herbert Xu, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Network Development
In-Reply-To: <CAHC9VhRzRAR+hhn4TFADnHWpzjOxjmh0S_Hg_HktkPkKQ35ycg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 780 bytes --]
On 2026/02/04 7:40, Paul Moore wrote:
> This is not an unusual request for such a proposed change, and
> is something that I would expect a LSM maintainer to do without much
> hesitation. If you are unwilling to investigate this, can you explain
> why?
Because I'm not familiar with how XFRM works; I'm not a user of LSM XFRM hooks.
I can't judge whether the current code is COMPREHENSIVELY GATING;
I can't imagine what the state you call COMPREHENSIVELY GATING is.
P.S. For your investigation, I attach a new report that syzbot found today, and
I'll drop "xfrm: always fail xfrm_dev_{state,policy}_flush_secctx_check()"
because these three reports will be sufficient for people to understand that
we need to kill xfrm_dev_{state,policy}_flush_secctx_check() calls.
[-- Attachment #2: report-0202-kernfs.txt --]
[-- Type: text/plain, Size: 90653 bytes --]
unregister_netdevice: waiting for netdevsim0 to become free. Usage count = 2
ref_tracker: netdev@ffff888028c4c630 has 1/1 users at
xfrm_dev_state_add+0x6f4/0xc40 net/xfrm/xfrm_device.c:316
xfrm_state_construct net/xfrm/xfrm_user.c:986 [inline]
xfrm_add_sa+0x34ca/0x4230 net/xfrm/xfrm_user.c:1022
xfrm_user_rcv_msg+0x746/0xb20 net/xfrm/xfrm_user.c:3507
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
xfrm_netlink_rcv+0x79/0x90 net/xfrm/xfrm_user.c:3529
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
__sock_sendmsg net/socket.c:752 [inline]
____sys_sendmsg+0x589/0x8c0 net/socket.c:2610
___sys_sendmsg+0x2a5/0x360 net/socket.c:2664
__sys_sendmsg net/socket.c:2696 [inline]
__do_sys_sendmsg net/socket.c:2701 [inline]
__se_sys_sendmsg net/socket.c:2699 [inline]
__x64_sys_sendmsg+0x1bd/0x2a0 net/socket.c:2699
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
infiniband: balance for netdevsim0@ib_gid_table_entry is 0
balance for netdevsim0@j1939_priv is 0
Call trace for netdevsim0[1] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
rx_queue_add_kobject net/core/net-sysfs.c:1257 [inline]
net_rx_queue_update_kobjects+0x148/0x750 net/core/net-sysfs.c:1322
register_queue_kobjects net/core/net-sysfs.c:2114 [inline]
netdev_register_kobject+0x21f/0x310 net/core/net-sysfs.c:2362
register_netdevice+0x12c0/0x1cf0 net/core/dev.c:11409
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
Call trace for netdevsim0[2] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
netdev_queue_add_kobject net/core/net-sysfs.c:1994 [inline]
netdev_queue_update_kobjects+0x170/0x6d0 net/core/net-sysfs.c:2056
register_queue_kobjects net/core/net-sysfs.c:2119 [inline]
netdev_register_kobject+0x258/0x310 net/core/net-sysfs.c:2362
register_netdevice+0x12c0/0x1cf0 net/core/dev.c:11409
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
Call trace for netdevsim0[3] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold+0x27/0xc0 include/linux/netdevice.h:4446
register_netdevice+0x15cc/0x1cf0 net/core/dev.c:11433
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
Call trace for netdevsim0[4] +3 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
netdevice_queue_work drivers/infiniband/core/roce_gid_mgmt.c:698 [inline]
netdevice_event+0x4ea/0x8d0 drivers/infiniband/core/roce_gid_mgmt.c:849
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
register_netdevice+0x173a/0x1cf0 net/core/dev.c:11447
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
Call trace for netdevsim0[5] +3 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
netdevice_queue_work drivers/infiniband/core/roce_gid_mgmt.c:699 [inline]
netdevice_event+0x593/0x8d0 drivers/infiniband/core/roce_gid_mgmt.c:849
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
register_netdevice+0x173a/0x1cf0 net/core/dev.c:11447
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
Call trace for netdevsim0[6] -10 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
dev_put include/linux/netdevice.h:4481 [inline]
netdevice_event_work_handler+0x12c/0x260 drivers/infiniband/core/roce_gid_mgmt.c:675
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[7] -10 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
dev_put include/linux/netdevice.h:4481 [inline]
netdevice_event_work_handler+0x1b2/0x260 drivers/infiniband/core/roce_gid_mgmt.c:676
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[8] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
neigh_parms_alloc+0x192/0x530 net/core/neighbour.c:1778
inetdev_init+0x118/0x4f0 net/ipv4/devinet.c:280
inetdev_event+0x30d/0x1610 net/ipv4/devinet.c:1590
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
register_netdevice+0x173a/0x1cf0 net/core/dev.c:11447
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
Call trace for netdevsim0[9] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
inetdev_init+0x19f/0x4f0 net/ipv4/devinet.c:286
inetdev_event+0x30d/0x1610 net/ipv4/devinet.c:1590
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
register_netdevice+0x173a/0x1cf0 net/core/dev.c:11447
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
Call trace for netdevsim0[10] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
neigh_parms_alloc+0x192/0x530 net/core/neighbour.c:1778
ipv6_add_dev+0x40d/0x13c0 net/ipv6/addrconf.c:403
addrconf_notify+0x771/0x1050 net/ipv6/addrconf.c:3655
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
register_netdevice+0x173a/0x1cf0 net/core/dev.c:11447
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
Call trace for netdevsim0[11] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
ipv6_add_dev+0x4ae/0x13c0 net/ipv6/addrconf.c:411
addrconf_notify+0x771/0x1050 net/ipv6/addrconf.c:3655
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
register_netdevice+0x173a/0x1cf0 net/core/dev.c:11447
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
Call trace for netdevsim0[12] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
batadv_hardif_add_interface net/batman-adv/hard-interface.c:878 [inline]
batadv_hard_if_event+0xb47/0x1240 net/batman-adv/hard-interface.c:958
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
register_netdevice+0x173a/0x1cf0 net/core/dev.c:11447
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
Call trace for netdevsim0[13] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
udp_tunnel_nic_register net/ipv4/udp_tunnel_nic.c:850 [inline]
udp_tunnel_nic_netdevice_event+0xaea/0x17e0 net/ipv4/udp_tunnel_nic.c:931
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
register_netdevice+0x173a/0x1cf0 net/core/dev.c:11447
nsim_init_netdevsim drivers/net/netdevsim/netdev.c:1064 [inline]
nsim_create+0xb92/0x1100 drivers/net/netdevsim/netdev.c:1146
__nsim_dev_port_add+0x72a/0xb50 drivers/net/netdevsim/dev.c:1494
nsim_dev_port_add_all+0x37/0xf0 drivers/net/netdevsim/dev.c:1550
nsim_drv_probe+0x905/0xc20 drivers/net/netdevsim/dev.c:1711
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x267/0xaf0 drivers/base/dd.c:661
__driver_probe_device+0x18c/0x320 drivers/base/dd.c:803
driver_probe_device+0x4f/0x240 drivers/base/dd.c:833
__device_attach_driver+0x2d4/0x4c0 drivers/base/dd.c:961
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c5/0x450 drivers/base/dd.c:1033
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1088
bus_probe_device+0x12a/0x220 drivers/base/bus.c:574
device_add+0x7b6/0xb70 drivers/base/core.c:3689
nsim_bus_dev_new drivers/net/netdevsim/bus.c:471 [inline]
new_device_store+0x37b/0x710 drivers/net/netdevsim/bus.c:191
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
Call trace for netdevsim0[14] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
qdisc_alloc+0x631/0x910 net/sched/sch_generic.c:985
qdisc_create_dflt+0x8e/0x510 net/sched/sch_generic.c:1008
attach_one_default_qdisc net/sched/sch_generic.c:1174 [inline]
netdev_for_each_tx_queue include/linux/netdevice.h:2688 [inline]
attach_default_qdiscs net/sched/sch_generic.c:1192 [inline]
dev_activate+0x378/0x1150 net/sched/sch_generic.c:1251
__dev_open+0x67a/0x830 net/core/dev.c:1704
__dev_change_flags+0x1f7/0x690 net/core/dev.c:9749
netif_change_flags+0x88/0x1a0 net/core/dev.c:9812
do_setlink+0xf82/0x4590 net/core/rtnetlink.c:3158
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[15] +3 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
netdevice_queue_work drivers/infiniband/core/roce_gid_mgmt.c:698 [inline]
netdevice_event+0x4ea/0x8d0 drivers/infiniband/core/roce_gid_mgmt.c:849
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
__dev_notify_flags+0x1a9/0x310 net/core/dev.c:9788
netif_change_flags+0xe8/0x1a0 net/core/dev.c:9817
do_setlink+0xf82/0x4590 net/core/rtnetlink.c:3158
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[16] +3 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
netdevice_queue_work drivers/infiniband/core/roce_gid_mgmt.c:699 [inline]
netdevice_event+0x593/0x8d0 drivers/infiniband/core/roce_gid_mgmt.c:849
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
__dev_notify_flags+0x1a9/0x310 net/core/dev.c:9788
netif_change_flags+0xe8/0x1a0 net/core/dev.c:9817
do_setlink+0xf82/0x4590 net/core/rtnetlink.c:3158
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[17] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_index+0x1b3/0x2f0 net/core/dev.c:995
netdev_get_by_index+0x25/0xb0 net/core/dev.c:1018
fib6_nh_init+0x1f2/0x2010 net/ipv6/route.c:3598
ip6_route_info_create_nh+0x16a/0xad0 net/ipv6/route.c:3898
ip6_route_add+0x6e/0x1b0 net/ipv6/route.c:3950
addrconf_add_mroute+0x2d1/0x370 net/ipv6/addrconf.c:2552
addrconf_add_dev net/ipv6/addrconf.c:2570 [inline]
addrconf_dev_config net/ipv6/addrconf.c:3484 [inline]
addrconf_init_auto_addrs+0x4d7/0xa50 net/ipv6/addrconf.c:3572
addrconf_notify+0xb1e/0x1050 net/ipv6/addrconf.c:3745
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
__dev_notify_flags+0x1a9/0x310 net/core/dev.c:9788
netif_change_flags+0xe8/0x1a0 net/core/dev.c:9817
do_setlink+0xf82/0x4590 net/core/rtnetlink.c:3158
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[18] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_index+0x1b3/0x2f0 net/core/dev.c:995
netdev_get_by_index+0x25/0xb0 net/core/dev.c:1018
fib6_nh_init+0x1f2/0x2010 net/ipv6/route.c:3598
ip6_route_info_create_nh+0x16a/0xad0 net/ipv6/route.c:3898
addrconf_f6i_alloc+0x3b7/0x630 net/ipv6/route.c:4690
ipv6_add_addr+0x59c/0x1100 net/ipv6/addrconf.c:1126
addrconf_add_linklocal+0x20c/0x460 net/ipv6/addrconf.c:3311
addrconf_addr_gen+0x2f8/0x360 net/ipv6/addrconf.c:3447
addrconf_notify+0xb1e/0x1050 net/ipv6/addrconf.c:3745
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
__dev_notify_flags+0x1a9/0x310 net/core/dev.c:9788
netif_change_flags+0xe8/0x1a0 net/core/dev.c:9817
do_setlink+0xf82/0x4590 net/core/rtnetlink.c:3158
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[19] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
addr_event+0x302/0x480 drivers/infiniband/core/roce_gid_mgmt.c:897
inet6addr_event+0x9f/0xd0 drivers/infiniband/core/roce_gid_mgmt.c:930
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
atomic_notifier_call_chain+0xda/0x180 kernel/notifier.c:223
ipv6_add_addr+0xe08/0x1100 net/ipv6/addrconf.c:1186
addrconf_add_linklocal+0x20c/0x460 net/ipv6/addrconf.c:3311
addrconf_addr_gen+0x2f8/0x360 net/ipv6/addrconf.c:3447
addrconf_notify+0xb1e/0x1050 net/ipv6/addrconf.c:3745
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
__dev_notify_flags+0x1a9/0x310 net/core/dev.c:9788
netif_change_flags+0xe8/0x1a0 net/core/dev.c:9817
do_setlink+0xf82/0x4590 net/core/rtnetlink.c:3158
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[20] -6 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
dev_put include/linux/netdevice.h:4481 [inline]
update_gid_event_work_handler+0x84/0xf0 drivers/infiniband/core/roce_gid_mgmt.c:861
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[21] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_index+0x1b3/0x2f0 net/core/dev.c:995
netdev_get_by_index+0x25/0xb0 net/core/dev.c:1018
fib6_nh_init+0x1f2/0x2010 net/ipv6/route.c:3598
ip6_route_info_create_nh+0x16a/0xad0 net/ipv6/route.c:3898
ip6_route_add+0x6e/0x1b0 net/ipv6/route.c:3950
addrconf_prefix_route+0x3a2/0x480 net/ipv6/addrconf.c:2488
addrconf_add_linklocal+0x266/0x460 net/ipv6/addrconf.c:3313
addrconf_addr_gen+0x2f8/0x360 net/ipv6/addrconf.c:3447
addrconf_notify+0xb1e/0x1050 net/ipv6/addrconf.c:3745
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
__dev_notify_flags+0x1a9/0x310 net/core/dev.c:9788
netif_change_flags+0xe8/0x1a0 net/core/dev.c:9817
do_setlink+0xf82/0x4590 net/core/rtnetlink.c:3158
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[22] +5 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dst_init+0x6f/0x490 net/core/dst.c:52
dst_alloc+0x12a/0x170 net/core/dst.c:94
ip6_dst_alloc net/ipv6/route.c:342 [inline]
icmp6_dst_alloc+0x75/0x440 net/ipv6/route.c:3333
mld_sendpack+0x6ba/0xe40 net/ipv6/mcast.c:1844
mld_send_cr net/ipv6/mcast.c:2154 [inline]
mld_ifc_work+0x835/0xe70 net/ipv6/mcast.c:2693
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[23] +2 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
___neigh_create+0xc3d/0x2290 net/core/neighbour.c:664
ip6_finish_output2+0x1038/0x1360 net/ipv6/ip6_output.c:128
NF_HOOK_COND include/linux/netfilter.h:307 [inline]
ip6_output+0x340/0x550 net/ipv6/ip6_output.c:247
NF_HOOK+0xa2/0x3a0 include/linux/netfilter.h:318
mld_sendpack+0x8b4/0xe40 net/ipv6/mcast.c:1855
mld_send_cr net/ipv6/mcast.c:2154 [inline]
mld_ifc_work+0x835/0xe70 net/ipv6/mcast.c:2693
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[24] -17 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
dst_destroy+0x117/0x360 net/core/dst.c:115
rcu_do_batch kernel/rcu/tree.c:2617 [inline]
rcu_core+0x7cd/0x1070 kernel/rcu/tree.c:2869
handle_softirqs+0x22a/0x870 kernel/softirq.c:626
Call trace for netdevsim0[25] +2 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dst_init+0x6f/0x490 net/core/dst.c:52
dst_alloc+0x12a/0x170 net/core/dst.c:94
ip6_dst_alloc net/ipv6/route.c:342 [inline]
icmp6_dst_alloc+0x75/0x440 net/ipv6/route.c:3333
ndisc_send_skb+0x42d/0x14e0 net/ipv6/ndisc.c:491
ndisc_send_ns+0xd7/0x160 net/ipv6/ndisc.c:670
addrconf_dad_work+0xac4/0x14c0 net/ipv6/addrconf.c:4287
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[26] +2 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
___neigh_create+0xc3d/0x2290 net/core/neighbour.c:664
ip6_finish_output2+0x1038/0x1360 net/ipv6/ip6_output.c:128
NF_HOOK_COND include/linux/netfilter.h:307 [inline]
ip6_output+0x340/0x550 net/ipv6/ip6_output.c:247
NF_HOOK include/linux/netfilter.h:318 [inline]
ndisc_send_skb+0xbaa/0x14e0 net/ipv6/ndisc.c:512
ndisc_send_ns+0xd7/0x160 net/ipv6/ndisc.c:670
addrconf_dad_work+0xac4/0x14c0 net/ipv6/addrconf.c:4287
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[27] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
addr_event+0x302/0x480 drivers/infiniband/core/roce_gid_mgmt.c:897
inetaddr_event+0xef/0x150 drivers/infiniband/core/roce_gid_mgmt.c:916
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380
__inet_insert_ifa+0x9e9/0xbc0 net/ipv4/devinet.c:566
inet_rtm_newaddr+0x10d8/0x1ad0 net/ipv4/devinet.c:1001
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[28] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_index+0x1b3/0x2f0 net/core/dev.c:995
fib_create_info+0x2296/0x31f0 net/ipv4/fib_semantics.c:1493
fib_table_insert+0xc8/0x1b50 net/ipv4/fib_trie.c:1212
fib_magic+0x434/0x510 net/ipv4/fib_frontend.c:1134
fib_add_ifaddr+0x144/0x5f0 net/ipv4/fib_frontend.c:1156
fib_inetaddr_event+0x12e/0x190 net/ipv4/fib_frontend.c:1470
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380
__inet_insert_ifa+0x9e9/0xbc0 net/ipv4/devinet.c:566
inet_rtm_newaddr+0x10d8/0x1ad0 net/ipv4/devinet.c:1001
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[29] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
fib_check_nh_nongw net/ipv4/fib_semantics.c:1263 [inline]
fib_check_nh+0xd1e/0x1b60 net/ipv4/fib_semantics.c:1283
fib_create_info+0x2085/0x31f0 net/ipv4/fib_semantics.c:1503
fib_table_insert+0xc8/0x1b50 net/ipv4/fib_trie.c:1212
fib_magic+0x434/0x510 net/ipv4/fib_frontend.c:1134
fib_add_ifaddr+0x38d/0x5f0 net/ipv4/fib_frontend.c:1171
fib_inetaddr_event+0x12e/0x190 net/ipv4/fib_frontend.c:1470
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380
__inet_insert_ifa+0x9e9/0xbc0 net/ipv4/devinet.c:566
inet_rtm_newaddr+0x10d8/0x1ad0 net/ipv4/devinet.c:1001
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[30] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
fib_check_nh_nongw net/ipv4/fib_semantics.c:1263 [inline]
fib_check_nh+0xd1e/0x1b60 net/ipv4/fib_semantics.c:1283
fib_create_info+0x2085/0x31f0 net/ipv4/fib_semantics.c:1503
fib_table_insert+0xc8/0x1b50 net/ipv4/fib_trie.c:1212
fib_magic+0x434/0x510 net/ipv4/fib_frontend.c:1134
fib_add_ifaddr+0x3fb/0x5f0 net/ipv4/fib_frontend.c:1178
fib_inetaddr_event+0x12e/0x190 net/ipv4/fib_frontend.c:1470
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380
__inet_insert_ifa+0x9e9/0xbc0 net/ipv4/devinet.c:566
inet_rtm_newaddr+0x10d8/0x1ad0 net/ipv4/devinet.c:1001
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[31] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_index+0x1b3/0x2f0 net/core/dev.c:995
netdev_get_by_index+0x25/0xb0 net/core/dev.c:1018
fib6_nh_init+0x1f2/0x2010 net/ipv6/route.c:3598
ip6_route_info_create_nh+0x16a/0xad0 net/ipv6/route.c:3898
ip6_route_add+0x6e/0x1b0 net/ipv6/route.c:3950
addrconf_add_mroute+0x2d1/0x370 net/ipv6/addrconf.c:2552
addrconf_add_dev net/ipv6/addrconf.c:2570 [inline]
inet6_addr_add+0x2dd/0xb20 net/ipv6/addrconf.c:3032
inet6_rtm_newaddr+0xa17/0xe30 net/ipv6/addrconf.c:5064
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[32] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_index+0x1b3/0x2f0 net/core/dev.c:995
netdev_get_by_index+0x25/0xb0 net/core/dev.c:1018
fib6_nh_init+0x1f2/0x2010 net/ipv6/route.c:3598
ip6_route_info_create_nh+0x16a/0xad0 net/ipv6/route.c:3898
addrconf_f6i_alloc+0x3b7/0x630 net/ipv6/route.c:4690
ipv6_add_addr+0x59c/0x1100 net/ipv6/addrconf.c:1126
inet6_addr_add+0x454/0xb20 net/ipv6/addrconf.c:3050
inet6_rtm_newaddr+0xa17/0xe30 net/ipv6/addrconf.c:5064
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[33] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
addr_event+0x302/0x480 drivers/infiniband/core/roce_gid_mgmt.c:897
inet6addr_event+0x9f/0xd0 drivers/infiniband/core/roce_gid_mgmt.c:930
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
atomic_notifier_call_chain+0xda/0x180 kernel/notifier.c:223
ipv6_add_addr+0xe08/0x1100 net/ipv6/addrconf.c:1186
inet6_addr_add+0x454/0xb20 net/ipv6/addrconf.c:3050
inet6_rtm_newaddr+0xa17/0xe30 net/ipv6/addrconf.c:5064
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[34] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_index+0x1b3/0x2f0 net/core/dev.c:995
netdev_get_by_index+0x25/0xb0 net/core/dev.c:1018
fib6_nh_init+0x1f2/0x2010 net/ipv6/route.c:3598
ip6_route_info_create_nh+0x16a/0xad0 net/ipv6/route.c:3898
ip6_route_add+0x6e/0x1b0 net/ipv6/route.c:3950
addrconf_prefix_route+0x3a2/0x480 net/ipv6/addrconf.c:2488
inet6_addr_add+0x508/0xb20 net/ipv6/addrconf.c:3053
inet6_rtm_newaddr+0xa17/0xe30 net/ipv6/addrconf.c:5064
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[35] +3 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
netdevice_queue_work drivers/infiniband/core/roce_gid_mgmt.c:698 [inline]
netdevice_event+0x4ea/0x8d0 drivers/infiniband/core/roce_gid_mgmt.c:849
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
netif_set_mac_address+0x39f/0x4e0 net/core/dev.c:9990
do_setlink+0x9b1/0x4590 net/core/rtnetlink.c:3110
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[36] +3 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
netdevice_queue_work drivers/infiniband/core/roce_gid_mgmt.c:699 [inline]
netdevice_event+0x593/0x8d0 drivers/infiniband/core/roce_gid_mgmt.c:849
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
netif_set_mac_address+0x39f/0x4e0 net/core/dev.c:9990
do_setlink+0x9b1/0x4590 net/core/rtnetlink.c:3110
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[37] -2 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
neigh_destroy+0x35c/0x5d0 net/core/neighbour.c:940
neigh_flush_dev net/core/neighbour.c:433 [inline]
neigh_changeaddr+0xde/0x130 net/core/neighbour.c:457
ndisc_netdev_event+0x18f/0x4d0 net/ipv6/ndisc.c:1862
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
netif_set_mac_address+0x39f/0x4e0 net/core/dev.c:9990
do_setlink+0x9b1/0x4590 net/core/rtnetlink.c:3110
rtnl_changelink net/core/rtnetlink.c:3776 [inline]
__rtnl_newlink net/core/rtnetlink.c:3935 [inline]
rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072
rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
__sock_sendmsg net/socket.c:752 [inline]
__sys_sendto+0x3ff/0x590 net/socket.c:2221
__do_sys_sendto net/socket.c:2228 [inline]
__se_sys_sendto net/socket.c:2224 [inline]
__x64_sys_sendto+0xde/0x100 net/socket.c:2224
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[38] -6 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
fib_nh_common_release+0x5c/0x430 net/ipv4/fib_semantics.c:204
fib6_info_destroy_rcu+0xca/0x1c0 net/ipv6/ip6_fib.c:177
rcu_do_batch kernel/rcu/tree.c:2617 [inline]
rcu_core+0x7cd/0x1070 kernel/rcu/tree.c:2869
handle_softirqs+0x22a/0x870 kernel/softirq.c:626
Call trace for netdevsim0[39] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dst_init+0x6f/0x490 net/core/dst.c:52
dst_alloc+0x12a/0x170 net/core/dst.c:94
ip6_dst_alloc net/ipv6/route.c:342 [inline]
icmp6_dst_alloc+0x75/0x440 net/ipv6/route.c:3333
mld_sendpack+0x6ba/0xe40 net/ipv6/mcast.c:1844
ipv6_mc_dad_complete+0x88/0x540 net/ipv6/mcast.c:2279
addrconf_dad_completed+0x8a7/0xe60 net/ipv6/addrconf.c:4345
addrconf_dad_work+0xc5e/0x14c0 net/ipv6/addrconf.c:-1
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[40] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dst_init+0x6f/0x490 net/core/dst.c:52
dst_alloc+0x12a/0x170 net/core/dst.c:94
ip6_dst_alloc net/ipv6/route.c:342 [inline]
icmp6_dst_alloc+0x75/0x440 net/ipv6/route.c:3333
ndisc_send_skb+0x42d/0x14e0 net/ipv6/ndisc.c:491
addrconf_dad_completed+0x909/0xe60 net/ipv6/addrconf.c:4365
addrconf_dad_work+0xc5e/0x14c0 net/ipv6/addrconf.c:-1
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[41] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
___neigh_create+0xc3d/0x2290 net/core/neighbour.c:664
ip6_finish_output2+0x1038/0x1360 net/ipv6/ip6_output.c:128
NF_HOOK_COND include/linux/netfilter.h:307 [inline]
ip6_output+0x340/0x550 net/ipv6/ip6_output.c:247
NF_HOOK include/linux/netfilter.h:318 [inline]
ndisc_send_skb+0xbaa/0x14e0 net/ipv6/ndisc.c:512
addrconf_dad_completed+0x909/0xe60 net/ipv6/addrconf.c:4365
addrconf_dad_work+0xc5e/0x14c0 net/ipv6/addrconf.c:-1
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[42] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dst_init+0x6f/0x490 net/core/dst.c:52
dst_alloc+0x12a/0x170 net/core/dst.c:94
ip6_dst_alloc net/ipv6/route.c:342 [inline]
icmp6_dst_alloc+0x75/0x440 net/ipv6/route.c:3333
mld_sendpack+0x6ba/0xe40 net/ipv6/mcast.c:1844
mld_dad_work+0x45/0x5b0 net/ipv6/mcast.c:2294
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
Call trace for netdevsim0[43] +7 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dst_init+0x6f/0x490 net/core/dst.c:52
dst_alloc+0x12a/0x170 net/core/dst.c:94
ip6_dst_alloc net/ipv6/route.c:342 [inline]
icmp6_dst_alloc+0x75/0x440 net/ipv6/route.c:3333
ndisc_send_skb+0x42d/0x14e0 net/ipv6/ndisc.c:491
addrconf_rs_timer+0x395/0x6d0 net/ipv6/addrconf.c:4042
call_timer_fn+0x192/0x640 kernel/time/timer.c:1748
expire_timers kernel/time/timer.c:1799 [inline]
__run_timers kernel/time/timer.c:2373 [inline]
__run_timer_base+0x652/0x8b0 kernel/time/timer.c:2385
run_timer_base kernel/time/timer.c:2394 [inline]
run_timer_softirq+0xb7/0x170 kernel/time/timer.c:2404
handle_softirqs+0x22a/0x870 kernel/softirq.c:626
Call trace for netdevsim0[44] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_index+0x1b3/0x2f0 net/core/dev.c:995
xfrm_dev_state_add+0x33a/0xc40 net/xfrm/xfrm_device.c:268
xfrm_state_construct net/xfrm/xfrm_user.c:986 [inline]
xfrm_add_sa+0x34ca/0x4230 net/xfrm/xfrm_user.c:1022
xfrm_user_rcv_msg+0x746/0xb20 net/xfrm/xfrm_user.c:3507
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
xfrm_netlink_rcv+0x79/0x90 net/xfrm/xfrm_user.c:3529
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[45] -6 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
neigh_destroy+0x35c/0x5d0 net/core/neighbour.c:940
neigh_periodic_work+0xb4f/0xe50 net/core/neighbour.c:1029
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
process_scheduled_works kernel/workqueue.c:3362 [inline]
worker_thread+0xb46/0x1140 kernel/workqueue.c:3443
kthread+0x388/0x470 kernel/kthread.c:467
ret_from_fork+0x51e/0xb90 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
Call trace for netdevsim0[46] +3 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
___neigh_create+0xc3d/0x2290 net/core/neighbour.c:664
ip6_finish_output2+0x1038/0x1360 net/ipv6/ip6_output.c:128
NF_HOOK_COND include/linux/netfilter.h:307 [inline]
ip6_output+0x340/0x550 net/ipv6/ip6_output.c:247
NF_HOOK include/linux/netfilter.h:318 [inline]
ndisc_send_skb+0xbaa/0x14e0 net/ipv6/ndisc.c:512
addrconf_rs_timer+0x395/0x6d0 net/ipv6/addrconf.c:4042
call_timer_fn+0x192/0x640 kernel/time/timer.c:1748
expire_timers kernel/time/timer.c:1799 [inline]
__run_timers kernel/time/timer.c:2373 [inline]
__run_timer_base+0x652/0x8b0 kernel/time/timer.c:2385
run_timer_base kernel/time/timer.c:2394 [inline]
run_timer_softirq+0xb7/0x170 kernel/time/timer.c:2404
handle_softirqs+0x22a/0x870 kernel/softirq.c:626
Call trace for netdevsim0[47] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
dev_get_by_name+0xdb/0x210 net/core/dev.c:909
netdev_get_by_name+0x27/0xb0 net/core/dev.c:933
ethnl_parse_header_dev_get+0x445/0x8b0 net/ethtool/netlink.c:194
ethnl_default_parse net/ethtool/netlink.c:457 [inline]
ethnl_default_set_doit+0x224/0xae0 net/ethtool/netlink.c:895
genl_family_rcv_msg_doit+0x22a/0x330 net/netlink/genetlink.c:1115
genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline]
genl_rcv_msg+0x61c/0x7a0 net/netlink/genetlink.c:1210
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[48] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
ethnl_parse_header_dev_put net/ethtool/netlink.h:274 [inline]
ethnl_default_set_doit+0x92e/0xae0 net/ethtool/netlink.c:940
genl_family_rcv_msg_doit+0x22a/0x330 net/netlink/genetlink.c:1115
genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline]
genl_rcv_msg+0x61c/0x7a0 net/netlink/genetlink.c:1210
netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec+0x18f/0x1d0 net/socket.c:737
Call trace for netdevsim0[49] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
linkwatch_add_event net/core/link_watch.c:131 [inline]
linkwatch_fire_event+0x166/0x220 net/core/link_watch.c:314
nsim_stop+0x88/0x430 drivers/net/netdevsim/netdev.c:595
__dev_close_many+0x368/0x6d0 net/core/dev.c:1768
netif_close_many+0x225/0x420 net/core/dev.c:1793
netif_close_many_and_unlock net/core/dev.c:12317 [inline]
unregister_netdevice_many_notify+0x81f/0x2380 net/core/dev.c:12381
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[50] +2 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
addr_event+0x302/0x480 drivers/infiniband/core/roce_gid_mgmt.c:897
inet6addr_event+0x9f/0xd0 drivers/infiniband/core/roce_gid_mgmt.c:930
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
atomic_notifier_call_chain+0xda/0x180 kernel/notifier.c:223
addrconf_ifdown+0xeb3/0x1a40 net/ipv6/addrconf.c:3983
addrconf_notify+0x1bc/0x1050 net/ipv6/addrconf.c:-1
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
netif_close_many+0x2ae/0x420 net/core/dev.c:1797
netif_close_many_and_unlock net/core/dev.c:12317 [inline]
unregister_netdevice_many_notify+0x81f/0x2380 net/core/dev.c:12381
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
Call trace for netdevsim0[51] -3 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
fib_nh_common_release+0x5c/0x430 net/ipv4/fib_semantics.c:204
fib_nh_release net/ipv4/fib_semantics.c:218 [inline]
free_fib_info_rcu+0xdf/0x310 net/ipv4/fib_semantics.c:230
rcu_do_batch kernel/rcu/tree.c:2617 [inline]
rcu_core+0x7cd/0x1070 kernel/rcu/tree.c:2869
handle_softirqs+0x22a/0x870 kernel/softirq.c:626
Call trace for netdevsim0[52] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
__qdisc_destroy+0x1c9/0x450 net/sched/sch_generic.c:1081
qdisc_put net/sched/sch_generic.c:1105 [inline]
dev_shutdown+0x34c/0x440 net/sched/sch_generic.c:1493
unregister_netdevice_many_notify+0x11a9/0x2380 net/core/dev.c:12405
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[53] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
netdevice_queue_work drivers/infiniband/core/roce_gid_mgmt.c:698 [inline]
netdevice_event+0x4ea/0x8d0 drivers/infiniband/core/roce_gid_mgmt.c:849
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
unregister_netdevice_many_notify+0x186a/0x2380 net/core/dev.c:12417
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[54] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
netdevice_queue_work drivers/infiniband/core/roce_gid_mgmt.c:699 [inline]
netdevice_event+0x593/0x8d0 drivers/infiniband/core/roce_gid_mgmt.c:849
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
unregister_netdevice_many_notify+0x186a/0x2380 net/core/dev.c:12417
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[55] +1 at
__dev_hold include/linux/netdevice.h:4403 [inline]
netdev_hold include/linux/netdevice.h:4446 [inline]
dev_hold include/linux/netdevice.h:4469 [inline]
addr_event+0x302/0x480 drivers/infiniband/core/roce_gid_mgmt.c:897
inetaddr_event+0xef/0x150 drivers/infiniband/core/roce_gid_mgmt.c:916
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380
__inet_del_ifa+0x840/0xfe0 net/ipv4/devinet.c:450
inet_del_ifa net/ipv4/devinet.c:487 [inline]
inetdev_destroy net/ipv4/devinet.c:328 [inline]
inetdev_event+0x647/0x1610 net/ipv4/devinet.c:1655
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
unregister_netdevice_many_notify+0x186a/0x2380 net/core/dev.c:12417
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
Call trace for netdevsim0[56] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
neigh_parms_release+0x170/0x200 net/core/neighbour.c:1817
inetdev_destroy net/ipv4/devinet.c:335 [inline]
inetdev_event+0x7f4/0x1610 net/ipv4/devinet.c:1655
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
unregister_netdevice_many_notify+0x186a/0x2380 net/core/dev.c:12417
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[57] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
neigh_parms_release+0x170/0x200 net/core/neighbour.c:1817
addrconf_ifdown+0x177b/0x1a40 net/ipv6/addrconf.c:4012
addrconf_notify+0x1bc/0x1050 net/ipv6/addrconf.c:-1
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
unregister_netdevice_many_notify+0x186a/0x2380 net/core/dev.c:12417
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[58] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
batadv_hardif_release net/batman-adv/hard-interface.c:55 [inline]
kref_put include/linux/kref.h:65 [inline]
batadv_hardif_put+0x8f/0x140 net/batman-adv/hard-interface.h:94
batadv_hard_if_event+0x624/0x1240 net/batman-adv/hard-interface.c:1008
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
unregister_netdevice_many_notify+0x186a/0x2380 net/core/dev.c:12417
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[59] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
in6_dev_finish_destroy+0xdd/0x1e0 net/ipv6/addrconf_core.c:273
in6_dev_put include/net/addrconf.h:422 [inline]
ip6_dst_ifdown+0xed/0x220 net/ipv6/route.c:384
dst_dev_put+0xab/0x2d0 net/core/dst.c:151
fib6_nh_release_dsts net/ipv6/route.c:3740 [inline]
fib6_nh_release+0x36c/0x430 net/ipv6/route.c:3721
fib6_info_destroy_rcu+0xca/0x1c0 net/ipv6/ip6_fib.c:177
rcu_do_batch kernel/rcu/tree.c:2617 [inline]
rcu_core+0x7cd/0x1070 kernel/rcu/tree.c:2869
handle_softirqs+0x22a/0x870 kernel/softirq.c:626
Call trace for netdevsim0[60] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
dev_put include/linux/netdevice.h:4481 [inline]
udp_tunnel_nic_unregister net/ipv4/udp_tunnel_nic.c:913 [inline]
udp_tunnel_nic_netdevice_event+0x1582/0x17e0 net/ipv4/udp_tunnel_nic.c:942
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
unregister_netdevice_many_notify+0x186a/0x2380 net/core/dev.c:12417
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[61] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
rx_queue_release+0x126/0x1a0 net/core/net-sysfs.c:1181
kobject_cleanup lib/kobject.c:689 [inline]
kobject_release lib/kobject.c:720 [inline]
kref_put include/linux/kref.h:65 [inline]
kobject_put+0x228/0x560 lib/kobject.c:737
net_rx_queue_update_kobjects+0x6a6/0x750 net/core/net-sysfs.c:1338
remove_queue_kobjects net/core/net-sysfs.c:2169 [inline]
netdev_unregister_kobject+0x113/0x450 net/core/net-sysfs.c:2325
unregister_netdevice_many_notify+0x1e0e/0x2380 net/core/dev.c:12452
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[62] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
netdev_queue_release+0x6a/0xd0 net/core/net-sysfs.c:1931
kobject_cleanup lib/kobject.c:689 [inline]
kobject_release lib/kobject.c:720 [inline]
kref_put include/linux/kref.h:65 [inline]
kobject_put+0x228/0x560 lib/kobject.c:737
netdev_queue_update_kobjects+0x5e8/0x6d0 net/core/net-sysfs.c:2073
remove_queue_kobjects net/core/net-sysfs.c:2170 [inline]
netdev_unregister_kobject+0x11f/0x450 net/core/net-sysfs.c:2325
unregister_netdevice_many_notify+0x1e0e/0x2380 net/core/dev.c:12452
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[63] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
in_dev_finish_destroy+0xa7/0x1a0 net/ipv4/devinet.c:258
in_dev_put include/linux/inetdevice.h:290 [inline]
inet_rcu_free_ifa+0x72/0xb0 net/ipv4/devinet.c:228
rcu_do_batch kernel/rcu/tree.c:2617 [inline]
rcu_core+0x7cd/0x1070 kernel/rcu/tree.c:2869
handle_softirqs+0x22a/0x870 kernel/softirq.c:626
Call trace for netdevsim0[64] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
netdev_put include/linux/netdevice.h:4456 [inline]
unregister_netdevice_many_notify+0x2068/0x2380 net/core/dev.c:12462
unregister_netdevice_many net/core/dev.c:12480 [inline]
unregister_netdevice_queue+0x31f/0x360 net/core/dev.c:12294
unregister_netdevice include/linux/netdevice.h:3414 [inline]
nsim_destroy+0x1e5/0x680 drivers/net/netdevsim/netdev.c:1183
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Call trace for netdevsim0[65] -1 at
__dev_put include/linux/netdevice.h:4389 [inline]
linkwatch_do_dev+0x89/0x180 net/core/link_watch.c:191
__linkwatch_run_queue+0x572/0x7f0 net/core/link_watch.c:244
linkwatch_event+0x4c/0x60 net/core/link_watch.c:304
process_one_work+0x949/0x1650 kernel/workqueue.c:3279
balance as of netdevsim0[65] is 1
xfrm_dev_state_flush_secctx_check: LSM policy is rejecting this operation.
CPU: 0 UID: 0 PID: 18368 Comm: syz-executor Tainted: G L syzkaller #0 PREEMPT(full)
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/24/2026
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
xfrm_dev_state_flush_secctx_check net/xfrm/xfrm_state.c:900 [inline]
xfrm_dev_state_flush+0x5fa/0x740 net/xfrm/xfrm_state.c:971
xfrm_dev_unregister net/xfrm/xfrm_device.c:549 [inline]
xfrm_dev_event+0x1bc/0x3f0 net/xfrm/xfrm_device.c:570
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
netdev_wait_allrefs_any net/core/dev.c:11589 [inline]
netdev_run_todo+0x778/0x1130 net/core/dev.c:11710
nsim_destroy+0x3ae/0x680 drivers/net/netdevsim/netdev.c:1190
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fd13375b78e
Code: 08 0f 85 a5 a8 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 80 00 00 00 00 48 83 ec 08
RSP: 002b:00007ffc52b936a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 0000555567157500 RCX: 00007fd13375b78e
RDX: 0000000000000001 RSI: 00007ffc52b93730 RDI: 0000000000000005
RBP: 00007fd133808a88 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007ffc52b93730 R14: 00007fd134544620 R15: 0000000000000003
</TASK>
xfrm_dev_state_flush_secctx_check: LSM policy is rejecting this operation.
CPU: 0 UID: 0 PID: 18368 Comm: syz-executor Tainted: G L syzkaller #0 PREEMPT(full)
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/24/2026
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
xfrm_dev_state_flush_secctx_check net/xfrm/xfrm_state.c:900 [inline]
xfrm_dev_state_flush+0x5fa/0x740 net/xfrm/xfrm_state.c:971
xfrm_dev_unregister net/xfrm/xfrm_device.c:549 [inline]
xfrm_dev_event+0x1bc/0x3f0 net/xfrm/xfrm_device.c:570
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
netdev_wait_allrefs_any net/core/dev.c:11589 [inline]
netdev_run_todo+0x778/0x1130 net/core/dev.c:11710
nsim_destroy+0x3ae/0x680 drivers/net/netdevsim/netdev.c:1190
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fd13375b78e
Code: 08 0f 85 a5 a8 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 80 00 00 00 00 48 83 ec 08
RSP: 002b:00007ffc52b936a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 0000555567157500 RCX: 00007fd13375b78e
RDX: 0000000000000001 RSI: 00007ffc52b93730 RDI: 0000000000000005
RBP: 00007fd133808a88 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007ffc52b93730 R14: 00007fd134544620 R15: 0000000000000003
</TASK>
xfrm_dev_state_flush_secctx_check: LSM policy is rejecting this operation.
CPU: 0 UID: 0 PID: 18368 Comm: syz-executor Tainted: G L syzkaller #0 PREEMPT(full)
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/24/2026
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
xfrm_dev_state_flush_secctx_check net/xfrm/xfrm_state.c:900 [inline]
xfrm_dev_state_flush+0x5fa/0x740 net/xfrm/xfrm_state.c:971
xfrm_dev_unregister net/xfrm/xfrm_device.c:549 [inline]
xfrm_dev_event+0x1bc/0x3f0 net/xfrm/xfrm_device.c:570
notifier_call_chain+0x1be/0x400 kernel/notifier.c:85
call_netdevice_notifiers_extack net/core/dev.c:2281 [inline]
call_netdevice_notifiers net/core/dev.c:2295 [inline]
netdev_wait_allrefs_any net/core/dev.c:11589 [inline]
netdev_run_todo+0x778/0x1130 net/core/dev.c:11710
nsim_destroy+0x3ae/0x680 drivers/net/netdevsim/netdev.c:1190
__nsim_dev_port_del+0x14d/0x1b0 drivers/net/netdevsim/dev.c:1529
nsim_dev_port_del_all drivers/net/netdevsim/dev.c:1541 [inline]
nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1765
nsim_drv_remove+0x58/0x170 drivers/net/netdevsim/dev.c:1780
device_remove drivers/base/dd.c:571 [inline]
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x46f/0x860 drivers/base/dd.c:1307
bus_remove_device+0x34d/0x440 drivers/base/bus.c:616
device_del+0x527/0x8f0 drivers/base/core.c:3878
device_unregister+0x21/0xf0 drivers/base/core.c:3919
nsim_bus_dev_del drivers/net/netdevsim/bus.c:491 [inline]
del_device_store+0x2b0/0x370 drivers/net/netdevsim/bus.c:244
kernfs_fop_write_iter+0x3af/0x540 fs/kernfs/file.c:352
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x61d/0xb90 fs/read_write.c:688
ksys_write+0x150/0x270 fs/read_write.c:740
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fd13375b78e
Code: 08 0f 85 a5 a8 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 80 00 00 00 00 48 83 ec 08
RSP: 002b:00007ffc52b936a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 0000555567157500 RCX: 00007fd13375b78e
RDX: 0000000000000001 RSI: 00007ffc52b93730 RDI: 0000000000000005
RBP: 00007fd133808a88 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007ffc52b93730 R14: 00007fd134544620 R15: 0000000000000003
</TASK>
^ permalink raw reply
* Re: [PATCH] man/man7/kernel_lockdown.7: remove Secure Boot untruth
From: Nicolas Bouchinet @ 2026-02-04 9:03 UTC (permalink / raw)
To: Alyssa Ross
Cc: Alejandro Colomar, Heinrich Schuchardt, David Howells,
Xiu Jianfeng, linux-security-module, linux-man
In-Reply-To: <20260203195001.20131-1-hi@alyssa.is>
Hi,
On Tue, Feb 03, 2026 at 08:50:01PM +0100, Alyssa Ross wrote:
> This is true for Fedora, where this page was sourced from, but I don't
> believe it has ever been true for the mainline kernel, because Linus
> rejected it.
>
I confirm this has never been merged upstream.
Idealy we really need to rewrite Lockdown documentation, it has changed
a lot since it was first introduced.
> Link: https://bbs.archlinux.org/viewtopic.php?pid=2088704#p2088704
> Link: https://lore.kernel.org/lkml/CA+55aFzYbpRAdma0PvqE+9ygySuKzNKByqOzzMufBoovXVnfPw@mail.gmail.com/
> Fixes: bb509e6fc ("kernel_lockdown.7: New page documenting the Kernel Lockdown feature")
> Signed-off-by: Alyssa Ross <hi@alyssa.is>
> ---
> man/man7/kernel_lockdown.7 | 3 ---
> 1 file changed, 3 deletions(-)
>
> diff --git a/man/man7/kernel_lockdown.7 b/man/man7/kernel_lockdown.7
> index 5090484ea..5986c8f01 100644
> --- a/man/man7/kernel_lockdown.7
> +++ b/man/man7/kernel_lockdown.7
> @@ -23,9 +23,6 @@ Lockdown: X: Y is restricted, see man kernel_lockdown.7
> .in
> .P
> where X indicates the process name and Y indicates what is restricted.
> -.P
> -On an EFI-enabled x86 or arm64 machine, lockdown will be automatically enabled
> -if the system boots in EFI Secure Boot mode.
> .\"
> .SS Coverage
> When lockdown is in effect, a number of features are disabled or have their
> --
> 2.52.0
Best regards,
Nicolas
^ permalink raw reply
* Re: [PATCH RESEND] apparmor: Replace deprecated strcpy with memcpy in gen_symlink_name
From: John Johansen @ 2026-02-04 8:22 UTC (permalink / raw)
To: Thorsten Blum
Cc: Paul Moore, James Morris, Serge E. Hallyn, apparmor,
linux-security-module, linux-kernel
In-Reply-To: <3CA1F386-2217-405B-AB6E-85195AD09CA8@linux.dev>
On 2/1/26 04:42, Thorsten Blum wrote:
> Hi John,
>
> On 27. Nov 2025, at 11:18, Thorsten Blum wrote:
>> On 27. Nov 2025, at 02:32, John Johansen wrote:
>>> hey Thorsten,
>>>
>>> sorry I have actually pulled these in, and tested them. I didn't send out
>>> the acks yet because I have another patch that I was waiting on a proper
>>> signed-off-by: on.
>>>
>>> I am going to have to pull that one so I can push. I'll add acks now but
>>> the push isn't going to happen for a few hours.
>>>
>>> Acked-by: John Johansen <john.johansen@canonical.com>
>>
>> Ah sorry for resending then, didn't know you looked at them already.
>
> Did you ever push the commits? I can't find them anywhere.
>
sorry I am having "fun" email issue atm
it should be in apparmor-next. I have been staging that through gitlab
https://gitlab.com/apparmor/apparmor-kernel
and
https://gitlab.com/jjohansen/apparmor-kernel
trying to get better CI integration with the userspace side. It was stuck
again and I had to manually kick it last week.
^ permalink raw reply
* Re: [PATCH net-next v2 0/4] net: uapi: Provide an UAPI definition of 'struct sockaddr'
From: Thomas Weißschuh @ 2026-02-04 5:51 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Simon Horman, Shuah Khan, Matthieu Baerts,
Mat Martineau, Geliang Tang, Mickaël Salaün,
Günther Noack, Alexei Starovoitov, Daniel Borkmann,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, netdev, linux-kernel,
linux-api, Arnd Bergmann, linux-kselftest, mptcp,
linux-security-module, bpf, libc-alpha, Carlos O'Donell,
Adhemerval Zanella, Rich Felker, klibc, Florian Weimer
In-Reply-To: <20260203144011.32d5b223@kernel.org>
On Tue, Feb 03, 2026 at 02:40:11PM -0800, Jakub Kicinski wrote:
> On Tue, 3 Feb 2026 12:42:22 +0100 Thomas Weißschuh wrote:
> > > FWIW the typelimits change broke compilation of ethtool, we'll see if
> > > anyone "outside kernel community itself" complains.
> >
> > Can you point me to that breakage? I was unable to find it.
>
> Not reported on the ML, and it's kinda annoying to repro because
> the uAPI header sync script isn't committed :/ You have to check
> this out
>
> https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/
>
> and run a script like this to sync headers from the kernel (then build):
>
> #!/bin/bash -e
>
> sn="${0##*/}"
> export ARCH="x86_64"
>
> if [ ! -d "$LINUX_GIT" ]; then
> echo "${sn}: LINUX_GIT not set" >&2
> exit 1
> fi
>
> pushd "$LINUX_GIT"
> if [ -n "$1" ]; then
> git checkout "$1"
> fi
> desc=$(git describe --exact-match 2>/dev/null \
> || git show -s --abbrev=12 --pretty='commit %h')
> kobj=$(mktemp -d)
> make -j16 O="$kobj" allmodconfig
> make -j16 O="$kobj" prepare
These are not necessary.
The UAPI generation does not need a kernel configuration.
> make -j16 O="$kobj" INSTALL_HDR_PATH="${kobj}/hdr" headers_install
> popd
>
> pushd uapi
> find . -type f -name '*.h' -exec cp -v "${kobj}/hdr/include/{}" {} \;
Here only those headers which already exist in ethtool's uapi/ directory
are copied. As linux/typelimits.h is new, it is now missing.
Honestly, if a user fiddles with the internals of the UAPI headers like
this, it is on them to update their code if the internal structure
changes. In your case a simple 'touch uapi/linux/typelimits.h'
before running the script will be enough. Also internal.h now requires
an explicit inclusion of <limits.h>, as that is not satisfied by the
UAPI anymore.
> popd
> rm -rf "$kobj"
>
> git add uapi
> git commit -s -F - <<EOT
> update UAPI header copies
>
> Update to kernel ${desc}.
>
> EOT
^ permalink raw reply
* [PATCH 13/13] VFS: unexport lock_rename(), lock_rename_child(), unlock_rename()
From: NeilBrown @ 2026-02-04 4:57 UTC (permalink / raw)
To: Christian Brauner, Alexander Viro, David Howells, Jan Kara,
Chuck Lever, Jeff Layton, Miklos Szeredi, Amir Goldstein,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Stephen Smalley
Cc: linux-kernel, netfs, linux-fsdevel, linux-nfs, linux-unionfs,
apparmor, linux-security-module, selinux
In-Reply-To: <20260204050726.177283-1-neilb@ownmail.net>
From: NeilBrown <neil@brown.name>
These three function are now only used in namei.c, so they don't need to
be exported.
Signed-off-by: NeilBrown <neil@brown.name>
---
Documentation/filesystems/porting.rst | 7 +++++++
fs/namei.c | 9 +++------
include/linux/namei.h | 3 ---
3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index ed86c95d9d01..5f7008172f14 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1347,3 +1347,10 @@ implementation should set it to generic_setlease().
lookup_one_qstr_excl() is no longer exported - use start_creating() or
similar.
+---
+
+** mandatory**
+
+lock_rename(), lock_rename_child(), unlock_rename() are no
+longer available. Use start_renaming() or similar.
+
diff --git a/fs/namei.c b/fs/namei.c
index 307b4d0866b8..0bc82bf90adc 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3713,7 +3713,7 @@ static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2)
/*
* p1 and p2 should be directories on the same fs.
*/
-struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
+static struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
{
if (p1 == p2) {
inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
@@ -3723,12 +3723,11 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
mutex_lock(&p1->d_sb->s_vfs_rename_mutex);
return lock_two_directories(p1, p2);
}
-EXPORT_SYMBOL(lock_rename);
/*
* c1 and p2 should be on the same fs.
*/
-struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2)
+static struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2)
{
if (READ_ONCE(c1->d_parent) == p2) {
/*
@@ -3765,9 +3764,8 @@ struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2)
mutex_unlock(&c1->d_sb->s_vfs_rename_mutex);
return NULL;
}
-EXPORT_SYMBOL(lock_rename_child);
-void unlock_rename(struct dentry *p1, struct dentry *p2)
+static void unlock_rename(struct dentry *p1, struct dentry *p2)
{
inode_unlock(p1->d_inode);
if (p1 != p2) {
@@ -3775,7 +3773,6 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
mutex_unlock(&p1->d_sb->s_vfs_rename_mutex);
}
}
-EXPORT_SYMBOL(unlock_rename);
/**
* __start_renaming - lookup and lock names for rename
diff --git a/include/linux/namei.h b/include/linux/namei.h
index c7a7288cdd25..2ad6dd9987b9 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -165,9 +165,6 @@ extern int follow_down_one(struct path *);
extern int follow_down(struct path *path, unsigned int flags);
extern int follow_up(struct path *);
-extern struct dentry *lock_rename(struct dentry *, struct dentry *);
-extern struct dentry *lock_rename_child(struct dentry *, struct dentry *);
-extern void unlock_rename(struct dentry *, struct dentry *);
int start_renaming(struct renamedata *rd, int lookup_flags,
struct qstr *old_last, struct qstr *new_last);
int start_renaming_dentry(struct renamedata *rd, int lookup_flags,
--
2.50.0.107.gf914562f5916.dirty
^ permalink raw reply related
* [PATCH 12/13] ovl: remove ovl_lock_rename_workdir()
From: NeilBrown @ 2026-02-04 4:57 UTC (permalink / raw)
To: Christian Brauner, Alexander Viro, David Howells, Jan Kara,
Chuck Lever, Jeff Layton, Miklos Szeredi, Amir Goldstein,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Stephen Smalley
Cc: linux-kernel, netfs, linux-fsdevel, linux-nfs, linux-unionfs,
apparmor, linux-security-module, selinux
In-Reply-To: <20260204050726.177283-1-neilb@ownmail.net>
From: NeilBrown <neil@brown.name>
This function is unused.
Signed-off-by: NeilBrown <neil@brown.name>
---
fs/overlayfs/overlayfs.h | 2 --
fs/overlayfs/util.c | 25 -------------------------
2 files changed, 27 deletions(-)
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 4fb4750a83e4..3eedc2684c23 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -569,8 +569,6 @@ bool ovl_is_inuse(struct dentry *dentry);
bool ovl_need_index(struct dentry *dentry);
int ovl_nlink_start(struct dentry *dentry);
void ovl_nlink_end(struct dentry *dentry);
-int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *work,
- struct dentry *upperdir, struct dentry *upper);
int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path,
struct ovl_metacopy *data);
int ovl_set_metacopy_xattr(struct ovl_fs *ofs, struct dentry *d,
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 94986d11a166..810c8752b4f7 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -1213,31 +1213,6 @@ void ovl_nlink_end(struct dentry *dentry)
ovl_inode_unlock(inode);
}
-int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *work,
- struct dentry *upperdir, struct dentry *upper)
-{
- struct dentry *trap;
-
- /* Workdir should not be subdir of upperdir and vice versa */
- trap = lock_rename(workdir, upperdir);
- if (IS_ERR(trap))
- goto err;
- if (trap)
- goto err_unlock;
- if (work && (work->d_parent != workdir || d_unhashed(work)))
- goto err_unlock;
- if (upper && (upper->d_parent != upperdir || d_unhashed(upper)))
- goto err_unlock;
-
- return 0;
-
-err_unlock:
- unlock_rename(workdir, upperdir);
-err:
- pr_err("failed to lock workdir+upperdir\n");
- return -EIO;
-}
-
/*
* err < 0, 0 if no metacopy xattr, metacopy data size if xattr found.
* an empty xattr returns OVL_METACOPY_MIN_SIZE to distinguish from no xattr value.
--
2.50.0.107.gf914562f5916.dirty
^ permalink raw reply related
* [PATCH 11/13] ovl: use is_subdir() for testing if one thing is a subdir of another
From: NeilBrown @ 2026-02-04 4:57 UTC (permalink / raw)
To: Christian Brauner, Alexander Viro, David Howells, Jan Kara,
Chuck Lever, Jeff Layton, Miklos Szeredi, Amir Goldstein,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Stephen Smalley
Cc: linux-kernel, netfs, linux-fsdevel, linux-nfs, linux-unionfs,
apparmor, linux-security-module, selinux
In-Reply-To: <20260204050726.177283-1-neilb@ownmail.net>
From: NeilBrown <neil@brown.name>
Rather than using lock_rename(), use the more obvious is_subdir() for
ensuring that neither upper nor workdir contain the other.
Also be explicit in the comment that the two directories cannot be the
same.
As this is a point-it-time sanity check and does not provide any
on-going guarantees, the removal of locking does not introduce any
interesting races.
Signed-off-by: NeilBrown <neil@brown.name>
---
fs/overlayfs/super.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index ba9146f22a2c..2fd3e0aee50e 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -451,18 +451,13 @@ static int ovl_lower_dir(const char *name, const struct path *path,
return 0;
}
-/* Workdir should not be subdir of upperdir and vice versa */
+/*
+ * Workdir should not be subdir of upperdir and vice versa, and
+ * they should not be the same.
+ */
static bool ovl_workdir_ok(struct dentry *workdir, struct dentry *upperdir)
{
- bool ok = false;
-
- if (workdir != upperdir) {
- struct dentry *trap = lock_rename(workdir, upperdir);
- if (!IS_ERR(trap))
- unlock_rename(workdir, upperdir);
- ok = (trap == NULL);
- }
- return ok;
+ return !is_subdir(workdir, upperdir) && !is_subdir(upperdir, workdir);
}
static int ovl_setup_trap(struct super_block *sb, struct dentry *dir,
--
2.50.0.107.gf914562f5916.dirty
^ permalink raw reply related
* [PATCH 10/13] ovl: change ovl_create_real() to get a new lock when re-opening created file.
From: NeilBrown @ 2026-02-04 4:57 UTC (permalink / raw)
To: Christian Brauner, Alexander Viro, David Howells, Jan Kara,
Chuck Lever, Jeff Layton, Miklos Szeredi, Amir Goldstein,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Stephen Smalley
Cc: linux-kernel, netfs, linux-fsdevel, linux-nfs, linux-unionfs,
apparmor, linux-security-module, selinux
In-Reply-To: <20260204050726.177283-1-neilb@ownmail.net>
From: NeilBrown <neil@brown.name>
When ovl_create_real() is used to create a file on the upper filesystem
it needs to return the resulting dentry - positive and hashed.
It is usually the case the that dentry passed to the create function
(e.g. vfs_create()) will be suitable but this is not guaranteed. The
filesystem may unhash that dentry forcing a repeat lookup next time the
name is wanted.
So ovl_create_real() must be (and is) aware of this and prepared to
perform that lookup to get a hash positive dentry.
This is currently done under that same directory lock that provided
exclusion for the create. Proposed changes to locking will make this
not possible - as the name, rather than the directory, will be locked.
The new APIs provided for lookup and locking do not and cannot support
this pattern.
The lock isn't needed. ovl_create_real() can drop the lock and then get
a new lock for the lookup - then check that the lookup returned the
correct inode. In a well-behaved configuration where the upper
filesystem is not being modified by a third party, this will always work
reliably, and if there are separate modification it will fail cleanly.
So change ovl_create_real() to drop the lock and call
ovl_start_creating_upper() to find the correct dentry. Note that
start_creating doesn't fail if the name already exists.
This removes the only remaining use of ovl_lookup_upper, so it is
removed.
Signed-off-by: NeilBrown <neil@brown.name>
---
fs/overlayfs/dir.c | 24 ++++++++++++++++++------
fs/overlayfs/overlayfs.h | 7 -------
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index ff3dbd1ca61f..ec08904d084d 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -219,21 +219,33 @@ struct dentry *ovl_create_real(struct ovl_fs *ofs, struct dentry *parent,
err = -EIO;
} else if (d_unhashed(newdentry)) {
struct dentry *d;
+ struct name_snapshot name;
/*
* Some filesystems (i.e. casefolded) may return an unhashed
- * negative dentry from the ovl_lookup_upper() call before
+ * negative dentry from the ovl_start_creating_upper() call before
* ovl_create_real().
* In that case, lookup again after making the newdentry
* positive, so ovl_create_upper() always returns a hashed
* positive dentry.
+ * As we have to drop the lock before the lookup a race
+ * could result in a lookup failure. In that case we return
+ * an error.
*/
- d = ovl_lookup_upper(ofs, newdentry->d_name.name, parent,
- newdentry->d_name.len);
- dput(newdentry);
- if (IS_ERR_OR_NULL(d))
+ take_dentry_name_snapshot(&name, newdentry);
+ end_creating_keep(newdentry);
+ d = ovl_start_creating_upper(ofs, parent, &name.name);
+ release_dentry_name_snapshot(&name);
+
+ if (IS_ERR_OR_NULL(d)) {
err = d ? PTR_ERR(d) : -ENOENT;
- else
+ } else if (d->d_inode != newdentry->d_inode) {
+ err = -EIO;
+ dput(newdentry);
+ } else {
+ dput(newdentry);
return d;
+ }
+ return ERR_PTR(err);
}
out:
if (err) {
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 315882a360ce..4fb4750a83e4 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -406,13 +406,6 @@ static inline struct file *ovl_do_tmpfile(struct ovl_fs *ofs,
return file;
}
-static inline struct dentry *ovl_lookup_upper(struct ovl_fs *ofs,
- const char *name,
- struct dentry *base, int len)
-{
- return lookup_one(ovl_upper_mnt_idmap(ofs), &QSTR_LEN(name, len), base);
-}
-
static inline struct dentry *ovl_lookup_upper_unlocked(struct ovl_fs *ofs,
const char *name,
struct dentry *base,
--
2.50.0.107.gf914562f5916.dirty
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox