diff options
Diffstat (limited to 'fs/ecryptfs/main.c')
-rw-r--r-- | fs/ecryptfs/main.c | 82 |
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 | */ |
118 | int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | 119 | static 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 | |||
138 | int 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 | ||
158 | void 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 | |||
145 | static struct inode *ecryptfs_get_inode(struct inode *lower_inode, | 171 | static 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 | } |
262 | out: | 290 | out: |
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; |