aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Halcrow <mhalcrow@us.ibm.com>2007-02-12 03:53:47 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-12 12:48:36 -0500
commite77a56ddceeec87575a13a60fc1a394af6a1f4bc (patch)
tree8be21cc4afbc0596716bc9d4d8dd145dd8c74252
parentdd2a3b7ad98f8482cae481cad89dfed5eee48365 (diff)
[PATCH] eCryptfs: Encrypted passthrough
Provide an option to provide a view of the encrypted files such that the metadata is always in the header of the files, regardless of whether the metadata is actually in the header or in the extended attribute. This mode of operation is useful for applications like incremental backup utilities that do not preserve the extended attributes when directly accessing the lower files. With this option enabled, the files under the eCryptfs mount point will be read-only. Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ecryptfs/crypto.c15
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h7
-rw-r--r--fs/ecryptfs/file.c13
-rw-r--r--fs/ecryptfs/inode.c15
-rw-r--r--fs/ecryptfs/mmap.c74
5 files changed, 113 insertions, 11 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 96fa40a48b4f..44c2ec2e9e6a 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1256,9 +1256,10 @@ out:
1256} 1256}
1257 1257
1258 1258
1259static void 1259void
1260write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat, 1260ecryptfs_write_header_metadata(char *virt,
1261 size_t *written) 1261 struct ecryptfs_crypt_stat *crypt_stat,
1262 size_t *written)
1262{ 1263{
1263 u32 header_extent_size; 1264 u32 header_extent_size;
1264 u16 num_header_extents_at_front; 1265 u16 num_header_extents_at_front;
@@ -1320,7 +1321,8 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t *size,
1320 offset += written; 1321 offset += written;
1321 write_ecryptfs_flags((page_virt + offset), crypt_stat, &written); 1322 write_ecryptfs_flags((page_virt + offset), crypt_stat, &written);
1322 offset += written; 1323 offset += written;
1323 write_header_metadata((page_virt + offset), crypt_stat, &written); 1324 ecryptfs_write_header_metadata((page_virt + offset), crypt_stat,
1325 &written);
1324 offset += written; 1326 offset += written;
1325 rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, 1327 rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat,
1326 ecryptfs_dentry, &written, 1328 ecryptfs_dentry, &written,
@@ -1606,7 +1608,12 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
1606 ssize_t bytes_read; 1608 ssize_t bytes_read;
1607 struct ecryptfs_crypt_stat *crypt_stat = 1609 struct ecryptfs_crypt_stat *crypt_stat =
1608 &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; 1610 &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
1611 struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
1612 &ecryptfs_superblock_to_private(
1613 ecryptfs_dentry->d_sb)->mount_crypt_stat;
1609 1614
1615 ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
1616 mount_crypt_stat);
1610 /* Read the first page from the underlying file */ 1617 /* Read the first page from the underlying file */
1611 page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER); 1618 page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER);
1612 if (!page_virt) { 1619 if (!page_virt) {
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 020abcd16f0e..ec526df4235e 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -559,7 +559,7 @@ ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
559int 559int
560ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, 560ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
561 size_t size, int flags); 561 size_t size, int flags);
562 562int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry);
563int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid); 563int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
564int ecryptfs_process_quit(uid_t uid, pid_t pid); 564int ecryptfs_process_quit(uid_t uid, pid_t pid);
565int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid, 565int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
@@ -582,6 +582,9 @@ int ecryptfs_send_connector(char *data, int data_len,
582 u16 msg_flags, pid_t daemon_pid); 582 u16 msg_flags, pid_t daemon_pid);
583int ecryptfs_init_connector(void); 583int ecryptfs_init_connector(void);
584void ecryptfs_release_connector(void); 584void ecryptfs_release_connector(void);
585 585void
586ecryptfs_write_header_metadata(char *virt,
587 struct ecryptfs_crypt_stat *crypt_stat,
588 size_t *written);
586 589
587#endif /* #ifndef ECRYPTFS_KERNEL_H */ 590#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index f22c3a73485c..652ed772a9be 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -250,6 +250,17 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
250 struct ecryptfs_file_info *file_info; 250 struct ecryptfs_file_info *file_info;
251 int lower_flags; 251 int lower_flags;
252 252
253 mount_crypt_stat = &ecryptfs_superblock_to_private(
254 ecryptfs_dentry->d_sb)->mount_crypt_stat;
255 if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
256 && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR)
257 || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC)
258 || (file->f_flags & O_APPEND))) {
259 printk(KERN_WARNING "Mount has encrypted view enabled; "
260 "files may only be read\n");
261 rc = -EPERM;
262 goto out;
263 }
253 /* Released in ecryptfs_release or end of function if failure */ 264 /* Released in ecryptfs_release or end of function if failure */
254 file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); 265 file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
255 ecryptfs_set_file_private(file, file_info); 266 ecryptfs_set_file_private(file, file_info);
@@ -261,8 +272,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
261 } 272 }
262 lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 273 lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
263 crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; 274 crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
264 mount_crypt_stat = &ecryptfs_superblock_to_private(
265 ecryptfs_dentry->d_sb)->mount_crypt_stat;
266 mutex_lock(&crypt_stat->cs_mutex); 275 mutex_lock(&crypt_stat->cs_mutex);
267 if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) { 276 if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) {
268 ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); 277 ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 6b45b2908f17..bbc1b4f666fe 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -289,6 +289,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
289 char *encoded_name; 289 char *encoded_name;
290 unsigned int encoded_namelen; 290 unsigned int encoded_namelen;
291 struct ecryptfs_crypt_stat *crypt_stat = NULL; 291 struct ecryptfs_crypt_stat *crypt_stat = NULL;
292 struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
292 char *page_virt = NULL; 293 char *page_virt = NULL;
293 struct inode *lower_inode; 294 struct inode *lower_inode;
294 u64 file_size; 295 u64 file_size;
@@ -388,8 +389,18 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
388 } 389 }
389 crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; 390 crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
390 } 391 }
391 memcpy(&file_size, page_virt, sizeof(file_size)); 392 mount_crypt_stat = &ecryptfs_superblock_to_private(
392 file_size = be64_to_cpu(file_size); 393 dentry->d_sb)->mount_crypt_stat;
394 if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
395 if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
396 file_size = (crypt_stat->header_extent_size
397 + i_size_read(lower_dentry->d_inode));
398 else
399 file_size = i_size_read(lower_dentry->d_inode);
400 } else {
401 memcpy(&file_size, page_virt, sizeof(file_size));
402 file_size = be64_to_cpu(file_size);
403 }
393 i_size_write(dentry->d_inode, (loff_t)file_size); 404 i_size_write(dentry->d_inode, (loff_t)file_size);
394 kmem_cache_free(ecryptfs_header_cache_2, page_virt); 405 kmem_cache_free(ecryptfs_header_cache_2, page_virt);
395 goto out; 406 goto out;
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index ba3650d03c48..3386014becc6 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -260,6 +260,33 @@ out:
260 ClearPageUptodate(page); 260 ClearPageUptodate(page);
261 return rc; 261 return rc;
262} 262}
263/**
264 * Header Extent:
265 * Octets 0-7: Unencrypted file size (big-endian)
266 * Octets 8-15: eCryptfs special marker
267 * Octets 16-19: Flags
268 * Octet 16: File format version number (between 0 and 255)
269 * Octets 17-18: Reserved
270 * Octet 19: Bit 1 (lsb): Reserved
271 * Bit 2: Encrypted?
272 * Bits 3-8: Reserved
273 * Octets 20-23: Header extent size (big-endian)
274 * Octets 24-25: Number of header extents at front of file
275 * (big-endian)
276 * Octet 26: Begin RFC 2440 authentication token packet set
277 */
278static void set_header_info(char *page_virt,
279 struct ecryptfs_crypt_stat *crypt_stat)
280{
281 size_t written;
282 int save_num_header_extents_at_front =
283 crypt_stat->num_header_extents_at_front;
284
285 crypt_stat->num_header_extents_at_front = 1;
286 ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written);
287 crypt_stat->num_header_extents_at_front =
288 save_num_header_extents_at_front;
289}
263 290
264/** 291/**
265 * ecryptfs_readpage 292 * ecryptfs_readpage
@@ -289,10 +316,55 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
289 "[%d]\n", rc); 316 "[%d]\n", rc);
290 goto out; 317 goto out;
291 } 318 }
319 } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
320 if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
321 int num_pages_in_header_region =
322 (crypt_stat->header_extent_size
323 / PAGE_CACHE_SIZE);
324
325 if (page->index < num_pages_in_header_region) {
326 char *page_virt;
327
328 page_virt = (char *)kmap(page);
329 if (!page_virt) {
330 rc = -ENOMEM;
331 printk(KERN_ERR "Error mapping page\n");
332 goto out;
333 }
334 memset(page_virt, 0, PAGE_CACHE_SIZE);
335 if (page->index == 0) {
336 rc = ecryptfs_read_xattr_region(
337 page_virt, file->f_path.dentry);
338 set_header_info(page_virt, crypt_stat);
339 }
340 kunmap(page);
341 if (rc) {
342 printk(KERN_ERR "Error reading xattr "
343 "region\n");
344 goto out;
345 }
346 } else {
347 rc = ecryptfs_do_readpage(
348 file, page,
349 (page->index
350 - num_pages_in_header_region));
351 if (rc) {
352 printk(KERN_ERR "Error reading page; "
353 "rc = [%d]\n", rc);
354 goto out;
355 }
356 }
357 } else {
358 rc = ecryptfs_do_readpage(file, page, page->index);
359 if (rc) {
360 printk(KERN_ERR "Error reading page; rc = "
361 "[%d]\n", rc);
362 goto out;
363 }
364 }
292 } else { 365 } else {
293 rc = ecryptfs_decrypt_page(file, page); 366 rc = ecryptfs_decrypt_page(file, page);
294 if (rc) { 367 if (rc) {
295
296 ecryptfs_printk(KERN_ERR, "Error decrypting page; " 368 ecryptfs_printk(KERN_ERR, "Error decrypting page; "
297 "rc = [%d]\n", rc); 369 "rc = [%d]\n", rc);
298 goto out; 370 goto out;