diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2008-02-06 04:38:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-06 13:41:12 -0500 |
commit | cc11beffdf80ca31dff21422fa2a5e54d25f1494 (patch) | |
tree | 3b0e28d18f493a7c59b089c4c6fc59c79945937e | |
parent | 7896b631823c6e8f1a520d89390624a51445840e (diff) |
eCryptfs: track header bytes rather than extents
Remove internal references to header extents; just keep track of header bytes
instead. Headers can easily span multiple pages with the recent persistent
file changes.
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.c | 98 | ||||
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 3 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 8 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 5 | ||||
-rw-r--r-- | fs/ecryptfs/mmap.c | 21 |
5 files changed, 51 insertions, 84 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 5e7d018a3486..4d1b2b4eb79e 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -379,8 +379,7 @@ out: | |||
379 | static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num, | 379 | static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num, |
380 | struct ecryptfs_crypt_stat *crypt_stat) | 380 | struct ecryptfs_crypt_stat *crypt_stat) |
381 | { | 381 | { |
382 | (*offset) = ((crypt_stat->extent_size | 382 | (*offset) = (crypt_stat->num_header_bytes_at_front |
383 | * crypt_stat->num_header_extents_at_front) | ||
384 | + (crypt_stat->extent_size * extent_num)); | 383 | + (crypt_stat->extent_size * extent_num)); |
385 | } | 384 | } |
386 | 385 | ||
@@ -842,15 +841,13 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat) | |||
842 | set_extent_mask_and_shift(crypt_stat); | 841 | set_extent_mask_and_shift(crypt_stat); |
843 | crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES; | 842 | crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES; |
844 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | 843 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) |
845 | crypt_stat->num_header_extents_at_front = 0; | 844 | crypt_stat->num_header_bytes_at_front = 0; |
846 | else { | 845 | else { |
847 | if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) | 846 | if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) |
848 | crypt_stat->num_header_extents_at_front = | 847 | crypt_stat->num_header_bytes_at_front = |
849 | (ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE | 848 | ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; |
850 | / crypt_stat->extent_size); | ||
851 | else | 849 | else |
852 | crypt_stat->num_header_extents_at_front = | 850 | crypt_stat->num_header_bytes_at_front = PAGE_CACHE_SIZE; |
853 | (PAGE_CACHE_SIZE / crypt_stat->extent_size); | ||
854 | } | 851 | } |
855 | } | 852 | } |
856 | 853 | ||
@@ -1236,7 +1233,8 @@ ecryptfs_write_header_metadata(char *virt, | |||
1236 | 1233 | ||
1237 | header_extent_size = (u32)crypt_stat->extent_size; | 1234 | header_extent_size = (u32)crypt_stat->extent_size; |
1238 | num_header_extents_at_front = | 1235 | num_header_extents_at_front = |
1239 | (u16)crypt_stat->num_header_extents_at_front; | 1236 | (u16)(crypt_stat->num_header_bytes_at_front |
1237 | / crypt_stat->extent_size); | ||
1240 | header_extent_size = cpu_to_be32(header_extent_size); | 1238 | header_extent_size = cpu_to_be32(header_extent_size); |
1241 | memcpy(virt, &header_extent_size, 4); | 1239 | memcpy(virt, &header_extent_size, 4); |
1242 | virt += 4; | 1240 | virt += 4; |
@@ -1311,40 +1309,16 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, | |||
1311 | static int | 1309 | static int |
1312 | ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, | 1310 | ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, |
1313 | struct dentry *ecryptfs_dentry, | 1311 | struct dentry *ecryptfs_dentry, |
1314 | char *page_virt) | 1312 | char *virt) |
1315 | { | 1313 | { |
1316 | int current_header_page; | ||
1317 | int header_pages; | ||
1318 | int rc; | 1314 | int rc; |
1319 | 1315 | ||
1320 | rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt, | 1316 | rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt, |
1321 | 0, PAGE_CACHE_SIZE); | 1317 | 0, crypt_stat->num_header_bytes_at_front); |
1322 | if (rc) { | 1318 | if (rc) |
1323 | printk(KERN_ERR "%s: Error attempting to write header " | 1319 | printk(KERN_ERR "%s: Error attempting to write header " |
1324 | "information to lower file; rc = [%d]\n", __FUNCTION__, | 1320 | "information to lower file; rc = [%d]\n", __FUNCTION__, |
1325 | rc); | 1321 | rc); |
1326 | goto out; | ||
1327 | } | ||
1328 | header_pages = ((crypt_stat->extent_size | ||
1329 | * crypt_stat->num_header_extents_at_front) | ||
1330 | / PAGE_CACHE_SIZE); | ||
1331 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
1332 | current_header_page = 1; | ||
1333 | while (current_header_page < header_pages) { | ||
1334 | loff_t offset; | ||
1335 | |||
1336 | offset = (((loff_t)current_header_page) << PAGE_CACHE_SHIFT); | ||
1337 | if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, | ||
1338 | page_virt, offset, | ||
1339 | PAGE_CACHE_SIZE))) { | ||
1340 | printk(KERN_ERR "%s: Error attempting to write header " | ||
1341 | "information to lower file; rc = [%d]\n", | ||
1342 | __FUNCTION__, rc); | ||
1343 | goto out; | ||
1344 | } | ||
1345 | current_header_page++; | ||
1346 | } | ||
1347 | out: | ||
1348 | return rc; | 1322 | return rc; |
1349 | } | 1323 | } |
1350 | 1324 | ||
@@ -1370,15 +1344,13 @@ ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, | |||
1370 | * retrieved via a prompt. Exactly what happens at this point should | 1344 | * retrieved via a prompt. Exactly what happens at this point should |
1371 | * be policy-dependent. | 1345 | * be policy-dependent. |
1372 | * | 1346 | * |
1373 | * TODO: Support header information spanning multiple pages | ||
1374 | * | ||
1375 | * Returns zero on success; non-zero on error | 1347 | * Returns zero on success; non-zero on error |
1376 | */ | 1348 | */ |
1377 | int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) | 1349 | int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) |
1378 | { | 1350 | { |
1379 | struct ecryptfs_crypt_stat *crypt_stat = | 1351 | struct ecryptfs_crypt_stat *crypt_stat = |
1380 | &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; | 1352 | &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; |
1381 | char *page_virt; | 1353 | char *virt; |
1382 | size_t size = 0; | 1354 | size_t size = 0; |
1383 | int rc = 0; | 1355 | int rc = 0; |
1384 | 1356 | ||
@@ -1389,40 +1361,39 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) | |||
1389 | goto out; | 1361 | goto out; |
1390 | } | 1362 | } |
1391 | } else { | 1363 | } else { |
1364 | printk(KERN_WARNING "%s: Encrypted flag not set\n", | ||
1365 | __FUNCTION__); | ||
1392 | rc = -EINVAL; | 1366 | rc = -EINVAL; |
1393 | ecryptfs_printk(KERN_WARNING, | ||
1394 | "Called with crypt_stat->encrypted == 0\n"); | ||
1395 | goto out; | 1367 | goto out; |
1396 | } | 1368 | } |
1397 | /* Released in this function */ | 1369 | /* Released in this function */ |
1398 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_0, GFP_USER); | 1370 | virt = kzalloc(crypt_stat->num_header_bytes_at_front, GFP_KERNEL); |
1399 | if (!page_virt) { | 1371 | if (!virt) { |
1400 | ecryptfs_printk(KERN_ERR, "Out of memory\n"); | 1372 | printk(KERN_ERR "%s: Out of memory\n", __FUNCTION__); |
1401 | rc = -ENOMEM; | 1373 | rc = -ENOMEM; |
1402 | goto out; | 1374 | goto out; |
1403 | } | 1375 | } |
1404 | rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat, | 1376 | rc = ecryptfs_write_headers_virt(virt, &size, crypt_stat, |
1405 | ecryptfs_dentry); | 1377 | ecryptfs_dentry); |
1406 | if (unlikely(rc)) { | 1378 | if (unlikely(rc)) { |
1407 | ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n"); | 1379 | printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n", |
1408 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 1380 | __FUNCTION__, rc); |
1409 | goto out_free; | 1381 | goto out_free; |
1410 | } | 1382 | } |
1411 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | 1383 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) |
1412 | rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, | 1384 | rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, |
1413 | crypt_stat, page_virt, | 1385 | crypt_stat, virt, size); |
1414 | size); | ||
1415 | else | 1386 | else |
1416 | rc = ecryptfs_write_metadata_to_contents(crypt_stat, | 1387 | rc = ecryptfs_write_metadata_to_contents(crypt_stat, |
1417 | ecryptfs_dentry, | 1388 | ecryptfs_dentry, virt); |
1418 | page_virt); | ||
1419 | if (rc) { | 1389 | if (rc) { |
1420 | printk(KERN_ERR "Error writing metadata out to lower file; " | 1390 | printk(KERN_ERR "%s: Error writing metadata out to lower file; " |
1421 | "rc = [%d]\n", rc); | 1391 | "rc = [%d]\n", __FUNCTION__, rc); |
1422 | goto out_free; | 1392 | goto out_free; |
1423 | } | 1393 | } |
1424 | out_free: | 1394 | out_free: |
1425 | kmem_cache_free(ecryptfs_header_cache_0, page_virt); | 1395 | memset(virt, 0, crypt_stat->num_header_bytes_at_front); |
1396 | kfree(virt); | ||
1426 | out: | 1397 | out: |
1427 | return rc; | 1398 | return rc; |
1428 | } | 1399 | } |
@@ -1442,16 +1413,16 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, | |||
1442 | virt += sizeof(u32); | 1413 | virt += sizeof(u32); |
1443 | memcpy(&num_header_extents_at_front, virt, sizeof(u16)); | 1414 | memcpy(&num_header_extents_at_front, virt, sizeof(u16)); |
1444 | num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front); | 1415 | num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front); |
1445 | crypt_stat->num_header_extents_at_front = | 1416 | crypt_stat->num_header_bytes_at_front = |
1446 | (int)num_header_extents_at_front; | 1417 | (((size_t)num_header_extents_at_front |
1418 | * (size_t)header_extent_size)); | ||
1447 | (*bytes_read) = (sizeof(u32) + sizeof(u16)); | 1419 | (*bytes_read) = (sizeof(u32) + sizeof(u16)); |
1448 | if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE) | 1420 | if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE) |
1449 | && ((crypt_stat->extent_size | 1421 | && (crypt_stat->num_header_bytes_at_front |
1450 | * crypt_stat->num_header_extents_at_front) | ||
1451 | < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) { | 1422 | < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) { |
1452 | rc = -EINVAL; | 1423 | rc = -EINVAL; |
1453 | printk(KERN_WARNING "Invalid number of header extents: [%zd]\n", | 1424 | printk(KERN_WARNING "Invalid header size: [%zd]\n", |
1454 | crypt_stat->num_header_extents_at_front); | 1425 | crypt_stat->num_header_bytes_at_front); |
1455 | } | 1426 | } |
1456 | return rc; | 1427 | return rc; |
1457 | } | 1428 | } |
@@ -1466,7 +1437,8 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, | |||
1466 | */ | 1437 | */ |
1467 | static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) | 1438 | static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) |
1468 | { | 1439 | { |
1469 | crypt_stat->num_header_extents_at_front = 2; | 1440 | crypt_stat->num_header_bytes_at_front = |
1441 | ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; | ||
1470 | } | 1442 | } |
1471 | 1443 | ||
1472 | /** | 1444 | /** |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 466661c9fb21..3d637e9ca36a 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -237,7 +237,7 @@ struct ecryptfs_crypt_stat { | |||
237 | u32 flags; | 237 | u32 flags; |
238 | unsigned int file_version; | 238 | unsigned int file_version; |
239 | size_t iv_bytes; | 239 | size_t iv_bytes; |
240 | size_t num_header_extents_at_front; | 240 | size_t num_header_bytes_at_front; |
241 | size_t extent_size; /* Data extent size; default is 4096 */ | 241 | size_t extent_size; /* Data extent size; default is 4096 */ |
242 | size_t key_size; | 242 | size_t key_size; |
243 | size_t extent_shift; | 243 | size_t extent_shift; |
@@ -518,7 +518,6 @@ extern struct kmem_cache *ecryptfs_file_info_cache; | |||
518 | extern struct kmem_cache *ecryptfs_dentry_info_cache; | 518 | extern struct kmem_cache *ecryptfs_dentry_info_cache; |
519 | extern struct kmem_cache *ecryptfs_inode_info_cache; | 519 | extern struct kmem_cache *ecryptfs_inode_info_cache; |
520 | extern struct kmem_cache *ecryptfs_sb_info_cache; | 520 | extern struct kmem_cache *ecryptfs_sb_info_cache; |
521 | extern struct kmem_cache *ecryptfs_header_cache_0; | ||
522 | extern struct kmem_cache *ecryptfs_header_cache_1; | 521 | extern struct kmem_cache *ecryptfs_header_cache_1; |
523 | extern struct kmem_cache *ecryptfs_header_cache_2; | 522 | extern struct kmem_cache *ecryptfs_header_cache_2; |
524 | extern struct kmem_cache *ecryptfs_xattr_cache; | 523 | extern struct kmem_cache *ecryptfs_xattr_cache; |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index ed0ed849ee28..a2bc9df546bd 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -365,8 +365,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
365 | dentry->d_sb)->mount_crypt_stat; | 365 | dentry->d_sb)->mount_crypt_stat; |
366 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | 366 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { |
367 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | 367 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) |
368 | file_size = ((crypt_stat->extent_size | 368 | file_size = (crypt_stat->num_header_bytes_at_front |
369 | * crypt_stat->num_header_extents_at_front) | ||
370 | + i_size_read(lower_dentry->d_inode)); | 369 | + i_size_read(lower_dentry->d_inode)); |
371 | else | 370 | else |
372 | file_size = i_size_read(lower_dentry->d_inode); | 371 | file_size = i_size_read(lower_dentry->d_inode); |
@@ -685,7 +684,7 @@ ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) | |||
685 | * @crypt_stat: Crypt_stat associated with file | 684 | * @crypt_stat: Crypt_stat associated with file |
686 | * @upper_size: Size of the upper file | 685 | * @upper_size: Size of the upper file |
687 | * | 686 | * |
688 | * Calculate the requried size of the lower file based on the | 687 | * Calculate the required size of the lower file based on the |
689 | * specified size of the upper file. This calculation is based on the | 688 | * specified size of the upper file. This calculation is based on the |
690 | * number of headers in the underlying file and the extent size. | 689 | * number of headers in the underlying file and the extent size. |
691 | * | 690 | * |
@@ -697,8 +696,7 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat, | |||
697 | { | 696 | { |
698 | loff_t lower_size; | 697 | loff_t lower_size; |
699 | 698 | ||
700 | lower_size = (crypt_stat->extent_size | 699 | lower_size = crypt_stat->num_header_bytes_at_front; |
701 | * crypt_stat->num_header_extents_at_front); | ||
702 | if (upper_size != 0) { | 700 | if (upper_size != 0) { |
703 | loff_t num_extents; | 701 | loff_t num_extents; |
704 | 702 | ||
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index d9f53c331a27..b67ce83da9fc 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -654,11 +654,6 @@ static struct ecryptfs_cache_info { | |||
654 | .size = sizeof(struct ecryptfs_sb_info), | 654 | .size = sizeof(struct ecryptfs_sb_info), |
655 | }, | 655 | }, |
656 | { | 656 | { |
657 | .cache = &ecryptfs_header_cache_0, | ||
658 | .name = "ecryptfs_headers_0", | ||
659 | .size = PAGE_CACHE_SIZE, | ||
660 | }, | ||
661 | { | ||
662 | .cache = &ecryptfs_header_cache_1, | 657 | .cache = &ecryptfs_header_cache_1, |
663 | .name = "ecryptfs_headers_1", | 658 | .name = "ecryptfs_headers_1", |
664 | .size = PAGE_CACHE_SIZE, | 659 | .size = PAGE_CACHE_SIZE, |
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 9a5e0d17f1c5..dc74b186145d 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -100,13 +100,14 @@ static void set_header_info(char *page_virt, | |||
100 | struct ecryptfs_crypt_stat *crypt_stat) | 100 | struct ecryptfs_crypt_stat *crypt_stat) |
101 | { | 101 | { |
102 | size_t written; | 102 | size_t written; |
103 | int save_num_header_extents_at_front = | 103 | size_t save_num_header_bytes_at_front = |
104 | crypt_stat->num_header_extents_at_front; | 104 | crypt_stat->num_header_bytes_at_front; |
105 | 105 | ||
106 | crypt_stat->num_header_extents_at_front = 1; | 106 | crypt_stat->num_header_bytes_at_front = |
107 | ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; | ||
107 | ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written); | 108 | ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written); |
108 | crypt_stat->num_header_extents_at_front = | 109 | crypt_stat->num_header_bytes_at_front = |
109 | save_num_header_extents_at_front; | 110 | save_num_header_bytes_at_front; |
110 | } | 111 | } |
111 | 112 | ||
112 | /** | 113 | /** |
@@ -132,8 +133,11 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, | |||
132 | loff_t view_extent_num = ((((loff_t)page->index) | 133 | loff_t view_extent_num = ((((loff_t)page->index) |
133 | * num_extents_per_page) | 134 | * num_extents_per_page) |
134 | + extent_num_in_page); | 135 | + extent_num_in_page); |
136 | size_t num_header_extents_at_front = | ||
137 | (crypt_stat->num_header_bytes_at_front | ||
138 | / crypt_stat->extent_size); | ||
135 | 139 | ||
136 | if (view_extent_num < crypt_stat->num_header_extents_at_front) { | 140 | if (view_extent_num < num_header_extents_at_front) { |
137 | /* This is a header extent */ | 141 | /* This is a header extent */ |
138 | char *page_virt; | 142 | char *page_virt; |
139 | 143 | ||
@@ -155,9 +159,8 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, | |||
155 | } else { | 159 | } else { |
156 | /* This is an encrypted data extent */ | 160 | /* This is an encrypted data extent */ |
157 | loff_t lower_offset = | 161 | loff_t lower_offset = |
158 | ((view_extent_num - | 162 | ((view_extent_num * crypt_stat->extent_size) |
159 | crypt_stat->num_header_extents_at_front) | 163 | - crypt_stat->num_header_bytes_at_front); |
160 | * crypt_stat->extent_size); | ||
161 | 164 | ||
162 | rc = ecryptfs_read_lower_page_segment( | 165 | rc = ecryptfs_read_lower_page_segment( |
163 | page, (lower_offset >> PAGE_CACHE_SHIFT), | 166 | page, (lower_offset >> PAGE_CACHE_SHIFT), |