|
@@ -27,7 +27,13 @@
|
|
|
#include <linux/mount.h>
|
|
|
#include "ecryptfs_kernel.h"
|
|
|
|
|
|
-struct kmem_cache *ecryptfs_open_req_cache;
|
|
|
+struct ecryptfs_open_req {
|
|
|
+ struct file **lower_file;
|
|
|
+ struct dentry *lower_dentry;
|
|
|
+ struct vfsmount *lower_mnt;
|
|
|
+ struct completion done;
|
|
|
+ struct list_head kthread_ctl_list;
|
|
|
+};
|
|
|
|
|
|
static struct ecryptfs_kthread_ctl {
|
|
|
#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
|
|
@@ -67,18 +73,13 @@ static int ecryptfs_threadfn(void *ignored)
|
|
|
req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
|
|
|
struct ecryptfs_open_req,
|
|
|
kthread_ctl_list);
|
|
|
- mutex_lock(&req->mux);
|
|
|
list_del(&req->kthread_ctl_list);
|
|
|
- if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) {
|
|
|
- dget(req->lower_dentry);
|
|
|
- mntget(req->lower_mnt);
|
|
|
- (*req->lower_file) = dentry_open(
|
|
|
- req->lower_dentry, req->lower_mnt,
|
|
|
- (O_RDWR | O_LARGEFILE), current_cred());
|
|
|
- req->flags |= ECRYPTFS_REQ_PROCESSED;
|
|
|
- }
|
|
|
- wake_up(&req->wait);
|
|
|
- mutex_unlock(&req->mux);
|
|
|
+ dget(req->lower_dentry);
|
|
|
+ mntget(req->lower_mnt);
|
|
|
+ (*req->lower_file) = dentry_open(
|
|
|
+ req->lower_dentry, req->lower_mnt,
|
|
|
+ (O_RDWR | O_LARGEFILE), current_cred());
|
|
|
+ complete(&req->done);
|
|
|
}
|
|
|
mutex_unlock(&ecryptfs_kthread_ctl.mux);
|
|
|
}
|
|
@@ -111,10 +112,9 @@ void ecryptfs_destroy_kthread(void)
|
|
|
ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
|
|
|
list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list,
|
|
|
kthread_ctl_list) {
|
|
|
- mutex_lock(&req->mux);
|
|
|
- req->flags |= ECRYPTFS_REQ_ZOMBIE;
|
|
|
- wake_up(&req->wait);
|
|
|
- mutex_unlock(&req->mux);
|
|
|
+ list_del(&req->kthread_ctl_list);
|
|
|
+ *req->lower_file = ERR_PTR(-EIO);
|
|
|
+ complete(&req->done);
|
|
|
}
|
|
|
mutex_unlock(&ecryptfs_kthread_ctl.mux);
|
|
|
kthread_stop(ecryptfs_kthread);
|
|
@@ -136,7 +136,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
|
|
|
struct vfsmount *lower_mnt,
|
|
|
const struct cred *cred)
|
|
|
{
|
|
|
- struct ecryptfs_open_req *req;
|
|
|
+ struct ecryptfs_open_req req;
|
|
|
int flags = O_LARGEFILE;
|
|
|
int rc = 0;
|
|
|
|
|
@@ -153,17 +153,10 @@ int ecryptfs_privileged_open(struct file **lower_file,
|
|
|
rc = PTR_ERR((*lower_file));
|
|
|
goto out;
|
|
|
}
|
|
|
- req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
|
|
|
- if (!req) {
|
|
|
- rc = -ENOMEM;
|
|
|
- goto out;
|
|
|
- }
|
|
|
- mutex_init(&req->mux);
|
|
|
- req->lower_file = lower_file;
|
|
|
- req->lower_dentry = lower_dentry;
|
|
|
- req->lower_mnt = lower_mnt;
|
|
|
- init_waitqueue_head(&req->wait);
|
|
|
- req->flags = 0;
|
|
|
+ init_completion(&req.done);
|
|
|
+ req.lower_file = lower_file;
|
|
|
+ req.lower_dentry = lower_dentry;
|
|
|
+ req.lower_mnt = lower_mnt;
|
|
|
mutex_lock(&ecryptfs_kthread_ctl.mux);
|
|
|
if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
|
|
|
rc = -EIO;
|
|
@@ -171,27 +164,14 @@ int ecryptfs_privileged_open(struct file **lower_file,
|
|
|
printk(KERN_ERR "%s: We are in the middle of shutting down; "
|
|
|
"aborting privileged request to open lower file\n",
|
|
|
__func__);
|
|
|
- goto out_free;
|
|
|
+ goto out;
|
|
|
}
|
|
|
- list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
|
|
|
+ list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
|
|
|
mutex_unlock(&ecryptfs_kthread_ctl.mux);
|
|
|
wake_up(&ecryptfs_kthread_ctl.wait);
|
|
|
- wait_event(req->wait, (req->flags != 0));
|
|
|
- mutex_lock(&req->mux);
|
|
|
- BUG_ON(req->flags == 0);
|
|
|
- if (req->flags & ECRYPTFS_REQ_DROPPED
|
|
|
- || req->flags & ECRYPTFS_REQ_ZOMBIE) {
|
|
|
- rc = -EIO;
|
|
|
- printk(KERN_WARNING "%s: Privileged open request dropped\n",
|
|
|
- __func__);
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
- if (IS_ERR(*req->lower_file))
|
|
|
- rc = PTR_ERR(*req->lower_file);
|
|
|
-out_unlock:
|
|
|
- mutex_unlock(&req->mux);
|
|
|
-out_free:
|
|
|
- kmem_cache_free(ecryptfs_open_req_cache, req);
|
|
|
+ wait_for_completion(&req.done);
|
|
|
+ if (IS_ERR(*lower_file))
|
|
|
+ rc = PTR_ERR(*lower_file);
|
|
|
out:
|
|
|
return rc;
|
|
|
}
|