> -----Original Message----- > From: Ben Hutchings <ben@xxxxxxxxxxxxxxx> > Sent: Wednesday, October 2, 2019 12:07 PM > To: linux-kernel@xxxxxxxxxxxxxxx; stable@xxxxxxxxxxxxxxx > Cc: akpm@xxxxxxxxxxxxxxxxxxxx; Denis Kirjanov <kda@xxxxxxxxxxxxxxxxx>; Ronnie Sahlberg <lsahlber@xxxxxxxxxx>; Steven French <Steven.French@xxxxxxxxxxxxx>; Pavel Shilovskiy <pshilov@xxxxxxxxxxxxx> > Subject: [PATCH 3.16 58/87] cifs: add spinlock for the openFileList to cifsInodeInfo > > 3.16.75-rc1 review patch. If anyone has any objections, please let me know. > > ------------------ > > From: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> > > commit 487317c99477d00f22370625d53be3239febabbe upstream. > > We can not depend on the tcon->open_file_lock here since in multiuser mode we may have the same file/inode open via multiple different tcons. > > The current code is race prone and will crash if one user deletes a file at the same time a different user opens/create the file. > > To avoid this we need to have a spinlock attached to the inode and not the tcon. > > RHBZ: 1580165 > > Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> > Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> > Reviewed-by: Pavel Shilovsky <pshilov@xxxxxxxxxxxxx> > [bwh: Backported to 3.16: adjust context, indentation] > Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> > --- > fs/cifs/cifsfs.c | 1 + > fs/cifs/cifsglob.h | 5 +++++ > fs/cifs/file.c | 8 ++++++-- > 3 files changed, 12 insertions(+), 2 deletions(-) > > --- a/fs/cifs/cifsfs.c > +++ b/fs/cifs/cifsfs.c > @@ -260,6 +260,7 @@ cifs_alloc_inode(struct super_block *sb) > cifs_inode->uniqueid = 0; > cifs_inode->createtime = 0; > cifs_inode->epoch = 0; > + spin_lock_init(&cifs_inode->open_file_lock); > #ifdef CONFIG_CIFS_SMB2 > generate_random_uuid(cifs_inode->lease_key); > #endif > --- a/fs/cifs/cifsglob.h > +++ b/fs/cifs/cifsglob.h > @@ -1116,6 +1116,7 @@ struct cifsInodeInfo { > struct rw_semaphore lock_sem; /* protect the fields above */ > /* BB add in lists for dirty pages i.e. write caching info for oplock */ > struct list_head openFileList; > + spinlock_t open_file_lock; /* protects openFileList */ > __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ > unsigned int oplock; /* oplock/lease level we have */ > unsigned int epoch; /* used to track lease state changes */ > @@ -1485,10 +1486,14 @@ require use of the stronger protocol */ > * tcp_ses_lock protects: > * list operations on tcp and SMB session lists > * tcon->open_file_lock protects the list of open files hanging off the tcon > + * inode->open_file_lock protects the openFileList hanging off the > + inode > * cfile->file_info_lock protects counters and fields in cifs file struct > * f_owner.lock protects certain per file struct operations > * mapping->page_lock protects certain per page operations > * > + * Note that the cifs_tcon.open_file_lock should be taken before > + * not after the cifsInodeInfo.open_file_lock > + * > * Semaphores > * ---------- > * sesSem operations on smb session > --- a/fs/cifs/file.c > +++ b/fs/cifs/file.c > @@ -337,10 +337,12 @@ cifs_new_fileinfo(struct cifs_fid *fid, > list_add(&cfile->tlist, &tcon->openFileList); > > /* if readable file instance put first in list*/ > + spin_lock(&cinode->open_file_lock); > if (file->f_mode & FMODE_READ) > list_add(&cfile->flist, &cinode->openFileList); > else > list_add_tail(&cfile->flist, &cinode->openFileList); > + spin_unlock(&cinode->open_file_lock); > spin_unlock(&tcon->open_file_lock); > > if (fid->purge_cache) > @@ -412,7 +414,9 @@ void _cifsFileInfo_put(struct cifsFileIn > cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open); > > /* remove it from the lists */ > + spin_lock(&cifsi->open_file_lock); > list_del(&cifs_file->flist); > + spin_unlock(&cifsi->open_file_lock); > list_del(&cifs_file->tlist); > > if (list_empty(&cifsi->openFileList)) { @@ -1850,10 +1854,10 @@ refind_writable: > if (!rc) > return inv_file; > else { > - spin_lock(&tcon->open_file_lock); > + spin_lock(&cifs_inode->open_file_lock); > list_move_tail(&inv_file->flist, > &cifs_inode->openFileList); > - spin_unlock(&tcon->open_file_lock); > + spin_unlock(&cifs_inode->open_file_lock); > cifsFileInfo_put(inv_file); > ++refind; > inv_file = NULL; > Hi Ben, We have recently found regressions in this patch that are addressed in the following two patches: cb248819d209d ("cifs: use cifsInodeInfo->open_file_lock while iterating to avoid a panic") 1a67c41596575 ("CIFS: Fix use after free of file info structures") So, I would suggest either to apply those two patches above or to revert this one. -- Best regards, Pavel Shilovsky