fix was already in cifs-2.6.git for-next, but added Cc: stable Let me know if I missed anything On Mon, Oct 30, 2023 at 3:20 PM Paulo Alcantara <pc@xxxxxxxxxxxxx> wrote: > > 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 anyway. > > 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: Frank Sorenson <sorenson@xxxxxxxxxx> > Signed-off-by: Paulo Alcantara (SUSE) <pc@xxxxxxxxxxxxx> > --- > fs/smb/client/cifsproto.h | 7 ++++++- > fs/smb/client/smb2misc.c | 2 +- > fs/smb/client/transport.c | 11 +---------- > 3 files changed, 8 insertions(+), 12 deletions(-) > > diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h > index 0c37eefa18a5..890ceddae07e 100644 > --- a/fs/smb/client/cifsproto.h > +++ b/fs/smb/client/cifsproto.h > @@ -81,7 +81,7 @@ extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx, > extern char *build_wildcard_path_from_dentry(struct dentry *direntry); > char *cifs_build_devname(char *nodename, const char *prepath); > extern void delete_mid(struct mid_q_entry *mid); > -extern void release_mid(struct mid_q_entry *mid); > +void __release_mid(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); > @@ -740,4 +740,9 @@ static inline bool dfs_src_pathname_equal(const char *s1, const char *s2) > return true; > } > > +static inline void release_mid(struct mid_q_entry *mid) > +{ > + kref_put(&mid->refcount, __release_mid); > +} > + > #endif /* _CIFSPROTO_H */ > diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c > index 25f7cd6f23d6..32dfa0f7a78c 100644 > --- a/fs/smb/client/smb2misc.c > +++ b/fs/smb/client/smb2misc.c > @@ -787,7 +787,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/smb/client/transport.c b/fs/smb/client/transport.c > index 14710afdc2a3..d553b7a54621 100644 > --- a/fs/smb/client/transport.c > +++ b/fs/smb/client/transport.c > @@ -76,7 +76,7 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) > return temp; > } > > -static void __release_mid(struct kref *refcount) > +void __release_mid(struct kref *refcount) > { > struct mid_q_entry *midEntry = > container_of(refcount, struct mid_q_entry, refcount); > @@ -156,15 +156,6 @@ static void __release_mid(struct kref *refcount) > mempool_free(midEntry, cifs_mid_poolp); > } > > -void release_mid(struct mid_q_entry *mid) > -{ > - struct TCP_Server_Info *server = mid->server; > - > - spin_lock(&server->mid_lock); > - kref_put(&mid->refcount, __release_mid); > - spin_unlock(&server->mid_lock); > -} > - > void > delete_mid(struct mid_q_entry *mid) > { > -- > 2.42.0 > -- Thanks, Steve