Thread (74 messages) 74 messages, 2 authors, 2012-03-12

[ 26/68] cifs: fix dentry refcount leak when opening a FIFO on lookup

From: Greg KH <gregkh@linuxfoundation.org>
Date: 2012-03-09 19:52:29
Also in: lkml

3.0-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jeff Layton <redacted>

commit 5bccda0ebc7c0331b81ac47d39e4b920b198b2cd upstream.

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.

Reported-by: CAI Qian <redacted>
Tested-by: CAI Qian <redacted>
Reviewed-by: Shirish Pargaonkar <redacted>
Signed-off-by: Jeff Layton <redacted>
Signed-off-by: Steve French <smfrench@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 fs/cifs/dir.c |   20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -583,10 +583,26 @@ cifs_lookup(struct inode *parent_dir_ino
 			 * 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,

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help