Re: A process killed while opening a file can result in leaked open handle on the server

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 






----- Original Message -----
> From: "Frank Sorenson" <sorenson@xxxxxxxxxx>
> To: "linux-cifs" <linux-cifs@xxxxxxxxxxxxxxx>
> Sent: Wednesday, 13 November, 2019 5:34:27 AM
> Subject: A process killed while opening a file can result in leaked open handle on the server
> 
> If a process opening a file is killed while waiting for a SMB2_CREATE
> response from the server, the response may not be handled by the client,
> leaking an open file handle on the server.
> 
> This can be reproduced with the following:
> 
> # mount //vm3/user1 /mnt/vm3
> -overs=3,sec=ntlmssp,credentials=/root/.user1_smb_creds
> # cd /mnt/vm3
> # echo foo > foo
> 
> # for i in {1..100} ; do cat foo >/dev/null 2>&1 & sleep 0.0001 ; kill -9 $!
> ; done
> 
> (increase count if necessary--100 appears sufficient to cause multiple leaked
> file handles)
> 
> 
> The client will stop waiting for the response, and will output
> the following when the response does arrive:
> 
>     CIFS VFS: Close unmatched open
> 
> on the server side, an open file handle is leaked.  If using samba,
> the following will show these open files:
> 
> 
> # smbstatus | grep -i Locked -A1000
> Locked files:
> Pid          Uid        DenyMode   Access      R/W        Oplock
> SharePath   Name   Time
> --------------------------------------------------------------------------------------------------
> 25936        501        DENY_NONE  0x80        RDONLY     NONE
> /home/user1   .   Tue Nov 12 12:29:24 2019
> 25936        501        DENY_NONE  0x80        RDONLY     NONE
> /home/user1   .   Tue Nov 12 12:29:24 2019
> 25936        501        DENY_NONE  0x120089    RDONLY     LEASE(RWH)
> /home/user1   foo   Tue Nov 12 12:29:24 2019
> 25936        501        DENY_NONE  0x120089    RDONLY     LEASE(RWH)
> /home/user1   foo   Tue Nov 12 12:29:24 2019
> 25936        501        DENY_NONE  0x120089    RDONLY     LEASE(RWH)
> /home/user1   foo   Tue Nov 12 12:29:24 2019
> 25936        501        DENY_NONE  0x120089    RDONLY     LEASE(RWH)
> /home/user1   foo   Tue Nov 12 12:29:24 2019
> 25936        501        DENY_NONE  0x120089    RDONLY     LEASE(RWH)
> /home/user1   foo   Tue Nov 12 12:29:24 2019
> 
> 
> (also tracked https://bugzilla.redhat.com/show_bug.cgi?id=1771691)
> 

I don't think it has to do with "CIFS VFS: Close unmatched open", in fact those are probably the times
where it did not leak. Unless the SMB2_close() fails with an error.
Can you try the patch below and check that these SMB2_close() are successful?

I think it is more likely that we leak because we can not match the SMB2_Create() response with a MID.
Do you get "No task to wake, unknown frame received" in the log?

We need to do two things here.
1, Find out why we can not match this with a MID and second,
   This it to fix THIS bug.
2, In the demultiplex_thread, where we get a "No task to wake, unknown frame received" we should check
   is this an Open? if so we should invoke server->ops->handle_cancelled_mid()
   This is to make sure other similar bugs do not cause leaks like this.

regards
ronnie sahlberg


> Frank
> --
> Frank Sorenson
> sorenson@xxxxxxxxxx
> Principal Software Maintenance Engineer
> Global Support Services - filesystems
> Red Hat
> 
> 
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index d78bfcc19156..10cb4d4fb122 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1548,6 +1548,7 @@ struct mid_q_entry {
 };
 
 struct close_cancelled_open {
+	__u64 mid;
 	struct cifs_fid         fid;
 	struct cifs_tcon        *tcon;
 	struct work_struct      work;
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index e311f58dc1c8..6120c307d88e 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -735,12 +735,19 @@ smb2_cancelled_close_fid(struct work_struct *work)
 {
 	struct close_cancelled_open *cancelled = container_of(work,
 					struct close_cancelled_open, work);
+	struct cifs_tcon *tcon = cancelled->tcon;
+	int rc;
 
-	cifs_dbg(VFS, "Close unmatched open\n");
+	cifs_tcon_dbg(VFS, "Close unmatched open for MID:%llx\n",
+		      cancelled->mid);
 
-	SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid,
-		   cancelled->fid.volatile_fid);
-	cifs_put_tcon(cancelled->tcon);
+	rc = SMB2_close(0, tcon, cancelled->fid.persistent_fid,
+			cancelled->fid.volatile_fid);
+	if (rc) {
+		cifs_tcon_dbg(VFS, "Close cancelled mid failed with rc:%d\n", rc);
+	}
+
+	cifs_put_tcon(tcon);
 	kfree(cancelled);
 }
 
@@ -770,6 +777,7 @@ smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
 	cancelled->fid.persistent_fid = rsp->PersistentFileId;
 	cancelled->fid.volatile_fid = rsp->VolatileFileId;
 	cancelled->tcon = tcon;
+	cancelled->mid = sync_hdr->MessageId;
 	INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
 	queue_work(cifsiod_wq, &cancelled->work);
 

[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux