aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ecryptfs/main.c')
-rw-r--r--fs/ecryptfs/main.c82
1 files changed, 55 insertions, 27 deletions
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 758323a0f09a..89b93389af8e 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...)
96} 96}
97 97
98/** 98/**
99 * ecryptfs_init_persistent_file 99 * ecryptfs_init_lower_file
100 * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with 100 * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with
101 * the lower dentry and the lower mount set 101 * the lower dentry and the lower mount set
102 * 102 *
@@ -104,44 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...)
104 * inode. All I/O operations to the lower inode occur through that 104 * inode. All I/O operations to the lower inode occur through that
105 * file. When the first eCryptfs dentry that interposes with the first 105 * file. When the first eCryptfs dentry that interposes with the first
106 * lower dentry for that inode is created, this function creates the 106 * lower dentry for that inode is created, this function creates the
107 * persistent file struct and associates it with the eCryptfs 107 * lower file struct and associates it with the eCryptfs
108 * inode. When the eCryptfs inode is destroyed, the file is closed. 108 * inode. When all eCryptfs files associated with the inode are released, the
109 * file is closed.
109 * 110 *
110 * The persistent file will be opened with read/write permissions, if 111 * The lower file will be opened with read/write permissions, if
111 * possible. Otherwise, it is opened read-only. 112 * possible. Otherwise, it is opened read-only.
112 * 113 *
113 * This function does nothing if a lower persistent file is already 114 * This function does nothing if a lower file is already
114 * associated with the eCryptfs inode. 115 * associated with the eCryptfs inode.
115 * 116 *
116 * Returns zero on success; non-zero otherwise 117 * Returns zero on success; non-zero otherwise
117 */ 118 */
118int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) 119static int ecryptfs_init_lower_file(struct dentry *dentry,
120 struct file **lower_file)
119{ 121{
120 const struct cred *cred = current_cred(); 122 const struct cred *cred = current_cred();
123 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
124 struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
125 int rc;
126
127 rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt,
128 cred);
129 if (rc) {
130 printk(KERN_ERR "Error opening lower file "
131 "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
132 "rc = [%d]\n", lower_dentry, lower_mnt, rc);
133 (*lower_file) = NULL;
134 }
135 return rc;
136}
137
138int ecryptfs_get_lower_file(struct dentry *dentry)
139{
121 struct ecryptfs_inode_info *inode_info = 140 struct ecryptfs_inode_info *inode_info =
122 ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); 141 ecryptfs_inode_to_private(dentry->d_inode);
123 int rc = 0; 142 int count, rc = 0;
124 143
125 mutex_lock(&inode_info->lower_file_mutex); 144 mutex_lock(&inode_info->lower_file_mutex);
126 if (!inode_info->lower_file) { 145 count = atomic_inc_return(&inode_info->lower_file_count);
127 struct dentry *lower_dentry; 146 if (WARN_ON_ONCE(count < 1))
128 struct vfsmount *lower_mnt = 147 rc = -EINVAL;
129 ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); 148 else if (count == 1) {
130 149 rc = ecryptfs_init_lower_file(dentry,
131 lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 150 &inode_info->lower_file);
132 rc = ecryptfs_privileged_open(&inode_info->lower_file, 151 if (rc)
133 lower_dentry, lower_mnt, cred); 152 atomic_set(&inode_info->lower_file_count, 0);
134 if (rc) {
135 printk(KERN_ERR "Error opening lower persistent file "
136 "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
137 "rc = [%d]\n", lower_dentry, lower_mnt, rc);
138 inode_info->lower_file = NULL;
139 }
140 } 153 }
141 mutex_unlock(&inode_info->lower_file_mutex); 154 mutex_unlock(&inode_info->lower_file_mutex);
142 return rc; 155 return rc;
143} 156}
144 157
158void ecryptfs_put_lower_file(struct inode *inode)
159{
160 struct ecryptfs_inode_info *inode_info;
161
162 inode_info = ecryptfs_inode_to_private(inode);
163 if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
164 &inode_info->lower_file_mutex)) {
165 fput(inode_info->lower_file);
166 inode_info->lower_file = NULL;
167 mutex_unlock(&inode_info->lower_file_mutex);
168 }
169}
170
145static struct inode *ecryptfs_get_inode(struct inode *lower_inode, 171static struct inode *ecryptfs_get_inode(struct inode *lower_inode,
146 struct super_block *sb) 172 struct super_block *sb)
147{ 173{
@@ -241,14 +267,14 @@ static int ecryptfs_init_global_auth_toks(
241 struct ecryptfs_mount_crypt_stat *mount_crypt_stat) 267 struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
242{ 268{
243 struct ecryptfs_global_auth_tok *global_auth_tok; 269 struct ecryptfs_global_auth_tok *global_auth_tok;
270 struct ecryptfs_auth_tok *auth_tok;
244 int rc = 0; 271 int rc = 0;
245 272
246 list_for_each_entry(global_auth_tok, 273 list_for_each_entry(global_auth_tok,
247 &mount_crypt_stat->global_auth_tok_list, 274 &mount_crypt_stat->global_auth_tok_list,
248 mount_crypt_stat_list) { 275 mount_crypt_stat_list) {
249 rc = ecryptfs_keyring_auth_tok_for_sig( 276 rc = ecryptfs_keyring_auth_tok_for_sig(
250 &global_auth_tok->global_auth_tok_key, 277 &global_auth_tok->global_auth_tok_key, &auth_tok,
251 &global_auth_tok->global_auth_tok,
252 global_auth_tok->sig); 278 global_auth_tok->sig);
253 if (rc) { 279 if (rc) {
254 printk(KERN_ERR "Could not find valid key in user " 280 printk(KERN_ERR "Could not find valid key in user "
@@ -256,8 +282,10 @@ static int ecryptfs_init_global_auth_toks(
256 "option: [%s]\n", global_auth_tok->sig); 282 "option: [%s]\n", global_auth_tok->sig);
257 global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID; 283 global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;
258 goto out; 284 goto out;
259 } else 285 } else {
260 global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID; 286 global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID;
287 up_write(&(global_auth_tok->global_auth_tok_key)->sem);
288 }
261 } 289 }
262out: 290out:
263 return rc; 291 return rc;
@@ -276,7 +304,7 @@ static void ecryptfs_init_mount_crypt_stat(
276/** 304/**
277 * ecryptfs_parse_options 305 * ecryptfs_parse_options
278 * @sb: The ecryptfs super block 306 * @sb: The ecryptfs super block
279 * @options: The options pased to the kernel 307 * @options: The options passed to the kernel
280 * 308 *
281 * Parse mount options: 309 * Parse mount options:
282 * debug=N - ecryptfs_verbosity level for debug output 310 * debug=N - ecryptfs_verbosity level for debug output
@@ -840,7 +868,7 @@ static int __init ecryptfs_init(void)
840 } 868 }
841 rc = ecryptfs_init_messaging(); 869 rc = ecryptfs_init_messaging();
842 if (rc) { 870 if (rc) {
843 printk(KERN_ERR "Failure occured while attempting to " 871 printk(KERN_ERR "Failure occurred while attempting to "
844 "initialize the communications channel to " 872 "initialize the communications channel to "
845 "ecryptfsd\n"); 873 "ecryptfsd\n");
846 goto out_destroy_kthread; 874 goto out_destroy_kthread;