public inbox for linux-security-module@vger.kernel.org
 help / color / mirror / Atom feed
From: Chris Mason <clm@meta.com>
To: NeilBrown <neil@brown.name>
Cc: Christian Brauner <brauner@kernel.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	David Howells <dhowells@redhat.com>, Jan Kara <jack@suse.cz>,
	Chuck Lever <chuck.lever@oracle.com>,
	Jeff Layton <jlayton@kernel.org>,
	Miklos Szeredi <miklos@szeredi.hu>,
	Amir Goldstein <amir73il@gmail.com>,
	John Johansen <john.johansen@canonical.com>,
	Paul Moore <paul@paul-moore.com>,
	James Morris <jmorris@namei.org>,
	"Serge E. Hallyn" <serge@hallyn.com>,
	Stephen Smalley <stephen.smalley.work@gmail.com>,
	"Darrick J. Wong" <djwong@kernel.org>,
	<linux-kernel@vger.kernel.org>, <netfs@lists.linux.dev>,
	<linux-fsdevel@vger.kernel.org>, <linux-nfs@vger.kernel.org>,
	<linux-unionfs@vger.kernel.org>, <apparmor@lists.ubuntu.com>,
	<linux-security-module@vger.kernel.org>,
	<selinux@vger.kernel.org>
Subject: Re: [PATCH v2 12/15] ovl: change ovl_create_real() to get a new lock when re-opening created file.
Date: Mon, 23 Feb 2026 05:23:00 -0800	[thread overview]
Message-ID: <20260223132424.105125-1-clm@meta.com> (raw)
In-Reply-To: <20260223011210.3853517-13-neilb@ownmail.net>

NeilBrown <neilb@ownmail.net> wrote:
> 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.
> 

Hi everyone,

Amir suggested I run these through, and this commit was flagged:

commit 62d49d1e44667e4f93bec415faabec5526992ac0
Author: NeilBrown <neil@brown.name>

ovl: change ovl_create_real() to get a new lock when re-opening created file.

This commit changes ovl_create_real() to drop the directory lock and
reacquire a new lock for lookup when the created dentry is unhashed. It
also removes ovl_lookup_upper() which is no longer used.

Signed-off-by: NeilBrown <neil@brown.name>

> diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
> index c4feb89ad1e39..6285069ccc590 100644
> --- a/fs/overlayfs/dir.c
> +++ b/fs/overlayfs/dir.c
> @@ -159,7 +159,8 @@ int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct dentry *dir,
>  }
>
>  struct dentry *ovl_create_real(struct ovl_fs *ofs, struct dentry *parent,
> -			       struct dentry *newdentry, struct ovl_cattr *attr)
> +			       struct dentry *newdentry, struct qstr *qname,
> +			       struct ovl_cattr *attr)
>  {
>  	struct inode *dir = parent->d_inode;
>  	int err;
> @@ -221,19 +222,29 @@ struct dentry *ovl_create_real(struct ovl_fs *ofs, struct dentry *parent,
>  		struct dentry *d;
>  		/*
>  		 * 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.
> +		 * positive dentry.  We lookup using qname which should be
> +		 * the same name as newentry, but is certain not to change.
> +		 * 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))
> +		end_creating_keep(newdentry);
> +		d = ovl_start_creating_upper(ofs, parent, qname);
> +
> +		if (IS_ERR_OR_NULL(d)) {
>  			err = d ? PTR_ERR(d) : -ENOENT;
> +		} else if (d->d_inode != newdentry->d_inode) {
> +			err = -EIO;
> +			dput(newdentry);
> +		} else {
> +			dput(newdentry);
>  			return d;
> +		}
> +		return ERR_PTR(err);
>  	}

Does this leak the newdentry reference when IS_ERR_OR_NULL(d) is true?

The code now calls end_creating_keep(newdentry) which keeps the reference,
then calls ovl_start_creating_upper(). If that returns an error or NULL,
the function returns ERR_PTR(err) without cleaning up newdentry:

	end_creating_keep(newdentry);
	d = ovl_start_creating_upper(ofs, parent, qname);

	if (IS_ERR_OR_NULL(d)) {
		err = d ? PTR_ERR(d) : -ENOENT;
	} ...
	return ERR_PTR(err);

The old code always went through the 'out:' label which called
end_creating(newdentry) on error. The new code bypasses that cleanup.


Does this leak both the parent lock and the dentry 'd' when the lookup
returns a different inode?

When d->d_inode != newdentry->d_inode, the code sets err = -EIO and calls
dput(newdentry), but doesn't clean up 'd':

	} else if (d->d_inode != newdentry->d_inode) {
		err = -EIO;
		dput(newdentry);
	} ...
	return ERR_PTR(err);

The dentry 'd' was returned by ovl_start_creating_upper() with the parent
directory lock held. The code needs to call end_creating(d) to release the
lock via end_dirop()->inode_unlock() and release the dentry reference via
end_dirop()->dput().


  parent reply	other threads:[~2026-02-23 13:25 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-23  1:06 [PATCH v2 00/15] Further centralising of directory locking for name ops NeilBrown
2026-02-23  1:06 ` [PATCH v2 01/15] VFS: note error returns is documentation for various lookup functions NeilBrown
2026-02-23 13:52   ` Chris Mason
2026-02-23 22:04     ` NeilBrown
2026-02-23  1:06 ` [PATCH v2 02/15] fs/proc: Don't lock root inode when creating "self" and "thread-self" NeilBrown
2026-02-23  1:06 ` [PATCH v2 03/15] VFS: move the start_dirop() kerndoc comment to before start_dirop() NeilBrown
2026-02-23  1:06 ` [PATCH v2 04/15] libfs: change simple_done_creating() to use end_creating() NeilBrown
2026-02-23  1:06 ` [PATCH v2 05/15] Apparmor: Use simple_start_creating() / simple_done_creating() NeilBrown
2026-02-23  1:06 ` [PATCH v2 06/15] selinux: " NeilBrown
2026-02-23 13:24   ` Chris Mason
2026-02-23 17:31     ` Paul Moore
2026-02-23 22:07       ` NeilBrown
2026-02-23  1:06 ` [PATCH v2 07/15] nfsd: switch purge_old() to use start_removing_noperm() NeilBrown
2026-02-23  1:06 ` [PATCH v2 08/15] VFS: make lookup_one_qstr_excl() static NeilBrown
2026-02-23  1:06 ` [PATCH v2 09/15] ovl: Simplify ovl_lookup_real_one() NeilBrown
2026-02-23  9:49   ` Amir Goldstein
2026-02-23 13:13   ` Chris Mason
2026-02-23 13:42     ` Amir Goldstein
2026-02-23 22:21       ` NeilBrown
2026-02-23  1:06 ` [PATCH v2 10/15] cachefiles: change cachefiles_bury_object to use start_renaming_dentry() NeilBrown
2026-02-23  1:06 ` [PATCH v2 11/15] ovl: pass name buffer to ovl_start_creating_temp() NeilBrown
2026-02-23  9:35   ` Amir Goldstein
2026-02-23  1:06 ` [PATCH v2 12/15] ovl: change ovl_create_real() to get a new lock when re-opening created file NeilBrown
2026-02-23  9:39   ` Amir Goldstein
2026-02-23 13:23   ` Chris Mason [this message]
2026-02-23 22:30     ` NeilBrown
2026-02-24  9:20     ` Christian Brauner
2026-02-23  1:06 ` [PATCH v2 13/15] ovl: use is_subdir() for testing if one thing is a subdir of another NeilBrown
2026-02-23  1:06 ` [PATCH v2 14/15] ovl: remove ovl_lock_rename_workdir() NeilBrown
2026-02-23  1:06 ` [PATCH v2 15/15] VFS: unexport lock_rename(), lock_rename_child(), unlock_rename() NeilBrown

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20260223132424.105125-1-clm@meta.com \
    --to=clm@meta.com \
    --cc=amir73il@gmail.com \
    --cc=apparmor@lists.ubuntu.com \
    --cc=brauner@kernel.org \
    --cc=chuck.lever@oracle.com \
    --cc=dhowells@redhat.com \
    --cc=djwong@kernel.org \
    --cc=jack@suse.cz \
    --cc=jlayton@kernel.org \
    --cc=jmorris@namei.org \
    --cc=john.johansen@canonical.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=neil@brown.name \
    --cc=netfs@lists.linux.dev \
    --cc=paul@paul-moore.com \
    --cc=selinux@vger.kernel.org \
    --cc=serge@hallyn.com \
    --cc=stephen.smalley.work@gmail.com \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

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

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