mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
smb: client: clean up failed cached directory opens
open_cached_dir() sends CREATE and QUERY_INFO as a compound request. If
the CREATE succeeds but a later command returns an error, the function
must retain the CREATE FID so common cleanup can issue SMB2_close(). It
also must not treat a response error as a valid CREATE.
Validate the CREATE response before using its fields, record the FIDs, and
mark the handle open before handling errors from later compound commands.
Move the -EREMCHG reconnect handling before response validation so a
missing response does not hide the reconnect request. Count the handle
when it is marked open; confirmed close responses decrement the counter,
while existing close retry behavior remains best effort on transport
failures.
Fixes: b0f6df737a ("cifs: cache FILE_ALL_INFO for the shared root handle")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: LLM
Co-developed-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Zihan Xi <zihanx@nebusec.ai>
Tested-by: Frank Sorenson <sorenson@redhat.com>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
This commit is contained in:
parent
566820af01
commit
d2ff5fb93e
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/namei.h>
|
||||
#include "cifsglob.h"
|
||||
#include "cifsproto.h"
|
||||
#include "../common/smb2status.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "smb2proto.h"
|
||||
#include "cached_dir.h"
|
||||
|
|
@ -323,25 +324,37 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|||
rc = compound_send_recv(xid, ses, server,
|
||||
flags, 2, rqst,
|
||||
resp_buftype, rsp_iov);
|
||||
if (rc) {
|
||||
if (rc == -EREMCHG) {
|
||||
tcon->need_reconnect = true;
|
||||
pr_warn_once("server share %s deleted\n",
|
||||
tcon->tree_name);
|
||||
}
|
||||
if (rc == -EREMCHG) {
|
||||
tcon->need_reconnect = true;
|
||||
pr_warn_once("server share %s deleted\n",
|
||||
tcon->tree_name);
|
||||
}
|
||||
|
||||
if (!rsp_iov[0].iov_base || rsp_iov[0].iov_len < sizeof(*o_rsp)) {
|
||||
if (!rc)
|
||||
rc = -EIO;
|
||||
goto oshr_free;
|
||||
}
|
||||
cfid->is_open = true;
|
||||
|
||||
spin_lock(&cfids->cfid_list_lock);
|
||||
|
||||
o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
|
||||
if (o_rsp->hdr.Status != STATUS_SUCCESS) {
|
||||
if (!rc)
|
||||
rc = -EIO;
|
||||
goto oshr_free;
|
||||
}
|
||||
|
||||
oparms.fid->persistent_fid = o_rsp->PersistentFileId;
|
||||
oparms.fid->volatile_fid = o_rsp->VolatileFileId;
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId);
|
||||
#endif /* CIFS_DEBUG2 */
|
||||
cfid->is_open = true;
|
||||
atomic_inc(&tcon->num_remote_opens);
|
||||
|
||||
if (rc)
|
||||
goto oshr_free;
|
||||
|
||||
spin_lock(&cfids->cfid_list_lock);
|
||||
|
||||
if (o_rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) {
|
||||
spin_unlock(&cfids->cfid_list_lock);
|
||||
|
|
@ -408,7 +421,6 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|||
close_cached_dir(cfid);
|
||||
} else {
|
||||
*ret_cfid = cfid;
|
||||
atomic_inc(&tcon->num_remote_opens);
|
||||
}
|
||||
kfree(utf16_path);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user