From: Paulo Alcantara pc@manguebit.com
mainline inclusion from mainline-v6.7-rc1 commit e6322fd177c6885a21dd4609dc5e5c973d1a2eb7 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9R4KS CVE: CVE-2023-52757
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
All release_mid() callers seem to hold a reference of @mid so there is no need to call kref_put(&mid->refcount, __release_mid) under @server->mid_lock spinlock. If they don't, then an use-after-free bug would have occurred anyways.
By getting rid of such spinlock also fixes a potential deadlock as shown below
CPU 0 CPU 1 ------------------------------------------------------------------ cifs_demultiplex_thread() cifs_debug_data_proc_show() release_mid() spin_lock(&server->mid_lock); spin_lock(&cifs_tcp_ses_lock) spin_lock(&server->mid_lock) __release_mid() smb2_find_smb_tcon() spin_lock(&cifs_tcp_ses_lock) *deadlock*
Cc: stable@vger.kernel.org Signed-off-by: Paulo Alcantara (SUSE) pc@manguebit.com Signed-off-by: Steve French stfrench@microsoft.com Conflicts: fs/smb/client/cifsproto.h fs/smb/client/smb2misc.c fs/smb/client/transport.c fs/cifs/cifsproto.h fs/cifs/smb2misc.c fs/cifs/transport.c [Path is changed and related functions has been refactored for a long time] Signed-off-by: Wang Zhaolong wangzhaolong1@huawei.com --- fs/cifs/cifsproto.h | 7 ++++++- fs/cifs/smb2misc.c | 2 +- fs/cifs/transport.c | 9 +-------- 3 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index a6ca4eda9a5a..5ff518be107e 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -85,7 +85,7 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server); extern void DeleteMidQEntry(struct mid_q_entry *midEntry); extern void cifs_delete_mid(struct mid_q_entry *mid); -extern void cifs_mid_q_entry_release(struct mid_q_entry *midEntry); +void _cifs_mid_q_entry_release(struct kref *refcount); extern void cifs_wake_up_task(struct mid_q_entry *mid); extern int cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid); @@ -646,4 +646,9 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) return options; }
+static inline void cifs_mid_q_entry_release(struct mid_q_entry *midEntry) +{ + kref_put(&midEntry->refcount, _cifs_mid_q_entry_release); +} + #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 49686086a333..4652b681f5aa 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -786,7 +786,7 @@ __smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid, { struct close_cancelled_open *cancelled;
- cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC); + cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL); if (!cancelled) return -ENOMEM;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index d209f989bb70..231a86327316 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -88,7 +88,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) return temp; }
-static void _cifs_mid_q_entry_release(struct kref *refcount) +void _cifs_mid_q_entry_release(struct kref *refcount) { struct mid_q_entry *midEntry = container_of(refcount, struct mid_q_entry, refcount); @@ -168,13 +168,6 @@ static void _cifs_mid_q_entry_release(struct kref *refcount) mempool_free(midEntry, cifs_mid_poolp); }
-void cifs_mid_q_entry_release(struct mid_q_entry *midEntry) -{ - spin_lock(&GlobalMid_Lock); - kref_put(&midEntry->refcount, _cifs_mid_q_entry_release); - spin_unlock(&GlobalMid_Lock); -} - void DeleteMidQEntry(struct mid_q_entry *midEntry) { cifs_mid_q_entry_release(midEntry);