From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: NeilBrown <neilb@suse.de>, David Disseldorp <ddiss@suse.de>,
Jeff Layton <jlayton@kernel.org>,
Al Viro <viro@zeniv.linux.org.uk>,
Linus Torvalds <torvalds@linux-foundation.org>,
Sasha Levin <sashal@kernel.org>,
linux-fsdevel@vger.kernel.org
Subject: [PATCH AUTOSEL 5.17 29/34] VFS: filename_create(): fix incorrect intent.
Date: Tue, 19 Apr 2022 14:10:56 -0400 [thread overview]
Message-ID: <20220419181104.484667-29-sashal@kernel.org> (raw)
In-Reply-To: <20220419181104.484667-1-sashal@kernel.org>
From: NeilBrown <neilb@suse.de>
[ Upstream commit b3d4650d82c71b9c9a8184de9e8bb656012b289e ]
When asked to create a path ending '/', but which is not to be a
directory (LOOKUP_DIRECTORY not set), filename_create() will never try
to create the file. If it doesn't exist, -ENOENT is reported.
However, it still passes LOOKUP_CREATE|LOOKUP_EXCL to the filesystems
->lookup() function, even though there is no intent to create. This is
misleading and can cause incorrect behaviour.
If you try
ln -s foo /path/dir/
where 'dir' is a directory on an NFS filesystem which is not currently
known in the dcache, this will fail with ENOENT.
But as the name is not in the dcache, nfs_lookup gets called with
LOOKUP_CREATE|LOOKUP_EXCL and so it returns NULL without performing any
lookup, with the expectation that a subsequent call to create the target
will be made, and the lookup can be combined with the creation. In the
case with a trailing '/' and no LOOKUP_DIRECTORY, that call is never
made. Instead filename_create() sees that the dentry is not (yet)
positive and returns -ENOENT - even though the directory actually
exists.
So only set LOOKUP_CREATE|LOOKUP_EXCL if there really is an intent to
create, and use the absence of these flags to decide if -ENOENT should
be returned.
Note that filename_parentat() is only interested in LOOKUP_REVAL, so we
split that out and store it in 'reval_flag'. __lookup_hash() then gets
reval_flag combined with whatever create flags were determined to be
needed.
Reviewed-by: David Disseldorp <ddiss@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: NeilBrown <neilb@suse.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/namei.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index 3f1829b3ab5b..509657fdf4f5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3673,18 +3673,14 @@ 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;
- bool is_dir = (lookup_flags & LOOKUP_DIRECTORY);
- /*
- * Note that only LOOKUP_REVAL and LOOKUP_DIRECTORY matter here. Any
- * other flags passed in are ignored!
- */
- lookup_flags &= LOOKUP_REVAL;
-
- error = filename_parentat(dfd, name, lookup_flags, path, &last, &type);
+ error = filename_parentat(dfd, name, reval_flag, path, &last, &type);
if (error)
return ERR_PTR(error);
@@ -3698,11 +3694,13 @@ static struct dentry *filename_create(int dfd, struct filename *name,
/* 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.
+ * Do the final lookup. Suppress 'create' if there is a trailing
+ * '/', and a directory wasn't requested.
*/
- lookup_flags |= LOOKUP_CREATE | LOOKUP_EXCL;
+ if (last.name[last.len] && !want_dir)
+ create_flags = 0;
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
- dentry = __lookup_hash(&last, path->dentry, lookup_flags);
+ dentry = __lookup_hash(&last, path->dentry, reval_flag | create_flags);
if (IS_ERR(dentry))
goto unlock;
@@ -3716,7 +3714,7 @@ static struct dentry *filename_create(int dfd, struct filename *name,
* 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(!is_dir && last.name[last.len])) {
+ if (unlikely(!create_flags)) {
error = -ENOENT;
goto fail;
}
--
2.35.1
next prev parent reply other threads:[~2022-04-19 18:14 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-19 18:10 [PATCH AUTOSEL 5.17 01/34] drm/msm/gpu: Rename runtime suspend/resume functions Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 02/34] drm/msm/gpu: Remove mutex from wait_event condition Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 03/34] ARM: vexpress/spc: Avoid negative array index when !SMP Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 04/34] reset: renesas: Check return value of reset_control_deassert() Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 05/34] reset: tegra-bpmp: Restore Handle errors in BPMP response Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 06/34] platform/x86: samsung-laptop: Fix an unsigned comparison which can never be negative Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 07/34] ALSA: usb-audio: Fix undefined behavior due to shift overflowing the constant Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 08/34] drm/msm/disp: check the return value of kzalloc() Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 09/34] selftests: KVM: Free the GIC FD when cleaning up in arch_timer Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 10/34] ALSA: hda: intel-dsp-config: update AlderLake PCI IDs Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 11/34] arm64: dts: imx: Fix imx8*-var-som touchscreen property sizes Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 12/34] vxlan: fix error return code in vxlan_fdb_append Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 13/34] cifs: Check the IOCB_DIRECT flag, not O_DIRECT Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 14/34] net: atlantic: Avoid out-of-bounds indexing Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 15/34] mt76: Fix undefined behavior due to shift overflowing the constant Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 16/34] brcmfmac: sdio: " Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 17/34] dpaa_eth: Fix missing of_node_put in dpaa_get_ts_info() Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 18/34] drm/msm/mdp5: check the return of kzalloc() Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 19/34] drm/msm: Stop using iommu_present() Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 20/34] KVM: x86: hyper-v: Avoid writing to TSC page without an active vCPU Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 21/34] net: macb: Restart tx only if queue pointer is lagging Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 22/34] scsi: iscsi: Move iscsi_ep_disconnect() Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 23/34] scsi: iscsi: Fix offload conn cleanup when iscsid restarts Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 24/34] scsi: iscsi: Release endpoint ID when its freed Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 25/34] scsi: iscsi: Merge suspend fields Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 26/34] scsi: iscsi: Fix NOP handling during conn recovery Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 27/34] scsi: qedi: Fix failed disconnect handling Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 28/34] stat: fix inconsistency between struct stat and struct compat_stat Sasha Levin
2022-04-19 18:10 ` Sasha Levin [this message]
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 30/34] nvme: add a quirk to disable namespace identifiers Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 31/34] nvme-pci: disable namespace identifiers for the MAXIO MAP1002/1202 Sasha Levin
2022-04-19 18:10 ` [PATCH AUTOSEL 5.17 32/34] nvme-pci: disable namespace identifiers for Qemu controllers Sasha Levin
2022-04-19 18:11 ` [PATCH AUTOSEL 5.17 33/34] block/compat_ioctl: fix range check in BLKGETSIZE Sasha Levin
2022-04-19 18:11 ` [PATCH AUTOSEL 5.17 34/34] irq_work: use kasan_record_aux_stack_noalloc() record callstack Sasha Levin
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=20220419181104.484667-29-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=ddiss@suse.de \
--cc=jlayton@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=neilb@suse.de \
--cc=stable@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--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