eCryptFS: mutex lock-unlock ordering fix
PATCH 1/1 eCryptFS: mutex lock-unlock ordering fix
We should lock/unlock mutexes by a proper way which means there should not be chains like ABAB but ABBA otherwise the race window is opened.
Signed-off-by Cyrill Gorcunov <[email protected]>
CC Michael A. Halcrow <[email protected]>
---
Michael, could you test it please? To be honest I see that my patch makes source looks ugly unfirtunelly... thoughts? Any comments are welcome. Maybe I missed something - but I think the chain LOCK: hash_mux -> mux, UNLOCK: hash_mux -> mux is a bit weird ;) so please check if I'm wrong.
fs/ecryptfs/miscdev.c +9 -6
@@ -50,7 +50,6 @@ ecryptfs_miscdev_poll(struct file *file, current->nsproxy->user_ns);BUG_ON (rc || !daemon);mutex_lock (&daemon->mux); -mutex_unlock (&ecryptfs_daemon_hash_mux);if (daemon->flags &ECRYPTFS_DAEMON_ZOMBIE ) {printk (KERN_WARNING "%s: Attempt to poll on zombified " "daemon\n" , __func__);
@@ -62,6 +61,7 @@ ecryptfs_miscdev_poll(struct file *file, goto out_unlock_daemon; daemon->flags |=ECRYPTFS_DAEMON_IN_POLL ;mutex_unlock (&daemon->mux); +mutex_unlock (&ecryptfs_daemon_hash_mux);poll_wait (file, &daemon->wait, pt);mutex_lock (&daemon->mux);if (!list_empty (&daemon->msg_ctx_out_queue))
@@ -69,6 +69,8 @@ ecryptfs_miscdev_poll(struct file *file, out_unlock_daemon: daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL ;mutex_unlock (&daemon->mux); +if (mutex_is_locked (&ecryptfs_daemon_hash_mux)) +mutex_unlock (&ecryptfs_daemon_hash_mux);return mask; }
@@ -257,24 +259,23 @@ ecryptfs_miscdev_read(struct file *file,mutex_lock (&daemon->mux);if (daemon->flags &ECRYPTFS_DAEMON_ZOMBIE ) { rc =0 ; -mutex_unlock (&ecryptfs_daemon_hash_mux);printk (KERN_WARNING "%s: Attempt to read from zombified " "daemon\n" , __func__); goto out_unlock_daemon; }if (daemon->flags &ECRYPTFS_DAEMON_IN_READ ) { rc =0 ; -mutex_unlock (&ecryptfs_daemon_hash_mux); goto out_unlock_daemon; }/* This daemon will not go away so long as this flag is set */ daemon->flags |=ECRYPTFS_DAEMON_IN_READ ; -mutex_unlock (&ecryptfs_daemon_hash_mux); check_list:if (list_empty (&daemon->msg_ctx_out_queue)) { +if (mutex_is_locked (&ecryptfs_daemon_hash_mux)) +mutex_unlock (&ecryptfs_daemon_hash_mux);mutex_unlock (&daemon->mux); - rc =wait_event_interruptible ( - daemon->wait, !list_empty (&daemon->msg_ctx_out_queue)); + rc =wait_event_interruptible (daemon->wait, + !list_empty (&daemon->msg_ctx_out_queue));mutex_lock (&daemon->mux);if (rc <0 ) { rc =0 ;
@@ -357,6 +358,8 @@ out_unlock_msg_ctx: out_unlock_daemon: daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ ;mutex_unlock (&daemon->mux); +if (mutex_is_locked (&ecryptfs_daemon_hash_mux)) +mutex_unlock (&ecryptfs_daemon_hash_mux);return rc; }
[Cyrill Gorcunov - Tue, May 20, 2008 at 08:39:28PM +0400]
| We should lock/unlock mutexes by a proper way which means | there should not be chains like ABAB but ABBA otherwise the | race window is opened. | | Signed-off-by: Cyrill Gorcunov <[email protected]> | CC: Michael A. Halcrow <[email protected]> | --- | | check_list: [...] | if (list_empty(&daemon->msg_ctx_out_queue)) { NIT ---> | + if (mutex_is_locked(&ecryptfs_daemon_hash_mux)) | + mutex_unlock(&ecryptfs_daemon_hash_mux); | mutex_unlock(&daemon->mux); | - rc = wait_event_interruptible( | - daemon->wait, !list_empty(&daemon->msg_ctx_out_queue)); | + rc = wait_event_interruptible(daemon->wait, | + !list_empty(&daemon->msg_ctx_out_queue)); | mutex_lock(&daemon->mux); | if (rc < 0) { | rc = 0; | @@ -357,6 +358,8 @@ out_unlock_msg_ctx: | out_unlock_daemon: | daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ; | mutex_unlock(&daemon->mux); | + if (mutex_is_locked(&ecryptfs_daemon_hash_mux)) | + mutex_unlock(&ecryptfs_daemon_hash_mux); | return rc; | } |
It's a bit wrong (could release mutex being ack'ed by another thread) will fix - please DROP this patch. Sorry!
- Cyrill -