summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2020-03-12 18:25:20 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-03-20 09:07:44 +0100
commitca9a513b01100a557f99fe69abcd3d664ff88b40 (patch)
tree0b17142385871ba4b67c3d7ef91da2e4b30d85c5
parent346ff2f614e5b9f00b648b9dad72d88aa9c46dc8 (diff)
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 <viro@zeniv.linux.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/filesystems/porting7
-rw-r--r--fs/cifs/dir.c1
-rw-r--r--fs/open.c3
3 files changed, 7 insertions, 4 deletions
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index bdd025ceb763..85ed3450099a 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -596,3 +596,10 @@ in your dentry operations instead.
[mandatory]
->rename() has an added flags argument. Any flags not handled by the
filesystem should result in EINVAL being returned.
+--
+[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 d6475dcce9df..0262c8f7e7c7 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -551,7 +551,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 8db6e3a5fc10..e17cc79bd88a 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -824,9 +824,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,