* FAILED: patch "[PATCH] smb: client: use finish_no_open() for non-regular inodes" failed to apply to 5.10-stable tree
@ 2026-09-29 11:51 gregkh
2026-09-30 18:41 ` [PATCH 5.10.y] smb: client: use finish_no_open() for non-regular inodes Sasha Levin
0 siblings, 1 reply; 2+ messages in thread
From: gregkh @ 2026-09-29 11:51 UTC (permalink / raw)
To: linkinjeon, pc; +Cc: stable
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x e66cf1625ec4a3fe68346119f371def713fd0a4d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026092924-unmolded-acts-04be@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e66cf1625ec4a3fe68346119f371def713fd0a4d Mon Sep 17 00:00:00 2001
From: Namjae Jeon <linkinjeon@kernel.org>
Date: Wed, 23 Sep 2026 20:25:49 +0900
Subject: [PATCH] smb: client: use finish_no_open() for non-regular inodes
An O_CREAT open can find an existing symlink or another non-regular
inode. cifs_atomic_open() calls finish_open() on it and attaches a
cifsFileInfo. Symlink inodes have no CIFS release operation, so the
dentry reference held by cifsFileInfo is leaked. FMODE_OPENED also
prevents the VFS from following the symlink.
Track whether cifs_do_create() returned an open server handle. For
non-regular inodes, close the handle if present, remove the pending
open, and call finish_no_open() so the VFS can continue the lookup.
Do not set FMODE_CREATED unless a regular file was opened. For
O_NOFOLLOW with __O_REGULAR, return -ELOOP before the VFS's
-EFTYPE check.
Defer closing a legacy POSIX handle on a non-regular inode until
after inode lookup. This avoids closing it again if lookup fails.
Fixes: d2c127197dfc ("cifs: implement i_op->atomic_open()")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Cc: stable@vger.kernel.org
diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
index 6fa6d48fdfd3..1a56fa4d0e89 100644
--- a/fs/smb/client/dir.c
+++ b/fs/smb/client/dir.c
@@ -199,7 +199,7 @@ static int __cifs_do_create(struct inode *dir, struct dentry *direntry,
struct tcon_link *tlink, unsigned int oflags,
umode_t mode, __u32 *oplock, struct cifs_fid *fid,
struct cifs_open_info_data *buf,
- struct inode **inode)
+ struct inode **inode, bool *opened)
{
int rc = -ENOENT;
int create_options = CREATE_NOT_DIR;
@@ -216,6 +216,7 @@ static int __cifs_do_create(struct inode *dir, struct dentry *direntry,
__le32 lease_flags = 0;
*inode = NULL;
+ *opened = false;
*oplock = 0;
if (tcon->ses->server->oplocks)
*oplock = REQ_OPLOCK;
@@ -232,6 +233,7 @@ static int __cifs_do_create(struct inode *dir, struct dentry *direntry,
oflags, oplock, &fid->netfid, xid);
switch (rc) {
case 0:
+ *opened = true;
if (newinode == NULL) {
/* query inode info */
goto cifs_create_get_file_info;
@@ -253,11 +255,9 @@ static int __cifs_do_create(struct inode *dir, struct dentry *direntry,
/*
* The server may allow us to open things like
* FIFOs, but the client isn't set up to deal
- * with that. If it's not a regular file, just
- * close it and proceed as if it were a normal
- * lookup.
+ * with that. Keep the handle until the caller
+ * can finish the lookup.
*/
- CIFSSMBClose(xid, tcon, fid->netfid);
goto cifs_create_get_file_info;
}
/* success, no need to query */
@@ -384,6 +384,7 @@ retry_open:
}
return rc;
}
+ *opened = true;
if (rdwr_for_fscache == 2)
cifs_invalidate_cache(dir, FSCACHE_INVAL_DIO_WRITE);
@@ -475,7 +476,7 @@ cifs_create_set_dentry:
return rc;
out_err:
- if (server->ops->close)
+ if (*opened && server->ops->close)
server->ops->close(xid, tcon, fid);
if (newinode)
iput(newinode);
@@ -487,7 +488,7 @@ static int cifs_do_create(struct inode *dir, struct dentry *direntry,
unsigned int oflags, umode_t mode,
__u32 *oplock, struct cifs_fid *fid,
struct cifs_open_info_data *buf,
- struct inode **inode)
+ struct inode **inode, bool *opened)
{
void *page = alloc_dentry_path();
const char *full_path;
@@ -496,10 +497,11 @@ static int cifs_do_create(struct inode *dir, struct dentry *direntry,
full_path = build_path_from_dentry(direntry, page);
if (IS_ERR(full_path)) {
rc = PTR_ERR(full_path);
+ *opened = false;
} else {
rc = __cifs_do_create(dir, direntry, full_path, xid,
tlink, oflags, mode, oplock,
- fid, buf, inode);
+ fid, buf, inode, opened);
}
free_dentry_path(page);
return rc;
@@ -529,6 +531,8 @@ int cifs_atomic_open(struct inode *dir, struct dentry *direntry,
struct inode *inode;
unsigned int xid;
__u32 oplock;
+ bool is_regular;
+ bool opened;
int rc;
if (unlikely(cifs_forced_shutdown(cifs_sb)))
@@ -581,12 +585,26 @@ int cifs_atomic_open(struct inode *dir, struct dentry *direntry,
cifs_add_pending_open(&fid, tlink, &open);
rc = cifs_do_create(dir, direntry, xid, tlink, oflags, mode,
- &oplock, &fid, &buf, &inode);
+ &oplock, &fid, &buf, &inode, &opened);
if (rc) {
cifs_del_pending_open(&open);
goto out;
}
+ is_regular = S_ISREG(inode->i_mode);
+ if (!is_regular || !opened) {
+ if (opened && server->ops->close)
+ server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
+ if (S_ISLNK(inode->i_mode) &&
+ (oflags & (O_NOFOLLOW | __O_REGULAR)) ==
+ (O_NOFOLLOW | __O_REGULAR) && !(oflags & O_EXCL)) {
+ iput(inode);
+ rc = -ELOOP;
+ goto out;
+ }
+ }
+
if (d_in_lookup(direntry)) {
alias = d_splice_alias(inode, direntry);
if (!IS_ERR_OR_NULL(alias))
@@ -595,9 +613,15 @@ int cifs_atomic_open(struct inode *dir, struct dentry *direntry,
d_instantiate(direntry, inode);
}
- if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ if (is_regular && opened &&
+ (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
file->f_mode |= FMODE_CREATED;
+ if (!is_regular || !opened) {
+ rc = finish_no_open(file, NULL);
+ goto out;
+ }
+
rc = finish_open(file, direntry, generic_file_open);
if (rc) {
if (server->ops->close)
@@ -660,6 +684,7 @@ int cifs_create(struct mnt_idmap *idmap, struct inode *dir,
struct inode *inode;
struct cifs_fid fid;
__u32 oplock;
+ bool opened;
struct cifs_open_info_data buf = {};
cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
@@ -682,10 +707,10 @@ int cifs_create(struct mnt_idmap *idmap, struct inode *dir,
server->ops->new_lease_key(&fid);
rc = cifs_do_create(dir, direntry, xid, tlink, oflags,
- mode, &oplock, &fid, &buf, &inode);
+ mode, &oplock, &fid, &buf, &inode, &opened);
if (!rc) {
d_instantiate(direntry, inode);
- if (server->ops->close)
+ if (opened && server->ops->close)
server->ops->close(xid, tcon, &fid);
}
@@ -1078,6 +1103,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
struct inode *inode;
unsigned int xid;
__u32 oplock;
+ bool opened;
int namelen;
int rc;
@@ -1116,7 +1142,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
namelen = scnprintf(name, namesize, CIFS_TMPNAME_PREFIX "%x",
atomic_inc_return(&cifs_tmpcounter));
rc = __cifs_do_create(dir, dentry, path, xid, tlink, oflags,
- mode, &oplock, &fid, NULL, &inode);
+ mode, &oplock, &fid, NULL, &inode, &opened);
if (!rc) {
rc = d_mark_tmpfile_name(file, &QSTR_LEN(name, namelen));
if (rc) {
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH 5.10.y] smb: client: use finish_no_open() for non-regular inodes
2026-09-29 11:51 FAILED: patch "[PATCH] smb: client: use finish_no_open() for non-regular inodes" failed to apply to 5.10-stable tree gregkh
@ 2026-09-30 18:41 ` Sasha Levin
0 siblings, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2026-09-30 18:41 UTC (permalink / raw)
To: stable; +Cc: Namjae Jeon, Paulo Alcantara, Sasha Levin
From: Namjae Jeon <linkinjeon@kernel.org>
[ Upstream commit e66cf1625ec4a3fe68346119f371def713fd0a4d ]
An O_CREAT open can find an existing symlink or another non-regular
inode. cifs_atomic_open() calls finish_open() on it and attaches a
cifsFileInfo. Symlink inodes have no CIFS release operation, so the
dentry reference held by cifsFileInfo is leaked. FMODE_OPENED also
prevents the VFS from following the symlink.
Track whether cifs_do_create() returned an open server handle. For
non-regular inodes, close the handle if present, remove the pending
open, and call finish_no_open() so the VFS can continue the lookup.
Do not set FMODE_CREATED unless a regular file was opened. For
O_NOFOLLOW with __O_REGULAR, return -ELOOP before the VFS's
-EFTYPE check.
Defer closing a legacy POSIX handle on a non-regular inode until
after inode lookup. This avoids closing it again if lookup fails.
Fixes: d2c127197dfc ("cifs: implement i_op->atomic_open()")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Cc: stable@vger.kernel.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/cifs/dir.c | 37 +++++++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 73d43d8911aa5..0366ac28ff07c 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -225,7 +225,7 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon)
static int
cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
struct tcon_link *tlink, unsigned oflags, umode_t mode,
- __u32 *oplock, struct cifs_fid *fid)
+ __u32 *oplock, struct cifs_fid *fid, bool *opened)
{
int rc = -ENOENT;
int create_options = CREATE_NOT_DIR;
@@ -239,6 +239,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
struct TCP_Server_Info *server = tcon->ses->server;
struct cifs_open_parms oparms;
+ *opened = false;
*oplock = 0;
if (tcon->ses->server->oplocks)
*oplock = REQ_OPLOCK;
@@ -254,6 +255,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
oflags, oplock, &fid->netfid, xid);
switch (rc) {
case 0:
+ *opened = true;
if (newinode == NULL) {
/* query inode info */
goto cifs_create_get_file_info;
@@ -270,11 +272,9 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
/*
* The server may allow us to open things like
* FIFOs, but the client isn't set up to deal
- * with that. If it's not a regular file, just
- * close it and proceed as if it were a normal
- * lookup.
+ * with that. Keep the handle until the caller
+ * can finish the lookup.
*/
- CIFSSMBClose(xid, tcon, fid->netfid);
goto cifs_create_get_file_info;
}
/* success, no need to query */
@@ -370,6 +370,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
goto out;
}
+ *opened = true;
/*
* If Open reported that we actually created a file then we now have to
@@ -452,7 +453,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
return rc;
out_err:
- if (server->ops->close)
+ if (*opened && server->ops->close)
server->ops->close(xid, tcon, fid);
if (newinode)
iput(newinode);
@@ -472,6 +473,8 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
struct cifs_pending_open open;
__u32 oplock;
struct cifsFileInfo *file_info;
+ bool is_regular;
+ bool opened;
/*
* Posix open is only called (at lookup time) for file create now. For
@@ -526,16 +529,29 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
cifs_add_pending_open(&fid, tlink, &open);
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
- &oplock, &fid);
+ &oplock, &fid, &opened);
if (rc) {
cifs_del_pending_open(&open);
goto out;
}
- if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ is_regular = d_is_reg(direntry);
+ if (!is_regular || !opened) {
+ if (opened && server->ops->close)
+ server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
+ }
+
+ if (is_regular && opened &&
+ (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
file->f_mode |= FMODE_CREATED;
+ if (!is_regular || !opened) {
+ rc = finish_no_open(file, NULL);
+ goto out;
+ }
+
rc = finish_open(file, direntry, generic_file_open);
if (rc) {
if (server->ops->close)
@@ -585,6 +601,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
struct TCP_Server_Info *server;
struct cifs_fid fid;
__u32 oplock;
+ bool opened;
cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
inode, direntry, direntry);
@@ -601,8 +618,8 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
server->ops->new_lease_key(&fid);
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
- &oplock, &fid);
- if (!rc && server->ops->close)
+ &oplock, &fid, &opened);
+ if (!rc && opened && server->ops->close)
server->ops->close(xid, tcon, &fid);
cifs_put_tlink(tlink);
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-30 18:41 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-29 11:51 FAILED: patch "[PATCH] smb: client: use finish_no_open() for non-regular inodes" failed to apply to 5.10-stable tree gregkh
2026-09-30 18:41 ` [PATCH 5.10.y] smb: client: use finish_no_open() for non-regular inodes Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).