62 lines
2.0 KiB
Diff
62 lines
2.0 KiB
Diff
|
From 5bccda0ebc7c0331b81ac47d39e4b920b198b2cd Mon Sep 17 00:00:00 2001
|
||
|
From: Jeff Layton <jlayton@redhat.com>
|
||
|
Date: Thu, 23 Feb 2012 09:37:45 -0500
|
||
|
Subject: [PATCH] cifs: fix dentry refcount leak when opening a FIFO on lookup
|
||
|
|
||
|
The cifs code will attempt to open files on lookup under certain
|
||
|
circumstances. What happens though if we find that the file we opened
|
||
|
was actually a FIFO or other special file?
|
||
|
|
||
|
Currently, the open filehandle just ends up being leaked leading to
|
||
|
a dentry refcount mismatch and oops on umount. Fix this by having the
|
||
|
code close the filehandle on the server if it turns out not to be a
|
||
|
regular file. While we're at it, change this spaghetti if statement
|
||
|
into a switch too.
|
||
|
|
||
|
Cc: stable@vger.kernel.org
|
||
|
Reported-by: CAI Qian <caiqian@redhat.com>
|
||
|
Tested-by: CAI Qian <caiqian@redhat.com>
|
||
|
Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
|
||
|
Signed-off-by: Jeff Layton <jlayton@redhat.com>
|
||
|
Signed-off-by: Steve French <smfrench@gmail.com>
|
||
|
---
|
||
|
fs/cifs/dir.c | 20 ++++++++++++++++++--
|
||
|
1 files changed, 18 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
|
||
|
index 63a196b..bc7e244 100644
|
||
|
--- a/fs/cifs/dir.c
|
||
|
+++ b/fs/cifs/dir.c
|
||
|
@@ -584,10 +584,26 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||
|
* If either that or op not supported returned, follow
|
||
|
* the normal lookup.
|
||
|
*/
|
||
|
- if ((rc == 0) || (rc == -ENOENT))
|
||
|
+ switch (rc) {
|
||
|
+ case 0:
|
||
|
+ /*
|
||
|
+ * The server may allow us to open things like
|
||
|
+ * FIFOs, but the client isn't set up to deal
|
||
|
+ * with that. If it's not a regular file, just
|
||
|
+ * close it and proceed as if it were a normal
|
||
|
+ * lookup.
|
||
|
+ */
|
||
|
+ if (newInode && !S_ISREG(newInode->i_mode)) {
|
||
|
+ CIFSSMBClose(xid, pTcon, fileHandle);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case -ENOENT:
|
||
|
posix_open = true;
|
||
|
- else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
|
||
|
+ case -EOPNOTSUPP:
|
||
|
+ break;
|
||
|
+ default:
|
||
|
pTcon->broken_posix_open = true;
|
||
|
+ }
|
||
|
}
|
||
|
if (!posix_open)
|
||
|
rc = cifs_get_inode_info_unix(&newInode, full_path,
|
||
|
--
|
||
|
1.7.0.4
|
||
|
|