aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@canonical.com>2012-06-21 02:50:59 -0400
committerTyler Hicks <tyhicks@canonical.com>2012-07-08 13:51:45 -0400
commite3ccaa9761200952cc269b1f4b7d7bb77a5e071b (patch)
treefce1240d5666184763da4b5fe3bfcfdf294faab6 /fs
parent8bc2d3cf612994a960c2e8eaea37f6676f67082a (diff)
eCryptfs: Initialize empty lower files when opening them
Historically, eCryptfs has only initialized lower files in the ecryptfs_create() path. Lower file initialization is the act of writing the cryptographic metadata from the inode's crypt_stat to the header of the file. The ecryptfs_open() path already expects that metadata to be in the header of the file. A number of users have reported empty lower files in beneath their eCryptfs mounts. Most of the causes for those empty files being left around have been addressed, but the presence of empty files causes problems due to the lack of proper cryptographic metadata. To transparently solve this problem, this patch initializes empty lower files in the ecryptfs_open() error path. If the metadata is unreadable due to the lower inode size being 0, plaintext passthrough support is not in use, and the metadata is stored in the header of the file (as opposed to the user.ecryptfs extended attribute), the lower file will be initialized. The number of nested conditionals in ecryptfs_open() was getting out of hand, so a helper function was created. To avoid the same nested conditional problem, the conditional logic was reversed inside of the helper function. https://launchpad.net/bugs/911507 Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Cc: John Johansen <john.johansen@canonical.com> Cc: Colin Ian King <colin.king@canonical.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h2
-rw-r--r--fs/ecryptfs/file.c71
-rw-r--r--fs/ecryptfs/inode.c4
3 files changed, 49 insertions, 28 deletions
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 0deb4f24957a..9f77ff818173 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -563,6 +563,8 @@ struct ecryptfs_open_req {
563struct inode *ecryptfs_get_inode(struct inode *lower_inode, 563struct inode *ecryptfs_get_inode(struct inode *lower_inode,
564 struct super_block *sb); 564 struct super_block *sb);
565void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); 565void ecryptfs_i_size_init(const char *page_virt, struct inode *inode);
566int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
567 struct inode *ecryptfs_inode);
566int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, 568int ecryptfs_decode_and_decrypt_filename(char **decrypted_name,
567 size_t *decrypted_name_size, 569 size_t *decrypted_name_size,
568 struct dentry *ecryptfs_dentry, 570 struct dentry *ecryptfs_dentry,
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 2b17f2f9b121..baf8b0550391 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -161,6 +161,48 @@ static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma)
161 161
162struct kmem_cache *ecryptfs_file_info_cache; 162struct kmem_cache *ecryptfs_file_info_cache;
163 163
164static int read_or_initialize_metadata(struct dentry *dentry)
165{
166 struct inode *inode = dentry->d_inode;
167 struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
168 struct ecryptfs_crypt_stat *crypt_stat;
169 int rc;
170
171 crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
172 mount_crypt_stat = &ecryptfs_superblock_to_private(
173 inode->i_sb)->mount_crypt_stat;
174 mutex_lock(&crypt_stat->cs_mutex);
175
176 if (crypt_stat->flags & ECRYPTFS_POLICY_APPLIED &&
177 crypt_stat->flags & ECRYPTFS_KEY_VALID) {
178 rc = 0;
179 goto out;
180 }
181
182 rc = ecryptfs_read_metadata(dentry);
183 if (!rc)
184 goto out;
185
186 if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) {
187 crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
188 | ECRYPTFS_ENCRYPTED);
189 rc = 0;
190 goto out;
191 }
192
193 if (!(mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) &&
194 !i_size_read(ecryptfs_inode_to_lower(inode))) {
195 rc = ecryptfs_initialize_file(dentry, inode);
196 if (!rc)
197 goto out;
198 }
199
200 rc = -EIO;
201out:
202 mutex_unlock(&crypt_stat->cs_mutex);
203 return rc;
204}
205
164/** 206/**
165 * ecryptfs_open 207 * ecryptfs_open
166 * @inode: inode speciying file to open 208 * @inode: inode speciying file to open
@@ -236,32 +278,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
236 rc = 0; 278 rc = 0;
237 goto out; 279 goto out;
238 } 280 }
239 mutex_lock(&crypt_stat->cs_mutex); 281 rc = read_or_initialize_metadata(ecryptfs_dentry);
240 if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) 282 if (rc)
241 || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { 283 goto out_put;
242 rc = ecryptfs_read_metadata(ecryptfs_dentry);
243 if (rc) {
244 ecryptfs_printk(KERN_DEBUG,
245 "Valid headers not found\n");
246 if (!(mount_crypt_stat->flags
247 & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
248 rc = -EIO;
249 printk(KERN_WARNING "Either the lower file "
250 "is not in a valid eCryptfs format, "
251 "or the key could not be retrieved. "
252 "Plaintext passthrough mode is not "
253 "enabled; returning -EIO\n");
254 mutex_unlock(&crypt_stat->cs_mutex);
255 goto out_put;
256 }
257 rc = 0;
258 crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
259 | ECRYPTFS_ENCRYPTED);
260 mutex_unlock(&crypt_stat->cs_mutex);
261 goto out;
262 }
263 }
264 mutex_unlock(&crypt_stat->cs_mutex);
265 ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = " 284 ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = "
266 "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, 285 "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
267 (unsigned long long)i_size_read(inode)); 286 (unsigned long long)i_size_read(inode));
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 65efe5fa687c..2d4143f8f5c9 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -227,8 +227,8 @@ out:
227 * 227 *
228 * Returns zero on success 228 * Returns zero on success
229 */ 229 */
230static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, 230int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
231 struct inode *ecryptfs_inode) 231 struct inode *ecryptfs_inode)
232{ 232{
233 struct ecryptfs_crypt_stat *crypt_stat = 233 struct ecryptfs_crypt_stat *crypt_stat =
234 &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 234 &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;