Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5bccda0e authored by Jeff Layton's avatar Jeff Layton Committed by Steve French
Browse files

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: default avatarCAI Qian <caiqian@redhat.com>
Tested-by: default avatarCAI Qian <caiqian@redhat.com>
Reviewed-by: default avatarShirish Pargaonkar <shirishpargaonkar@gmail.com>
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 6de2ce42
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -584,11 +584,27 @@ 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,
						parent_dir_inode->i_sb, xid);