diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-10-16 04:28:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:12 -0400 |
commit | d7cdc5febf9f2664755002c3a2f84bd348389fe9 (patch) | |
tree | ad770ac2031d87474220cc20eb7b99a246dea8bb /fs/ecryptfs/crypto.c | |
parent | 4981e081cfe2c3f4abcfa3924ebd999cdbed4914 (diff) |
eCryptfs: update metadata read/write functions
Update the metadata read/write functions and grow_file() to use the
read_write.c routines. Do not open another lower file; use the persistent
lower file instead. Provide a separate function for
crypto.c::ecryptfs_read_xattr_region() to get to the lower xattr without
having to go through the eCryptfs getxattr.
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>
Diffstat (limited to 'fs/ecryptfs/crypto.c')
-rw-r--r-- | fs/ecryptfs/crypto.c | 127 |
1 files changed, 59 insertions, 68 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 7f788ea5da2b..55110ffe9ebd 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -1342,21 +1342,28 @@ out: | |||
1342 | return rc; | 1342 | return rc; |
1343 | } | 1343 | } |
1344 | 1344 | ||
1345 | int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry, | 1345 | int ecryptfs_read_and_validate_header_region(char *data, |
1346 | struct vfsmount *mnt) | 1346 | struct inode *ecryptfs_inode) |
1347 | { | 1347 | { |
1348 | struct ecryptfs_crypt_stat *crypt_stat = | ||
1349 | &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); | ||
1348 | int rc; | 1350 | int rc; |
1349 | 1351 | ||
1350 | rc = ecryptfs_read_header_region(data, dentry, mnt); | 1352 | rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size, |
1351 | if (rc) | 1353 | ecryptfs_inode); |
1354 | if (rc) { | ||
1355 | printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n", | ||
1356 | __FUNCTION__, rc); | ||
1352 | goto out; | 1357 | goto out; |
1353 | if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) | 1358 | } |
1359 | if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) { | ||
1354 | rc = -EINVAL; | 1360 | rc = -EINVAL; |
1361 | ecryptfs_printk(KERN_DEBUG, "Valid marker not found\n"); | ||
1362 | } | ||
1355 | out: | 1363 | out: |
1356 | return rc; | 1364 | return rc; |
1357 | } | 1365 | } |
1358 | 1366 | ||
1359 | |||
1360 | void | 1367 | void |
1361 | ecryptfs_write_header_metadata(char *virt, | 1368 | ecryptfs_write_header_metadata(char *virt, |
1362 | struct ecryptfs_crypt_stat *crypt_stat, | 1369 | struct ecryptfs_crypt_stat *crypt_stat, |
@@ -1441,24 +1448,19 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, | |||
1441 | 1448 | ||
1442 | static int | 1449 | static int |
1443 | ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, | 1450 | ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, |
1444 | struct file *lower_file, char *page_virt) | 1451 | struct dentry *ecryptfs_dentry, |
1452 | char *page_virt) | ||
1445 | { | 1453 | { |
1446 | mm_segment_t oldfs; | ||
1447 | int current_header_page; | 1454 | int current_header_page; |
1448 | int header_pages; | 1455 | int header_pages; |
1449 | ssize_t size; | 1456 | int rc; |
1450 | int rc = 0; | ||
1451 | 1457 | ||
1452 | lower_file->f_pos = 0; | 1458 | rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt, |
1453 | oldfs = get_fs(); | 1459 | 0, PAGE_CACHE_SIZE); |
1454 | set_fs(get_ds()); | 1460 | if (rc) { |
1455 | size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE, | 1461 | printk(KERN_ERR "%s: Error attempting to write header " |
1456 | &lower_file->f_pos); | 1462 | "information to lower file; rc = [%d]\n", __FUNCTION__, |
1457 | if (size < 0) { | 1463 | rc); |
1458 | rc = (int)size; | ||
1459 | printk(KERN_ERR "Error attempting to write lower page; " | ||
1460 | "rc = [%d]\n", rc); | ||
1461 | set_fs(oldfs); | ||
1462 | goto out; | 1464 | goto out; |
1463 | } | 1465 | } |
1464 | header_pages = ((crypt_stat->extent_size | 1466 | header_pages = ((crypt_stat->extent_size |
@@ -1467,18 +1469,19 @@ ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, | |||
1467 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 1469 | memset(page_virt, 0, PAGE_CACHE_SIZE); |
1468 | current_header_page = 1; | 1470 | current_header_page = 1; |
1469 | while (current_header_page < header_pages) { | 1471 | while (current_header_page < header_pages) { |
1470 | size = vfs_write(lower_file, (char __user *)page_virt, | 1472 | loff_t offset; |
1471 | PAGE_CACHE_SIZE, &lower_file->f_pos); | 1473 | |
1472 | if (size < 0) { | 1474 | offset = (current_header_page << PAGE_CACHE_SHIFT); |
1473 | rc = (int)size; | 1475 | if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, |
1474 | printk(KERN_ERR "Error attempting to write lower page; " | 1476 | page_virt, offset, |
1475 | "rc = [%d]\n", rc); | 1477 | PAGE_CACHE_SIZE))) { |
1476 | set_fs(oldfs); | 1478 | printk(KERN_ERR "%s: Error attempting to write header " |
1479 | "information to lower file; rc = [%d]\n", | ||
1480 | __FUNCTION__, rc); | ||
1477 | goto out; | 1481 | goto out; |
1478 | } | 1482 | } |
1479 | current_header_page++; | 1483 | current_header_page++; |
1480 | } | 1484 | } |
1481 | set_fs(oldfs); | ||
1482 | out: | 1485 | out: |
1483 | return rc; | 1486 | return rc; |
1484 | } | 1487 | } |
@@ -1498,7 +1501,6 @@ ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, | |||
1498 | /** | 1501 | /** |
1499 | * ecryptfs_write_metadata | 1502 | * ecryptfs_write_metadata |
1500 | * @ecryptfs_dentry: The eCryptfs dentry | 1503 | * @ecryptfs_dentry: The eCryptfs dentry |
1501 | * @lower_file: The lower file struct, which was returned from dentry_open | ||
1502 | * | 1504 | * |
1503 | * Write the file headers out. This will likely involve a userspace | 1505 | * Write the file headers out. This will likely involve a userspace |
1504 | * callout, in which the session key is encrypted with one or more | 1506 | * callout, in which the session key is encrypted with one or more |
@@ -1506,22 +1508,21 @@ ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, | |||
1506 | * retrieved via a prompt. Exactly what happens at this point should | 1508 | * retrieved via a prompt. Exactly what happens at this point should |
1507 | * be policy-dependent. | 1509 | * be policy-dependent. |
1508 | * | 1510 | * |
1511 | * TODO: Support header information spanning multiple pages | ||
1512 | * | ||
1509 | * Returns zero on success; non-zero on error | 1513 | * Returns zero on success; non-zero on error |
1510 | */ | 1514 | */ |
1511 | int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, | 1515 | int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) |
1512 | struct file *lower_file) | ||
1513 | { | 1516 | { |
1514 | struct ecryptfs_crypt_stat *crypt_stat; | 1517 | struct ecryptfs_crypt_stat *crypt_stat = |
1518 | &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; | ||
1515 | char *page_virt; | 1519 | char *page_virt; |
1516 | size_t size; | 1520 | size_t size = 0; |
1517 | int rc = 0; | 1521 | int rc = 0; |
1518 | 1522 | ||
1519 | crypt_stat = &ecryptfs_inode_to_private( | ||
1520 | ecryptfs_dentry->d_inode)->crypt_stat; | ||
1521 | if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { | 1523 | if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { |
1522 | if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { | 1524 | if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { |
1523 | ecryptfs_printk(KERN_DEBUG, "Key is " | 1525 | printk(KERN_ERR "Key is invalid; bailing out\n"); |
1524 | "invalid; bailing out\n"); | ||
1525 | rc = -EINVAL; | 1526 | rc = -EINVAL; |
1526 | goto out; | 1527 | goto out; |
1527 | } | 1528 | } |
@@ -1550,7 +1551,8 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, | |||
1550 | crypt_stat, page_virt, | 1551 | crypt_stat, page_virt, |
1551 | size); | 1552 | size); |
1552 | else | 1553 | else |
1553 | rc = ecryptfs_write_metadata_to_contents(crypt_stat, lower_file, | 1554 | rc = ecryptfs_write_metadata_to_contents(crypt_stat, |
1555 | ecryptfs_dentry, | ||
1554 | page_virt); | 1556 | page_virt); |
1555 | if (rc) { | 1557 | if (rc) { |
1556 | printk(KERN_ERR "Error writing metadata out to lower file; " | 1558 | printk(KERN_ERR "Error writing metadata out to lower file; " |
@@ -1678,15 +1680,17 @@ out: | |||
1678 | * | 1680 | * |
1679 | * Returns zero on success; non-zero on error | 1681 | * Returns zero on success; non-zero on error |
1680 | */ | 1682 | */ |
1681 | int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry) | 1683 | int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode) |
1682 | { | 1684 | { |
1685 | struct dentry *lower_dentry = | ||
1686 | ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry; | ||
1683 | ssize_t size; | 1687 | ssize_t size; |
1684 | int rc = 0; | 1688 | int rc = 0; |
1685 | 1689 | ||
1686 | size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, | 1690 | size = ecryptfs_getxattr_lower(lower_dentry, ECRYPTFS_XATTR_NAME, |
1687 | page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE); | 1691 | page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE); |
1688 | if (size < 0) { | 1692 | if (size < 0) { |
1689 | printk(KERN_DEBUG "Error attempting to read the [%s] " | 1693 | printk(KERN_ERR "Error attempting to read the [%s] " |
1690 | "xattr from the lower file; return value = [%zd]\n", | 1694 | "xattr from the lower file; return value = [%zd]\n", |
1691 | ECRYPTFS_XATTR_NAME, size); | 1695 | ECRYPTFS_XATTR_NAME, size); |
1692 | rc = -EINVAL; | 1696 | rc = -EINVAL; |
@@ -1701,7 +1705,7 @@ int ecryptfs_read_and_validate_xattr_region(char *page_virt, | |||
1701 | { | 1705 | { |
1702 | int rc; | 1706 | int rc; |
1703 | 1707 | ||
1704 | rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry); | 1708 | rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry->d_inode); |
1705 | if (rc) | 1709 | if (rc) |
1706 | goto out; | 1710 | goto out; |
1707 | if (!contains_ecryptfs_marker(page_virt + ECRYPTFS_FILE_SIZE_BYTES)) { | 1711 | if (!contains_ecryptfs_marker(page_virt + ECRYPTFS_FILE_SIZE_BYTES)) { |
@@ -1715,8 +1719,6 @@ out: | |||
1715 | 1719 | ||
1716 | /** | 1720 | /** |
1717 | * ecryptfs_read_metadata | 1721 | * ecryptfs_read_metadata |
1718 | * @ecryptfs_dentry: The eCryptfs dentry | ||
1719 | * @lower_file: The lower file from which to read the metadata | ||
1720 | * | 1722 | * |
1721 | * Common entry point for reading file metadata. From here, we could | 1723 | * Common entry point for reading file metadata. From here, we could |
1722 | * retrieve the header information from the header region of the file, | 1724 | * retrieve the header information from the header region of the file, |
@@ -1727,15 +1729,13 @@ out: | |||
1727 | * | 1729 | * |
1728 | * Returns zero if valid headers found and parsed; non-zero otherwise | 1730 | * Returns zero if valid headers found and parsed; non-zero otherwise |
1729 | */ | 1731 | */ |
1730 | int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry, | 1732 | int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) |
1731 | struct file *lower_file) | ||
1732 | { | 1733 | { |
1733 | int rc = 0; | 1734 | int rc = 0; |
1734 | char *page_virt = NULL; | 1735 | char *page_virt = NULL; |
1735 | mm_segment_t oldfs; | 1736 | struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; |
1736 | ssize_t bytes_read; | ||
1737 | struct ecryptfs_crypt_stat *crypt_stat = | 1737 | struct ecryptfs_crypt_stat *crypt_stat = |
1738 | &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; | 1738 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; |
1739 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = | 1739 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = |
1740 | &ecryptfs_superblock_to_private( | 1740 | &ecryptfs_superblock_to_private( |
1741 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | 1741 | ecryptfs_dentry->d_sb)->mount_crypt_stat; |
@@ -1746,27 +1746,18 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry, | |||
1746 | page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER); | 1746 | page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER); |
1747 | if (!page_virt) { | 1747 | if (!page_virt) { |
1748 | rc = -ENOMEM; | 1748 | rc = -ENOMEM; |
1749 | ecryptfs_printk(KERN_ERR, "Unable to allocate page_virt\n"); | 1749 | printk(KERN_ERR "%s: Unable to allocate page_virt\n", |
1750 | __FUNCTION__); | ||
1750 | goto out; | 1751 | goto out; |
1751 | } | 1752 | } |
1752 | lower_file->f_pos = 0; | 1753 | rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size, |
1753 | oldfs = get_fs(); | 1754 | ecryptfs_inode); |
1754 | set_fs(get_ds()); | 1755 | if (!rc) |
1755 | bytes_read = lower_file->f_op->read(lower_file, | 1756 | rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, |
1756 | (char __user *)page_virt, | 1757 | ecryptfs_dentry, |
1757 | ECRYPTFS_DEFAULT_EXTENT_SIZE, | 1758 | ECRYPTFS_VALIDATE_HEADER_SIZE); |
1758 | &lower_file->f_pos); | ||
1759 | set_fs(oldfs); | ||
1760 | if (bytes_read != ECRYPTFS_DEFAULT_EXTENT_SIZE) { | ||
1761 | rc = -EINVAL; | ||
1762 | goto out; | ||
1763 | } | ||
1764 | rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, | ||
1765 | ecryptfs_dentry, | ||
1766 | ECRYPTFS_VALIDATE_HEADER_SIZE); | ||
1767 | if (rc) { | 1759 | if (rc) { |
1768 | rc = ecryptfs_read_xattr_region(page_virt, | 1760 | rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode); |
1769 | ecryptfs_dentry); | ||
1770 | if (rc) { | 1761 | if (rc) { |
1771 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " | 1762 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " |
1772 | "file header region or xattr region\n"); | 1763 | "file header region or xattr region\n"); |