1 /** 2 * eCryptfs: Linux filesystem encryption layer 3 * 4 * Copyright (C) 2008 International Business Machines Corp. 5 * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of the 10 * License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 */ 22 23 #include <linux/kthread.h> 24 #include <linux/freezer.h> 25 #include <linux/slab.h> 26 #include <linux/wait.h> 27 #include <linux/mount.h> 28 #include "ecryptfs_kernel.h" 29 30 struct ecryptfs_open_req { 31 struct file **lower_file; 32 struct path path; 33 struct completion done; 34 struct list_head kthread_ctl_list; 35 }; 36 37 static struct ecryptfs_kthread_ctl { 38 #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 39 u32 flags; 40 struct mutex mux; 41 struct list_head req_list; 42 wait_queue_head_t wait; 43 } ecryptfs_kthread_ctl; 44 45 static struct task_struct *ecryptfs_kthread; 46 47 /** 48 * ecryptfs_threadfn 49 * @ignored: ignored 50 * 51 * The eCryptfs kernel thread that has the responsibility of getting 52 * the lower file with RW permissions. 53 * 54 * Returns zero on success; non-zero otherwise 55 */ 56 static int ecryptfs_threadfn(void *ignored) 57 { 58 set_freezable(); 59 while (1) { 60 struct ecryptfs_open_req *req; 61 62 wait_event_freezable( 63 ecryptfs_kthread_ctl.wait, 64 (!list_empty(&ecryptfs_kthread_ctl.req_list) 65 || kthread_should_stop())); 66 mutex_lock(&ecryptfs_kthread_ctl.mux); 67 if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { 68 mutex_unlock(&ecryptfs_kthread_ctl.mux); 69 goto out; 70 } 71 while (!list_empty(&ecryptfs_kthread_ctl.req_list)) { 72 req = list_first_entry(&ecryptfs_kthread_ctl.req_list, 73 struct ecryptfs_open_req, 74 kthread_ctl_list); 75 list_del(&req->kthread_ctl_list); 76 *req->lower_file = dentry_open(&req->path, 77 (O_RDWR | O_LARGEFILE), current_cred()); 78 complete(&req->done); 79 } 80 mutex_unlock(&ecryptfs_kthread_ctl.mux); 81 } 82 out: 83 return 0; 84 } 85 86 int __init ecryptfs_init_kthread(void) 87 { 88 int rc = 0; 89 90 mutex_init(&ecryptfs_kthread_ctl.mux); 91 init_waitqueue_head(&ecryptfs_kthread_ctl.wait); 92 INIT_LIST_HEAD(&ecryptfs_kthread_ctl.req_list); 93 ecryptfs_kthread = kthread_run(&ecryptfs_threadfn, NULL, 94 "ecryptfs-kthread"); 95 if (IS_ERR(ecryptfs_kthread)) { 96 rc = PTR_ERR(ecryptfs_kthread); 97 printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]" 98 "\n", __func__, rc); 99 } 100 return rc; 101 } 102 103 void ecryptfs_destroy_kthread(void) 104 { 105 struct ecryptfs_open_req *req; 106 107 mutex_lock(&ecryptfs_kthread_ctl.mux); 108 ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE; 109 list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list, 110 kthread_ctl_list) { 111 list_del(&req->kthread_ctl_list); 112 *req->lower_file = ERR_PTR(-EIO); 113 complete(&req->done); 114 } 115 mutex_unlock(&ecryptfs_kthread_ctl.mux); 116 kthread_stop(ecryptfs_kthread); 117 wake_up(&ecryptfs_kthread_ctl.wait); 118 } 119 120 /** 121 * ecryptfs_privileged_open 122 * @lower_file: Result of dentry_open by root on lower dentry 123 * @lower_dentry: Lower dentry for file to open 124 * @lower_mnt: Lower vfsmount for file to open 125 * 126 * This function gets a r/w file opened againt the lower dentry. 127 * 128 * Returns zero on success; non-zero otherwise 129 */ 130 int ecryptfs_privileged_open(struct file **lower_file, 131 struct dentry *lower_dentry, 132 struct vfsmount *lower_mnt, 133 const struct cred *cred) 134 { 135 struct ecryptfs_open_req req; 136 int flags = O_LARGEFILE; 137 int rc = 0; 138 139 init_completion(&req.done); 140 req.lower_file = lower_file; 141 req.path.dentry = lower_dentry; 142 req.path.mnt = lower_mnt; 143 144 /* Corresponding dput() and mntput() are done when the 145 * lower file is fput() when all eCryptfs files for the inode are 146 * released. */ 147 flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; 148 (*lower_file) = dentry_open(&req.path, flags, cred); 149 if (!IS_ERR(*lower_file)) 150 goto out; 151 if ((flags & O_ACCMODE) == O_RDONLY) { 152 rc = PTR_ERR((*lower_file)); 153 goto out; 154 } 155 mutex_lock(&ecryptfs_kthread_ctl.mux); 156 if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { 157 rc = -EIO; 158 mutex_unlock(&ecryptfs_kthread_ctl.mux); 159 printk(KERN_ERR "%s: We are in the middle of shutting down; " 160 "aborting privileged request to open lower file\n", 161 __func__); 162 goto out; 163 } 164 list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); 165 mutex_unlock(&ecryptfs_kthread_ctl.mux); 166 wake_up(&ecryptfs_kthread_ctl.wait); 167 wait_for_completion(&req.done); 168 if (IS_ERR(*lower_file)) 169 rc = PTR_ERR(*lower_file); 170 out: 171 return rc; 172 } 173