From: Al Viro <viro@zeniv.linux.org.uk>
To: NeilBrown <neilb@suse.de>
Cc: Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
Kent Overstreet <kent.overstreet@linux.dev>,
Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>,
Namjae Jeon <linkinjeon@kernel.org>,
Steve French <sfrench@samba.org>,
Sergey Senozhatsky <senozhatsky@chromium.org>,
Tom Talpey <tom@talpey.com>, Paul Moore <paul@paul-moore.com>,
Eric Paris <eparis@redhat.com>,
linux-kernel@vger.kernel.org, linux-bcachefs@vger.kernel.org,
linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org,
linux-cifs@vger.kernel.org, audit@vger.kernel.org
Subject: Re: [PATCH 2/2] VFS: add common error checks to lookup_one_qstr_excl()
Date: Wed, 12 Feb 2025 03:25:05 +0000 [thread overview]
Message-ID: <20250212032505.GM1977892@ZenIV> (raw)
In-Reply-To: <20250212031608.GL1977892@ZenIV>
On Wed, Feb 12, 2025 at 03:16:08AM +0000, Al Viro wrote:
> On Fri, Feb 07, 2025 at 02:36:48PM +1100, NeilBrown wrote:
> > @@ -1690,6 +1692,15 @@ struct dentry *lookup_one_qstr_excl(const struct qstr *name,
> > dput(dentry);
> > dentry = old;
> > }
> > +found:
>
> ... and if ->lookup() returns an error, this will blow up (as bot has just
> reported).
>
> > + if (d_is_negative(dentry) && !(flags & LOOKUP_CREATE)) {
> > + dput(dentry);
> > + return ERR_PTR(-ENOENT);
> > + }
> > + if (d_is_positive(dentry) && (flags & LOOKUP_EXCL)) {
> > + dput(dentry);
> > + return ERR_PTR(-EEXIST);
> > + }
>
>
> > @@ -4077,27 +4084,13 @@ static struct dentry *filename_create(int dfd, struct filename *name,
> > * '/', and a directory wasn't requested.
> > */
> > if (last.name[last.len] && !want_dir)
> > - create_flags = 0;
> > + create_flags &= ~LOOKUP_CREATE;
>
> See the patch I've posted in earlier thread; the entire "strip LOOKUP_CREATE"
> thing is wrong.
On top of mainline that's
filename_create(): don't force handling trailing slashes into the common path
Only mkdir accepts pathnames that end with / - anything like mknod() (symlink(),
etc.) always fails on those. Don't try to force that the common codepath -
all we are doing is a lookup and check for existence to determine which
error should it be. Do that before bothering with mnt_want_write(), etc.;
as far as underlying filesystem is concerned it's just a lookup. Simplifies
the normal codepath and kills the lookup intent dependency on more than
the call site.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
diff --git a/fs/namei.c b/fs/namei.c
index 3ab9440c5b93..6189e54f767a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4054,13 +4054,13 @@ static struct dentry *filename_create(int dfd, struct filename *name,
struct dentry *dentry = ERR_PTR(-EEXIST);
struct qstr last;
bool want_dir = lookup_flags & LOOKUP_DIRECTORY;
- unsigned int reval_flag = lookup_flags & LOOKUP_REVAL;
- unsigned int create_flags = LOOKUP_CREATE | LOOKUP_EXCL;
int type;
int err2;
int error;
- error = filename_parentat(dfd, name, reval_flag, path, &last, &type);
+ lookup_flags &= LOOKUP_REVAL;
+
+ error = filename_parentat(dfd, name, lookup_flags, path, &last, &type);
if (error)
return ERR_PTR(error);
@@ -4070,18 +4070,28 @@ static struct dentry *filename_create(int dfd, struct filename *name,
*/
if (unlikely(type != LAST_NORM))
goto out;
+ /*
+ * mkdir foo/bar/ is OK, but for anything else a slash in the end
+ * is always an error; the only question is which one.
+ */
+ if (unlikely(last.name[last.len] && !want_dir)) {
+ dentry = lookup_dcache(&last, path->dentry, lookup_flags);
+ if (!dentry)
+ dentry = lookup_slow(&last, path->dentry, lookup_flags);
+ if (!IS_ERR(dentry)) {
+ error = d_is_positive(dentry) ? -EEXIST : -ENOENT;
+ dput(dentry);
+ dentry = ERR_PTR(error);
+ }
+ goto out;
+ }
/* don't fail immediately if it's r/o, at least try to report other errors */
err2 = mnt_want_write(path->mnt);
- /*
- * Do the final lookup. Suppress 'create' if there is a trailing
- * '/', and a directory wasn't requested.
- */
- if (last.name[last.len] && !want_dir)
- create_flags = 0;
+ /* do the final lookup */
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
dentry = lookup_one_qstr_excl(&last, path->dentry,
- reval_flag | create_flags);
+ lookup_flags | LOOKUP_CREATE | LOOKUP_EXCL);
if (IS_ERR(dentry))
goto unlock;
@@ -4089,16 +4099,6 @@ static struct dentry *filename_create(int dfd, struct filename *name,
if (d_is_positive(dentry))
goto fail;
- /*
- * Special case - lookup gave negative, but... we had foo/bar/
- * From the vfs_mknod() POV we just have a negative dentry -
- * all is fine. Let's be bastards - you had / on the end, you've
- * been asking for (non-existent) directory. -ENOENT for you.
- */
- if (unlikely(!create_flags)) {
- error = -ENOENT;
- goto fail;
- }
if (unlikely(err2)) {
error = err2;
goto fail;
next prev parent reply other threads:[~2025-02-12 3:25 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-07 3:36 [PATCH 0/2] VFS: minor improvements to a couple of interfaces NeilBrown
2025-02-07 3:36 ` [PATCH 1/2] VFS: change kern_path_locked() and user_path_locked_at() to never return negative dentry NeilBrown
2025-02-07 3:46 ` Kent Overstreet
2025-02-07 4:53 ` NeilBrown
2025-02-07 6:13 ` Kent Overstreet
2025-02-07 6:34 ` NeilBrown
2025-02-07 6:51 ` Kent Overstreet
2025-02-07 7:30 ` NeilBrown
2025-02-07 13:35 ` Kent Overstreet
2025-02-10 1:20 ` NeilBrown
2025-02-10 16:33 ` Kent Overstreet
2025-02-12 3:24 ` NeilBrown
2025-02-07 6:51 ` [PATCH 1/2 v2] " NeilBrown
2025-02-07 6:53 ` [PATCH 1/2] " NeilBrown
2025-02-07 19:09 ` Paul Moore
2025-02-07 3:36 ` [PATCH 2/2] VFS: add common error checks to lookup_one_qstr_excl() NeilBrown
2025-02-12 2:50 ` kernel test robot
2025-02-12 3:16 ` Al Viro
2025-02-12 3:25 ` Al Viro [this message]
2025-02-12 3:45 ` NeilBrown
2025-02-12 4:06 ` Al Viro
2025-02-12 4:40 ` NeilBrown
2025-02-10 8:25 ` [PATCH 0/2] VFS: minor improvements to a couple of interfaces Christian Brauner
2025-02-10 8:42 ` Al Viro
2025-02-10 9:41 ` Christian Brauner
-- strict thread matches above, loose matches on Subject: below --
2025-02-17 0:27 [PATCH 0/2 v2] " NeilBrown
2025-02-17 0:27 ` [PATCH 2/2] VFS: add common error checks to lookup_one_qstr_excl() NeilBrown
2025-02-17 13:46 ` Jeff Layton
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=20250212032505.GM1977892@ZenIV \
--to=viro@zeniv.linux.org.uk \
--cc=anna@kernel.org \
--cc=audit@vger.kernel.org \
--cc=brauner@kernel.org \
--cc=dakr@kernel.org \
--cc=eparis@redhat.com \
--cc=gregkh@linuxfoundation.org \
--cc=jack@suse.cz \
--cc=kent.overstreet@linux.dev \
--cc=linkinjeon@kernel.org \
--cc=linux-bcachefs@vger.kernel.org \
--cc=linux-cifs@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@suse.de \
--cc=paul@paul-moore.com \
--cc=rafael@kernel.org \
--cc=senozhatsky@chromium.org \
--cc=sfrench@samba.org \
--cc=tom@talpey.com \
--cc=trondmy@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.