diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-25 18:03:04 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-25 18:03:04 -0500 |
| commit | 3074c0350b173c9e98b62685e0a61a66d9ff8728 (patch) | |
| tree | 28f2cd48f1278983b1fa7d5b4a5895882ce5ca84 | |
| parent | f8275f9694b8adf9f3498e747ea4c3e8b984499b (diff) | |
| parent | 58ded24f0fcb85bddb665baba75892f6ad0f4b8a (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs
Says Tyler:
"Tim's logging message update will be really helpful to users when
they're trying to locate a problematic file in the lower filesystem
with filename encryption enabled.
You'll recognize the fix from Li, as you commented on that.
You should also be familiar with my setattr/truncate improvements,
since you were the one that pointed them out to us (thanks again!).
Andrew noted the /dev/ecryptfs write count sanitization needed to be
improved, so I've got a fix in there for that along with some other
less important cleanups of the /dev/ecryptfs read/write code."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs:
eCryptfs: Fix oops when printing debug info in extent crypto functions
eCryptfs: Remove unused ecryptfs_read()
eCryptfs: Check inode changes in setattr
eCryptfs: Make truncate path killable
eCryptfs: Infinite loop due to overflow in ecryptfs_write()
eCryptfs: Replace miscdev read/write magic numbers
eCryptfs: Report errors in writes to /dev/ecryptfs
eCryptfs: Sanitize write counts of /dev/ecryptfs
ecryptfs: Remove unnecessary variable initialization
ecryptfs: Improve metadata read failure logging
MAINTAINERS: Update eCryptfs maintainer address
| -rw-r--r-- | MAINTAINERS | 2 | ||||
| -rw-r--r-- | fs/ecryptfs/crypto.c | 54 | ||||
| -rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 5 | ||||
| -rw-r--r-- | fs/ecryptfs/inode.c | 48 | ||||
| -rw-r--r-- | fs/ecryptfs/keystore.c | 5 | ||||
| -rw-r--r-- | fs/ecryptfs/miscdev.c | 140 | ||||
| -rw-r--r-- | fs/ecryptfs/read_write.c | 96 |
7 files changed, 155 insertions, 195 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 93c68d5f1cf4..260d9c1785d0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2402,7 +2402,7 @@ F: net/bridge/netfilter/ebt*.c | |||
| 2402 | 2402 | ||
| 2403 | ECRYPT FILE SYSTEM | 2403 | ECRYPT FILE SYSTEM |
| 2404 | M: Tyler Hicks <tyhicks@canonical.com> | 2404 | M: Tyler Hicks <tyhicks@canonical.com> |
| 2405 | M: Dustin Kirkland <kirkland@canonical.com> | 2405 | M: Dustin Kirkland <dustin.kirkland@gazzang.com> |
| 2406 | L: ecryptfs@vger.kernel.org | 2406 | L: ecryptfs@vger.kernel.org |
| 2407 | W: https://launchpad.net/ecryptfs | 2407 | W: https://launchpad.net/ecryptfs |
| 2408 | S: Supported | 2408 | S: Supported |
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 2a834255c75d..63ab24510649 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
| @@ -417,17 +417,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, | |||
| 417 | (unsigned long long)(extent_base + extent_offset), rc); | 417 | (unsigned long long)(extent_base + extent_offset), rc); |
| 418 | goto out; | 418 | goto out; |
| 419 | } | 419 | } |
| 420 | if (unlikely(ecryptfs_verbosity > 0)) { | ||
| 421 | ecryptfs_printk(KERN_DEBUG, "Encrypting extent " | ||
| 422 | "with iv:\n"); | ||
| 423 | ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes); | ||
| 424 | ecryptfs_printk(KERN_DEBUG, "First 8 bytes before " | ||
| 425 | "encryption:\n"); | ||
| 426 | ecryptfs_dump_hex((char *) | ||
| 427 | (page_address(page) | ||
| 428 | + (extent_offset * crypt_stat->extent_size)), | ||
| 429 | 8); | ||
| 430 | } | ||
| 431 | rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0, | 420 | rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0, |
| 432 | page, (extent_offset | 421 | page, (extent_offset |
| 433 | * crypt_stat->extent_size), | 422 | * crypt_stat->extent_size), |
| @@ -440,14 +429,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, | |||
| 440 | goto out; | 429 | goto out; |
| 441 | } | 430 | } |
| 442 | rc = 0; | 431 | rc = 0; |
| 443 | if (unlikely(ecryptfs_verbosity > 0)) { | ||
| 444 | ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16llx]; " | ||
| 445 | "rc = [%d]\n", | ||
| 446 | (unsigned long long)(extent_base + extent_offset), rc); | ||
| 447 | ecryptfs_printk(KERN_DEBUG, "First 8 bytes after " | ||
| 448 | "encryption:\n"); | ||
| 449 | ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8); | ||
| 450 | } | ||
| 451 | out: | 432 | out: |
| 452 | return rc; | 433 | return rc; |
| 453 | } | 434 | } |
| @@ -543,17 +524,6 @@ static int ecryptfs_decrypt_extent(struct page *page, | |||
| 543 | (unsigned long long)(extent_base + extent_offset), rc); | 524 | (unsigned long long)(extent_base + extent_offset), rc); |
| 544 | goto out; | 525 | goto out; |
| 545 | } | 526 | } |
| 546 | if (unlikely(ecryptfs_verbosity > 0)) { | ||
| 547 | ecryptfs_printk(KERN_DEBUG, "Decrypting extent " | ||
| 548 | "with iv:\n"); | ||
| 549 | ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes); | ||
| 550 | ecryptfs_printk(KERN_DEBUG, "First 8 bytes before " | ||
| 551 | "decryption:\n"); | ||
| 552 | ecryptfs_dump_hex((char *) | ||
| 553 | (page_address(enc_extent_page) | ||
| 554 | + (extent_offset * crypt_stat->extent_size)), | ||
| 555 | 8); | ||
| 556 | } | ||
| 557 | rc = ecryptfs_decrypt_page_offset(crypt_stat, page, | 527 | rc = ecryptfs_decrypt_page_offset(crypt_stat, page, |
| 558 | (extent_offset | 528 | (extent_offset |
| 559 | * crypt_stat->extent_size), | 529 | * crypt_stat->extent_size), |
| @@ -567,16 +537,6 @@ static int ecryptfs_decrypt_extent(struct page *page, | |||
| 567 | goto out; | 537 | goto out; |
| 568 | } | 538 | } |
| 569 | rc = 0; | 539 | rc = 0; |
| 570 | if (unlikely(ecryptfs_verbosity > 0)) { | ||
| 571 | ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16llx]; " | ||
| 572 | "rc = [%d]\n", | ||
| 573 | (unsigned long long)(extent_base + extent_offset), rc); | ||
| 574 | ecryptfs_printk(KERN_DEBUG, "First 8 bytes after " | ||
| 575 | "decryption:\n"); | ||
| 576 | ecryptfs_dump_hex((char *)(page_address(page) | ||
| 577 | + (extent_offset | ||
| 578 | * crypt_stat->extent_size)), 8); | ||
| 579 | } | ||
| 580 | out: | 540 | out: |
| 581 | return rc; | 541 | return rc; |
| 582 | } | 542 | } |
| @@ -1590,8 +1550,8 @@ int ecryptfs_read_and_validate_xattr_region(struct dentry *dentry, | |||
| 1590 | */ | 1550 | */ |
| 1591 | int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) | 1551 | int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) |
| 1592 | { | 1552 | { |
| 1593 | int rc = 0; | 1553 | int rc; |
| 1594 | char *page_virt = NULL; | 1554 | char *page_virt; |
| 1595 | struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; | 1555 | struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; |
| 1596 | struct ecryptfs_crypt_stat *crypt_stat = | 1556 | struct ecryptfs_crypt_stat *crypt_stat = |
| 1597 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; | 1557 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; |
| @@ -1616,11 +1576,13 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) | |||
| 1616 | ecryptfs_dentry, | 1576 | ecryptfs_dentry, |
| 1617 | ECRYPTFS_VALIDATE_HEADER_SIZE); | 1577 | ECRYPTFS_VALIDATE_HEADER_SIZE); |
| 1618 | if (rc) { | 1578 | if (rc) { |
| 1579 | /* metadata is not in the file header, so try xattrs */ | ||
| 1619 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 1580 | memset(page_virt, 0, PAGE_CACHE_SIZE); |
| 1620 | rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode); | 1581 | rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode); |
| 1621 | if (rc) { | 1582 | if (rc) { |
| 1622 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " | 1583 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " |
| 1623 | "file header region or xattr region\n"); | 1584 | "file header region or xattr region, inode %lu\n", |
| 1585 | ecryptfs_inode->i_ino); | ||
| 1624 | rc = -EINVAL; | 1586 | rc = -EINVAL; |
| 1625 | goto out; | 1587 | goto out; |
| 1626 | } | 1588 | } |
| @@ -1629,7 +1591,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) | |||
| 1629 | ECRYPTFS_DONT_VALIDATE_HEADER_SIZE); | 1591 | ECRYPTFS_DONT_VALIDATE_HEADER_SIZE); |
| 1630 | if (rc) { | 1592 | if (rc) { |
| 1631 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " | 1593 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " |
| 1632 | "file xattr region either\n"); | 1594 | "file xattr region either, inode %lu\n", |
| 1595 | ecryptfs_inode->i_ino); | ||
| 1633 | rc = -EINVAL; | 1596 | rc = -EINVAL; |
| 1634 | } | 1597 | } |
| 1635 | if (crypt_stat->mount_crypt_stat->flags | 1598 | if (crypt_stat->mount_crypt_stat->flags |
| @@ -1640,7 +1603,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) | |||
| 1640 | "crypto metadata only in the extended attribute " | 1603 | "crypto metadata only in the extended attribute " |
| 1641 | "region, but eCryptfs was mounted without " | 1604 | "region, but eCryptfs was mounted without " |
| 1642 | "xattr support enabled. eCryptfs will not treat " | 1605 | "xattr support enabled. eCryptfs will not treat " |
| 1643 | "this like an encrypted file.\n"); | 1606 | "this like an encrypted file, inode %lu\n", |
| 1607 | ecryptfs_inode->i_ino); | ||
| 1644 | rc = -EINVAL; | 1608 | rc = -EINVAL; |
| 1645 | } | 1609 | } |
| 1646 | } | 1610 | } |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index a9f29b12fbf2..a2362df58ae8 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
| @@ -151,6 +151,11 @@ ecryptfs_get_key_payload_data(struct key *key) | |||
| 151 | * dentry name */ | 151 | * dentry name */ |
| 152 | #define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as | 152 | #define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as |
| 153 | * metadata */ | 153 | * metadata */ |
| 154 | #define ECRYPTFS_MIN_PKT_LEN_SIZE 1 /* Min size to specify packet length */ | ||
| 155 | #define ECRYPTFS_MAX_PKT_LEN_SIZE 2 /* Pass at least this many bytes to | ||
| 156 | * ecryptfs_parse_packet_length() and | ||
| 157 | * ecryptfs_write_packet_length() | ||
| 158 | */ | ||
| 154 | /* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >= | 159 | /* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >= |
| 155 | * ECRYPTFS_MAX_IV_BYTES */ | 160 | * ECRYPTFS_MAX_IV_BYTES */ |
| 156 | #define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16 | 161 | #define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16 |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 19a8ca4ab1dd..19892d7d2ed1 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
| @@ -822,18 +822,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
| 822 | size_t num_zeros = (PAGE_CACHE_SIZE | 822 | size_t num_zeros = (PAGE_CACHE_SIZE |
| 823 | - (ia->ia_size & ~PAGE_CACHE_MASK)); | 823 | - (ia->ia_size & ~PAGE_CACHE_MASK)); |
| 824 | 824 | ||
| 825 | |||
| 826 | /* | ||
| 827 | * XXX(truncate) this should really happen at the begginning | ||
| 828 | * of ->setattr. But the code is too messy to that as part | ||
| 829 | * of a larger patch. ecryptfs is also totally missing out | ||
| 830 | * on the inode_change_ok check at the beginning of | ||
| 831 | * ->setattr while would include this. | ||
| 832 | */ | ||
| 833 | rc = inode_newsize_ok(inode, ia->ia_size); | ||
| 834 | if (rc) | ||
| 835 | goto out; | ||
| 836 | |||
| 837 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { | 825 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { |
| 838 | truncate_setsize(inode, ia->ia_size); | 826 | truncate_setsize(inode, ia->ia_size); |
| 839 | lower_ia->ia_size = ia->ia_size; | 827 | lower_ia->ia_size = ia->ia_size; |
| @@ -883,6 +871,28 @@ out: | |||
| 883 | return rc; | 871 | return rc; |
| 884 | } | 872 | } |
| 885 | 873 | ||
| 874 | static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset) | ||
| 875 | { | ||
| 876 | struct ecryptfs_crypt_stat *crypt_stat; | ||
| 877 | loff_t lower_oldsize, lower_newsize; | ||
| 878 | |||
| 879 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | ||
| 880 | lower_oldsize = upper_size_to_lower_size(crypt_stat, | ||
| 881 | i_size_read(inode)); | ||
| 882 | lower_newsize = upper_size_to_lower_size(crypt_stat, offset); | ||
| 883 | if (lower_newsize > lower_oldsize) { | ||
| 884 | /* | ||
| 885 | * The eCryptfs inode and the new *lower* size are mixed here | ||
| 886 | * because we may not have the lower i_mutex held and/or it may | ||
| 887 | * not be appropriate to call inode_newsize_ok() with inodes | ||
| 888 | * from other filesystems. | ||
| 889 | */ | ||
| 890 | return inode_newsize_ok(inode, lower_newsize); | ||
| 891 | } | ||
| 892 | |||
| 893 | return 0; | ||
| 894 | } | ||
| 895 | |||
| 886 | /** | 896 | /** |
| 887 | * ecryptfs_truncate | 897 | * ecryptfs_truncate |
| 888 | * @dentry: The ecryptfs layer dentry | 898 | * @dentry: The ecryptfs layer dentry |
| @@ -899,6 +909,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
| 899 | struct iattr lower_ia = { .ia_valid = 0 }; | 909 | struct iattr lower_ia = { .ia_valid = 0 }; |
| 900 | int rc; | 910 | int rc; |
| 901 | 911 | ||
| 912 | rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length); | ||
| 913 | if (rc) | ||
| 914 | return rc; | ||
| 915 | |||
| 902 | rc = truncate_upper(dentry, &ia, &lower_ia); | 916 | rc = truncate_upper(dentry, &ia, &lower_ia); |
| 903 | if (!rc && lower_ia.ia_valid & ATTR_SIZE) { | 917 | if (!rc && lower_ia.ia_valid & ATTR_SIZE) { |
| 904 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | 918 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); |
| @@ -978,6 +992,16 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
| 978 | } | 992 | } |
| 979 | } | 993 | } |
| 980 | mutex_unlock(&crypt_stat->cs_mutex); | 994 | mutex_unlock(&crypt_stat->cs_mutex); |
| 995 | |||
| 996 | rc = inode_change_ok(inode, ia); | ||
| 997 | if (rc) | ||
| 998 | goto out; | ||
| 999 | if (ia->ia_valid & ATTR_SIZE) { | ||
| 1000 | rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size); | ||
| 1001 | if (rc) | ||
| 1002 | goto out; | ||
| 1003 | } | ||
| 1004 | |||
| 981 | if (S_ISREG(inode->i_mode)) { | 1005 | if (S_ISREG(inode->i_mode)) { |
| 982 | rc = filemap_write_and_wait(inode->i_mapping); | 1006 | rc = filemap_write_and_wait(inode->i_mapping); |
| 983 | if (rc) | 1007 | if (rc) |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index ac1ad48c2376..8e3b943e330f 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
| @@ -109,7 +109,7 @@ int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, | |||
| 109 | (*size) += ((unsigned char)(data[1]) + 192); | 109 | (*size) += ((unsigned char)(data[1]) + 192); |
| 110 | (*length_size) = 2; | 110 | (*length_size) = 2; |
| 111 | } else if (data[0] == 255) { | 111 | } else if (data[0] == 255) { |
| 112 | /* Five-byte length; we're not supposed to see this */ | 112 | /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */ |
| 113 | ecryptfs_printk(KERN_ERR, "Five-byte packet length not " | 113 | ecryptfs_printk(KERN_ERR, "Five-byte packet length not " |
| 114 | "supported\n"); | 114 | "supported\n"); |
| 115 | rc = -EINVAL; | 115 | rc = -EINVAL; |
| @@ -126,7 +126,7 @@ out: | |||
| 126 | /** | 126 | /** |
| 127 | * ecryptfs_write_packet_length | 127 | * ecryptfs_write_packet_length |
| 128 | * @dest: The byte array target into which to write the length. Must | 128 | * @dest: The byte array target into which to write the length. Must |
| 129 | * have at least 5 bytes allocated. | 129 | * have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated. |
| 130 | * @size: The length to write. | 130 | * @size: The length to write. |
| 131 | * @packet_size_length: The number of bytes used to encode the packet | 131 | * @packet_size_length: The number of bytes used to encode the packet |
| 132 | * length is written to this address. | 132 | * length is written to this address. |
| @@ -146,6 +146,7 @@ int ecryptfs_write_packet_length(char *dest, size_t size, | |||
| 146 | dest[1] = ((size - 192) % 256); | 146 | dest[1] = ((size - 192) % 256); |
| 147 | (*packet_size_length) = 2; | 147 | (*packet_size_length) = 2; |
| 148 | } else { | 148 | } else { |
| 149 | /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */ | ||
| 149 | rc = -EINVAL; | 150 | rc = -EINVAL; |
| 150 | ecryptfs_printk(KERN_WARNING, | 151 | ecryptfs_printk(KERN_WARNING, |
| 151 | "Unsupported packet size: [%zd]\n", size); | 152 | "Unsupported packet size: [%zd]\n", size); |
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index 940a82e63dc3..349209dc6a91 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c | |||
| @@ -218,6 +218,29 @@ out_unlock: | |||
| 218 | return rc; | 218 | return rc; |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | /* | ||
| 222 | * miscdevfs packet format: | ||
| 223 | * Octet 0: Type | ||
| 224 | * Octets 1-4: network byte order msg_ctx->counter | ||
| 225 | * Octets 5-N0: Size of struct ecryptfs_message to follow | ||
| 226 | * Octets N0-N1: struct ecryptfs_message (including data) | ||
| 227 | * | ||
| 228 | * Octets 5-N1 not written if the packet type does not include a message | ||
| 229 | */ | ||
| 230 | #define PKT_TYPE_SIZE 1 | ||
| 231 | #define PKT_CTR_SIZE 4 | ||
| 232 | #define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE) | ||
| 233 | #define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \ | ||
| 234 | + ECRYPTFS_MIN_PKT_LEN_SIZE) | ||
| 235 | /* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */ | ||
| 236 | #define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \ | ||
| 237 | + ECRYPTFS_MAX_PKT_LEN_SIZE \ | ||
| 238 | + sizeof(struct ecryptfs_message) \ | ||
| 239 | + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) | ||
| 240 | #define PKT_TYPE_OFFSET 0 | ||
| 241 | #define PKT_CTR_OFFSET PKT_TYPE_SIZE | ||
| 242 | #define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE) | ||
| 243 | |||
| 221 | /** | 244 | /** |
| 222 | * ecryptfs_miscdev_read - format and send message from queue | 245 | * ecryptfs_miscdev_read - format and send message from queue |
| 223 | * @file: fs/ecryptfs/euid miscdevfs handle (ignored) | 246 | * @file: fs/ecryptfs/euid miscdevfs handle (ignored) |
| @@ -237,7 +260,7 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, | |||
| 237 | struct ecryptfs_daemon *daemon; | 260 | struct ecryptfs_daemon *daemon; |
| 238 | struct ecryptfs_msg_ctx *msg_ctx; | 261 | struct ecryptfs_msg_ctx *msg_ctx; |
| 239 | size_t packet_length_size; | 262 | size_t packet_length_size; |
| 240 | char packet_length[3]; | 263 | char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; |
| 241 | size_t i; | 264 | size_t i; |
| 242 | size_t total_length; | 265 | size_t total_length; |
| 243 | uid_t euid = current_euid(); | 266 | uid_t euid = current_euid(); |
| @@ -305,15 +328,8 @@ check_list: | |||
| 305 | packet_length_size = 0; | 328 | packet_length_size = 0; |
| 306 | msg_ctx->msg_size = 0; | 329 | msg_ctx->msg_size = 0; |
| 307 | } | 330 | } |
| 308 | /* miscdevfs packet format: | 331 | total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size |
| 309 | * Octet 0: Type | 332 | + msg_ctx->msg_size); |
| 310 | * Octets 1-4: network byte order msg_ctx->counter | ||
| 311 | * Octets 5-N0: Size of struct ecryptfs_message to follow | ||
| 312 | * Octets N0-N1: struct ecryptfs_message (including data) | ||
| 313 | * | ||
| 314 | * Octets 5-N1 not written if the packet type does not | ||
| 315 | * include a message */ | ||
| 316 | total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size); | ||
| 317 | if (count < total_length) { | 333 | if (count < total_length) { |
| 318 | rc = 0; | 334 | rc = 0; |
| 319 | printk(KERN_WARNING "%s: Only given user buffer of " | 335 | printk(KERN_WARNING "%s: Only given user buffer of " |
| @@ -324,9 +340,10 @@ check_list: | |||
| 324 | rc = -EFAULT; | 340 | rc = -EFAULT; |
| 325 | if (put_user(msg_ctx->type, buf)) | 341 | if (put_user(msg_ctx->type, buf)) |
| 326 | goto out_unlock_msg_ctx; | 342 | goto out_unlock_msg_ctx; |
| 327 | if (put_user(cpu_to_be32(msg_ctx->counter), (__be32 __user *)(buf + 1))) | 343 | if (put_user(cpu_to_be32(msg_ctx->counter), |
| 344 | (__be32 __user *)(&buf[PKT_CTR_OFFSET]))) | ||
| 328 | goto out_unlock_msg_ctx; | 345 | goto out_unlock_msg_ctx; |
| 329 | i = 5; | 346 | i = PKT_TYPE_SIZE + PKT_CTR_SIZE; |
| 330 | if (msg_ctx->msg) { | 347 | if (msg_ctx->msg) { |
| 331 | if (copy_to_user(&buf[i], packet_length, packet_length_size)) | 348 | if (copy_to_user(&buf[i], packet_length, packet_length_size)) |
| 332 | goto out_unlock_msg_ctx; | 349 | goto out_unlock_msg_ctx; |
| @@ -391,12 +408,6 @@ out: | |||
| 391 | * @count: Amount of data in @buf | 408 | * @count: Amount of data in @buf |
| 392 | * @ppos: Pointer to offset in file (ignored) | 409 | * @ppos: Pointer to offset in file (ignored) |
| 393 | * | 410 | * |
| 394 | * miscdevfs packet format: | ||
| 395 | * Octet 0: Type | ||
| 396 | * Octets 1-4: network byte order msg_ctx->counter (0's for non-response) | ||
| 397 | * Octets 5-N0: Size of struct ecryptfs_message to follow | ||
| 398 | * Octets N0-N1: struct ecryptfs_message (including data) | ||
| 399 | * | ||
| 400 | * Returns the number of bytes read from @buf | 411 | * Returns the number of bytes read from @buf |
| 401 | */ | 412 | */ |
| 402 | static ssize_t | 413 | static ssize_t |
| @@ -405,60 +416,78 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, | |||
| 405 | { | 416 | { |
| 406 | __be32 counter_nbo; | 417 | __be32 counter_nbo; |
| 407 | u32 seq; | 418 | u32 seq; |
| 408 | size_t packet_size, packet_size_length, i; | 419 | size_t packet_size, packet_size_length; |
| 409 | ssize_t sz = 0; | ||
| 410 | char *data; | 420 | char *data; |
| 411 | uid_t euid = current_euid(); | 421 | uid_t euid = current_euid(); |
| 412 | int rc; | 422 | unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; |
| 423 | ssize_t rc; | ||
| 413 | 424 | ||
| 414 | if (count == 0) | 425 | if (count == 0) { |
| 415 | goto out; | 426 | return 0; |
| 427 | } else if (count == MIN_NON_MSG_PKT_SIZE) { | ||
| 428 | /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */ | ||
| 429 | goto memdup; | ||
| 430 | } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) { | ||
| 431 | printk(KERN_WARNING "%s: Acceptable packet size range is " | ||
| 432 | "[%d-%lu], but amount of data written is [%zu].", | ||
| 433 | __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count); | ||
| 434 | return -EINVAL; | ||
| 435 | } | ||
| 436 | |||
| 437 | if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET], | ||
| 438 | sizeof(packet_size_peek))) { | ||
| 439 | printk(KERN_WARNING "%s: Error while inspecting packet size\n", | ||
| 440 | __func__); | ||
| 441 | return -EFAULT; | ||
| 442 | } | ||
| 416 | 443 | ||
| 444 | rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size, | ||
| 445 | &packet_size_length); | ||
| 446 | if (rc) { | ||
| 447 | printk(KERN_WARNING "%s: Error parsing packet length; " | ||
| 448 | "rc = [%zd]\n", __func__, rc); | ||
| 449 | return rc; | ||
| 450 | } | ||
| 451 | |||
| 452 | if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size) | ||
| 453 | != count) { | ||
| 454 | printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__, | ||
| 455 | packet_size); | ||
| 456 | return -EINVAL; | ||
| 457 | } | ||
| 458 | |||
| 459 | memdup: | ||
| 417 | data = memdup_user(buf, count); | 460 | data = memdup_user(buf, count); |
| 418 | if (IS_ERR(data)) { | 461 | if (IS_ERR(data)) { |
| 419 | printk(KERN_ERR "%s: memdup_user returned error [%ld]\n", | 462 | printk(KERN_ERR "%s: memdup_user returned error [%ld]\n", |
| 420 | __func__, PTR_ERR(data)); | 463 | __func__, PTR_ERR(data)); |
| 421 | goto out; | 464 | return PTR_ERR(data); |
| 422 | } | 465 | } |
| 423 | sz = count; | 466 | switch (data[PKT_TYPE_OFFSET]) { |
| 424 | i = 0; | ||
| 425 | switch (data[i++]) { | ||
| 426 | case ECRYPTFS_MSG_RESPONSE: | 467 | case ECRYPTFS_MSG_RESPONSE: |
| 427 | if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) { | 468 | if (count < (MIN_MSG_PKT_SIZE |
| 469 | + sizeof(struct ecryptfs_message))) { | ||
| 428 | printk(KERN_WARNING "%s: Minimum acceptable packet " | 470 | printk(KERN_WARNING "%s: Minimum acceptable packet " |
| 429 | "size is [%zd], but amount of data written is " | 471 | "size is [%zd], but amount of data written is " |
| 430 | "only [%zd]. Discarding response packet.\n", | 472 | "only [%zd]. Discarding response packet.\n", |
| 431 | __func__, | 473 | __func__, |
| 432 | (1 + 4 + 1 + sizeof(struct ecryptfs_message)), | 474 | (MIN_MSG_PKT_SIZE |
| 433 | count); | 475 | + sizeof(struct ecryptfs_message)), count); |
| 476 | rc = -EINVAL; | ||
| 434 | goto out_free; | 477 | goto out_free; |
| 435 | } | 478 | } |
| 436 | memcpy(&counter_nbo, &data[i], 4); | 479 | memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); |
| 437 | seq = be32_to_cpu(counter_nbo); | 480 | seq = be32_to_cpu(counter_nbo); |
| 438 | i += 4; | 481 | rc = ecryptfs_miscdev_response( |
| 439 | rc = ecryptfs_parse_packet_length(&data[i], &packet_size, | 482 | &data[PKT_LEN_OFFSET + packet_size_length], |
| 440 | &packet_size_length); | 483 | packet_size, euid, current_user_ns(), |
| 484 | task_pid(current), seq); | ||
| 441 | if (rc) { | 485 | if (rc) { |
| 442 | printk(KERN_WARNING "%s: Error parsing packet length; " | ||
| 443 | "rc = [%d]\n", __func__, rc); | ||
| 444 | goto out_free; | ||
| 445 | } | ||
| 446 | i += packet_size_length; | ||
| 447 | if ((1 + 4 + packet_size_length + packet_size) != count) { | ||
| 448 | printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])" | ||
| 449 | " + packet_size([%zd]))([%zd]) != " | ||
| 450 | "count([%zd]). Invalid packet format.\n", | ||
| 451 | __func__, packet_size_length, packet_size, | ||
| 452 | (1 + packet_size_length + packet_size), count); | ||
| 453 | goto out_free; | ||
| 454 | } | ||
| 455 | rc = ecryptfs_miscdev_response(&data[i], packet_size, | ||
| 456 | euid, current_user_ns(), | ||
| 457 | task_pid(current), seq); | ||
| 458 | if (rc) | ||
| 459 | printk(KERN_WARNING "%s: Failed to deliver miscdev " | 486 | printk(KERN_WARNING "%s: Failed to deliver miscdev " |
| 460 | "response to requesting operation; rc = [%d]\n", | 487 | "response to requesting operation; rc = [%zd]\n", |
| 461 | __func__, rc); | 488 | __func__, rc); |
| 489 | goto out_free; | ||
| 490 | } | ||
| 462 | break; | 491 | break; |
| 463 | case ECRYPTFS_MSG_HELO: | 492 | case ECRYPTFS_MSG_HELO: |
| 464 | case ECRYPTFS_MSG_QUIT: | 493 | case ECRYPTFS_MSG_QUIT: |
| @@ -467,12 +496,13 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, | |||
| 467 | ecryptfs_printk(KERN_WARNING, "Dropping miscdev " | 496 | ecryptfs_printk(KERN_WARNING, "Dropping miscdev " |
| 468 | "message of unrecognized type [%d]\n", | 497 | "message of unrecognized type [%d]\n", |
| 469 | data[0]); | 498 | data[0]); |
| 470 | break; | 499 | rc = -EINVAL; |
| 500 | goto out_free; | ||
| 471 | } | 501 | } |
| 502 | rc = count; | ||
| 472 | out_free: | 503 | out_free: |
| 473 | kfree(data); | 504 | kfree(data); |
| 474 | out: | 505 | return rc; |
| 475 | return sz; | ||
| 476 | } | 506 | } |
| 477 | 507 | ||
| 478 | 508 | ||
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 3745f7c2b9c2..5c0106f75775 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c | |||
| @@ -130,13 +130,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
| 130 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); | 130 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); |
| 131 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); | 131 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); |
| 132 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); | 132 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); |
| 133 | size_t total_remaining_bytes = ((offset + size) - pos); | 133 | loff_t total_remaining_bytes = ((offset + size) - pos); |
| 134 | |||
| 135 | if (fatal_signal_pending(current)) { | ||
| 136 | rc = -EINTR; | ||
| 137 | break; | ||
| 138 | } | ||
| 134 | 139 | ||
| 135 | if (num_bytes > total_remaining_bytes) | 140 | if (num_bytes > total_remaining_bytes) |
| 136 | num_bytes = total_remaining_bytes; | 141 | num_bytes = total_remaining_bytes; |
| 137 | if (pos < offset) { | 142 | if (pos < offset) { |
| 138 | /* remaining zeros to write, up to destination offset */ | 143 | /* remaining zeros to write, up to destination offset */ |
| 139 | size_t total_remaining_zeros = (offset - pos); | 144 | loff_t total_remaining_zeros = (offset - pos); |
| 140 | 145 | ||
| 141 | if (num_bytes > total_remaining_zeros) | 146 | if (num_bytes > total_remaining_zeros) |
| 142 | num_bytes = total_remaining_zeros; | 147 | num_bytes = total_remaining_zeros; |
| @@ -193,15 +198,19 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
| 193 | } | 198 | } |
| 194 | pos += num_bytes; | 199 | pos += num_bytes; |
| 195 | } | 200 | } |
| 196 | if ((offset + size) > ecryptfs_file_size) { | 201 | if (pos > ecryptfs_file_size) { |
| 197 | i_size_write(ecryptfs_inode, (offset + size)); | 202 | i_size_write(ecryptfs_inode, pos); |
| 198 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { | 203 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { |
| 199 | rc = ecryptfs_write_inode_size_to_metadata( | 204 | int rc2; |
| 205 | |||
| 206 | rc2 = ecryptfs_write_inode_size_to_metadata( | ||
| 200 | ecryptfs_inode); | 207 | ecryptfs_inode); |
| 201 | if (rc) { | 208 | if (rc2) { |
| 202 | printk(KERN_ERR "Problem with " | 209 | printk(KERN_ERR "Problem with " |
| 203 | "ecryptfs_write_inode_size_to_metadata; " | 210 | "ecryptfs_write_inode_size_to_metadata; " |
| 204 | "rc = [%d]\n", rc); | 211 | "rc = [%d]\n", rc2); |
| 212 | if (!rc) | ||
| 213 | rc = rc2; | ||
| 205 | goto out; | 214 | goto out; |
| 206 | } | 215 | } |
| 207 | } | 216 | } |
| @@ -273,76 +282,3 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, | |||
| 273 | flush_dcache_page(page_for_ecryptfs); | 282 | flush_dcache_page(page_for_ecryptfs); |
| 274 | return rc; | 283 | return rc; |
| 275 | } | 284 | } |
| 276 | |||
| 277 | #if 0 | ||
| 278 | /** | ||
| 279 | * ecryptfs_read | ||
| 280 | * @data: The virtual address into which to write the data read (and | ||
| 281 | * possibly decrypted) from the lower file | ||
| 282 | * @offset: The offset in the decrypted view of the file from which to | ||
| 283 | * read into @data | ||
| 284 | * @size: The number of bytes to read into @data | ||
| 285 | * @ecryptfs_file: The eCryptfs file from which to read | ||
| 286 | * | ||
| 287 | * Read an arbitrary amount of data from an arbitrary location in the | ||
| 288 | * eCryptfs page cache. This is done on an extent-by-extent basis; | ||
| 289 | * individual extents are decrypted and read from the lower page | ||
| 290 | * cache (via VFS reads). This function takes care of all the | ||
| 291 | * address translation to locations in the lower filesystem. | ||
| 292 | * | ||
| 293 | * Returns zero on success; non-zero otherwise | ||
| 294 | */ | ||
| 295 | int ecryptfs_read(char *data, loff_t offset, size_t size, | ||
| 296 | struct file *ecryptfs_file) | ||
| 297 | { | ||
| 298 | struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode; | ||
| 299 | struct page *ecryptfs_page; | ||
| 300 | char *ecryptfs_page_virt; | ||
| 301 | loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode); | ||
| 302 | loff_t data_offset = 0; | ||
| 303 | loff_t pos; | ||
| 304 | int rc = 0; | ||
| 305 | |||
| 306 | if ((offset + size) > ecryptfs_file_size) { | ||
| 307 | rc = -EINVAL; | ||
| 308 | printk(KERN_ERR "%s: Attempt to read data past the end of the " | ||
| 309 | "file; offset = [%lld]; size = [%td]; " | ||
| 310 | "ecryptfs_file_size = [%lld]\n", | ||
| 311 | __func__, offset, size, ecryptfs_file_size); | ||
| 312 | goto out; | ||
| 313 | } | ||
| 314 | pos = offset; | ||
| 315 | while (pos < (offset + size)) { | ||
| 316 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); | ||
| 317 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); | ||
| 318 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); | ||
| 319 | size_t total_remaining_bytes = ((offset + size) - pos); | ||
| 320 | |||
| 321 | if (num_bytes > total_remaining_bytes) | ||
| 322 | num_bytes = total_remaining_bytes; | ||
| 323 | ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode, | ||
| 324 | ecryptfs_page_idx); | ||
| 325 | if (IS_ERR(ecryptfs_page)) { | ||
| 326 | rc = PTR_ERR(ecryptfs_page); | ||
| 327 | printk(KERN_ERR "%s: Error getting page at " | ||
| 328 | "index [%ld] from eCryptfs inode " | ||
| 329 | "mapping; rc = [%d]\n", __func__, | ||
| 330 | ecryptfs_page_idx, rc); | ||
| 331 | goto out; | ||
| 332 | } | ||
| 333 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | ||
| 334 | memcpy((data + data_offset), | ||
| 335 | ((char *)ecryptfs_page_virt + start_offset_in_page), | ||
| 336 | num_bytes); | ||
| 337 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); | ||
| 338 | flush_dcache_page(ecryptfs_page); | ||
| 339 | SetPageUptodate(ecryptfs_page); | ||
| 340 | unlock_page(ecryptfs_page); | ||
| 341 | page_cache_release(ecryptfs_page); | ||
| 342 | pos += num_bytes; | ||
| 343 | data_offset += num_bytes; | ||
| 344 | } | ||
| 345 | out: | ||
| 346 | return rc; | ||
| 347 | } | ||
| 348 | #endif /* 0 */ | ||
