[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <DM5PR21MB0185257853E50A73C593B891B6660@DM5PR21MB0185.namprd21.prod.outlook.com>
Date: Mon, 28 Oct 2019 22:19:02 +0000
From: Pavel Shilovskiy <pshilov@...rosoft.com>
To: Ben Hutchings <ben@...adent.org.uk>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"stable@...r.kernel.org" <stable@...r.kernel.org>
CC: "akpm@...ux-foundation.org" <akpm@...ux-foundation.org>,
Denis Kirjanov <kda@...ux-powerpc.org>,
Ronnie Sahlberg <lsahlber@...hat.com>,
Steven French <Steven.French@...rosoft.com>
Subject: RE: [PATCH 3.16 58/87] cifs: add spinlock for the openFileList to
cifsInodeInfo
> -----Original Message-----
> From: Ben Hutchings <ben@...adent.org.uk>
> Sent: Wednesday, October 2, 2019 12:07 PM
> To: linux-kernel@...r.kernel.org; stable@...r.kernel.org
> Cc: akpm@...ux-foundation.org; Denis Kirjanov <kda@...ux-powerpc.org>; Ronnie Sahlberg <lsahlber@...hat.com>; Steven French <Steven.French@...rosoft.com>; Pavel Shilovskiy <pshilov@...rosoft.com>
> 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@...hat.com>
>
> 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@...hat.com>
> Signed-off-by: Steve French <stfrench@...rosoft.com>
> Reviewed-by: Pavel Shilovsky <pshilov@...rosoft.com>
> [bwh: Backported to 3.16: adjust context, indentation]
> Signed-off-by: Ben Hutchings <ben@...adent.org.uk>
> ---
> 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
Powered by blists - more mailing lists