From a8ab0b70979059773f34171c8f05f340f60d47d9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 12 Mar 2020 18:25:20 -0400 Subject: [PATCH] cifs_atomic_open(): fix double-put on late allocation failure commit d9a9f4849fe0c9d560851ab22a85a666cddfdd24 upstream. several iterations of ->atomic_open() calling conventions ago, we used to need fput() if ->atomic_open() failed at some point after successful finish_open(). Now (since 2016) it's not needed - struct file carries enough state to make fput() work regardless of the point in struct file lifecycle and discarding it on failure exits in open() got unified. Unfortunately, I'd missed the fact that we had an instance of ->atomic_open() (cifs one) that used to need that fput(), as well as the stale comment in finish_open() demanding such late failure handling. Trivially fixed... Fixes: fe9ec8291fca "do_last(): take fput() on error after opening to out:" Cc: stable@kernel.org # v4.7+ Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/porting | 7 +++++++ fs/cifs/dir.c | 1 - fs/open.c | 3 --- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 32b5186..041b0de 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -627,3 +627,10 @@ in your dentry operations instead. DCACHE_RCUACCESS is gone; having an RCU delay on dentry freeing is the default. DCACHE_NORCU opts out, and only d_alloc_pseudo() has any business doing so. +-- +[mandatory] + + [should've been added in 2016] stale comment in finish_open() + nonwithstanding, failure exits in ->atomic_open() instances should + *NOT* fput() the file, no matter what. Everything is handled by the + caller. diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 2fb6fa5..f6e3c00 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -561,7 +561,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, if (server->ops->close) server->ops->close(xid, tcon, &fid); cifs_del_pending_open(&open); - fput(file); rc = -ENOMEM; } diff --git a/fs/open.c b/fs/open.c index 8784787..76996f9 100644 --- a/fs/open.c +++ b/fs/open.c @@ -851,9 +851,6 @@ cleanup_file: * the return value of d_splice_alias(), then the caller needs to perform dput() * on it after finish_open(). * - * On successful return @file is a fully instantiated open file. After this, if - * an error occurs in ->atomic_open(), it needs to clean up with fput(). - * * Returns zero on success or -errno if the open failed. */ int finish_open(struct file *file, struct dentry *dentry, -- 2.7.4