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
This commit is contained in:
Коммит
3074c0350b
|
@ -2402,7 +2402,7 @@ F: net/bridge/netfilter/ebt*.c
|
|||
|
||||
ECRYPT FILE SYSTEM
|
||||
M: Tyler Hicks <tyhicks@canonical.com>
|
||||
M: Dustin Kirkland <kirkland@canonical.com>
|
||||
M: Dustin Kirkland <dustin.kirkland@gazzang.com>
|
||||
L: ecryptfs@vger.kernel.org
|
||||
W: https://launchpad.net/ecryptfs
|
||||
S: Supported
|
||||
|
|
|
@ -417,17 +417,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
|
|||
(unsigned long long)(extent_base + extent_offset), rc);
|
||||
goto out;
|
||||
}
|
||||
if (unlikely(ecryptfs_verbosity > 0)) {
|
||||
ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
|
||||
"with iv:\n");
|
||||
ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
|
||||
ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
|
||||
"encryption:\n");
|
||||
ecryptfs_dump_hex((char *)
|
||||
(page_address(page)
|
||||
+ (extent_offset * crypt_stat->extent_size)),
|
||||
8);
|
||||
}
|
||||
rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
|
||||
page, (extent_offset
|
||||
* crypt_stat->extent_size),
|
||||
|
@ -440,14 +429,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
|
|||
goto out;
|
||||
}
|
||||
rc = 0;
|
||||
if (unlikely(ecryptfs_verbosity > 0)) {
|
||||
ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16llx]; "
|
||||
"rc = [%d]\n",
|
||||
(unsigned long long)(extent_base + extent_offset), rc);
|
||||
ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
|
||||
"encryption:\n");
|
||||
ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
@ -543,17 +524,6 @@ static int ecryptfs_decrypt_extent(struct page *page,
|
|||
(unsigned long long)(extent_base + extent_offset), rc);
|
||||
goto out;
|
||||
}
|
||||
if (unlikely(ecryptfs_verbosity > 0)) {
|
||||
ecryptfs_printk(KERN_DEBUG, "Decrypting extent "
|
||||
"with iv:\n");
|
||||
ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
|
||||
ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
|
||||
"decryption:\n");
|
||||
ecryptfs_dump_hex((char *)
|
||||
(page_address(enc_extent_page)
|
||||
+ (extent_offset * crypt_stat->extent_size)),
|
||||
8);
|
||||
}
|
||||
rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
|
||||
(extent_offset
|
||||
* crypt_stat->extent_size),
|
||||
|
@ -567,16 +537,6 @@ static int ecryptfs_decrypt_extent(struct page *page,
|
|||
goto out;
|
||||
}
|
||||
rc = 0;
|
||||
if (unlikely(ecryptfs_verbosity > 0)) {
|
||||
ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16llx]; "
|
||||
"rc = [%d]\n",
|
||||
(unsigned long long)(extent_base + extent_offset), rc);
|
||||
ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
|
||||
"decryption:\n");
|
||||
ecryptfs_dump_hex((char *)(page_address(page)
|
||||
+ (extent_offset
|
||||
* crypt_stat->extent_size)), 8);
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
@ -1590,8 +1550,8 @@ int ecryptfs_read_and_validate_xattr_region(struct dentry *dentry,
|
|||
*/
|
||||
int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
||||
{
|
||||
int rc = 0;
|
||||
char *page_virt = NULL;
|
||||
int rc;
|
||||
char *page_virt;
|
||||
struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
|
||||
struct ecryptfs_crypt_stat *crypt_stat =
|
||||
&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
|
||||
|
@ -1616,11 +1576,13 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
|||
ecryptfs_dentry,
|
||||
ECRYPTFS_VALIDATE_HEADER_SIZE);
|
||||
if (rc) {
|
||||
/* metadata is not in the file header, so try xattrs */
|
||||
memset(page_virt, 0, PAGE_CACHE_SIZE);
|
||||
rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode);
|
||||
if (rc) {
|
||||
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
|
||||
"file header region or xattr region\n");
|
||||
"file header region or xattr region, inode %lu\n",
|
||||
ecryptfs_inode->i_ino);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -1629,7 +1591,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
|||
ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
|
||||
if (rc) {
|
||||
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
|
||||
"file xattr region either\n");
|
||||
"file xattr region either, inode %lu\n",
|
||||
ecryptfs_inode->i_ino);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
if (crypt_stat->mount_crypt_stat->flags
|
||||
|
@ -1640,7 +1603,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
|||
"crypto metadata only in the extended attribute "
|
||||
"region, but eCryptfs was mounted without "
|
||||
"xattr support enabled. eCryptfs will not treat "
|
||||
"this like an encrypted file.\n");
|
||||
"this like an encrypted file, inode %lu\n",
|
||||
ecryptfs_inode->i_ino);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,6 +151,11 @@ ecryptfs_get_key_payload_data(struct key *key)
|
|||
* dentry name */
|
||||
#define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as
|
||||
* metadata */
|
||||
#define ECRYPTFS_MIN_PKT_LEN_SIZE 1 /* Min size to specify packet length */
|
||||
#define ECRYPTFS_MAX_PKT_LEN_SIZE 2 /* Pass at least this many bytes to
|
||||
* ecryptfs_parse_packet_length() and
|
||||
* ecryptfs_write_packet_length()
|
||||
*/
|
||||
/* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >=
|
||||
* ECRYPTFS_MAX_IV_BYTES */
|
||||
#define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16
|
||||
|
|
|
@ -822,18 +822,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
|
|||
size_t num_zeros = (PAGE_CACHE_SIZE
|
||||
- (ia->ia_size & ~PAGE_CACHE_MASK));
|
||||
|
||||
|
||||
/*
|
||||
* XXX(truncate) this should really happen at the begginning
|
||||
* of ->setattr. But the code is too messy to that as part
|
||||
* of a larger patch. ecryptfs is also totally missing out
|
||||
* on the inode_change_ok check at the beginning of
|
||||
* ->setattr while would include this.
|
||||
*/
|
||||
rc = inode_newsize_ok(inode, ia->ia_size);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
|
||||
truncate_setsize(inode, ia->ia_size);
|
||||
lower_ia->ia_size = ia->ia_size;
|
||||
|
@ -883,6 +871,28 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset)
|
||||
{
|
||||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
loff_t lower_oldsize, lower_newsize;
|
||||
|
||||
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
lower_oldsize = upper_size_to_lower_size(crypt_stat,
|
||||
i_size_read(inode));
|
||||
lower_newsize = upper_size_to_lower_size(crypt_stat, offset);
|
||||
if (lower_newsize > lower_oldsize) {
|
||||
/*
|
||||
* The eCryptfs inode and the new *lower* size are mixed here
|
||||
* because we may not have the lower i_mutex held and/or it may
|
||||
* not be appropriate to call inode_newsize_ok() with inodes
|
||||
* from other filesystems.
|
||||
*/
|
||||
return inode_newsize_ok(inode, lower_newsize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ecryptfs_truncate
|
||||
* @dentry: The ecryptfs layer dentry
|
||||
|
@ -899,6 +909,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
|
|||
struct iattr lower_ia = { .ia_valid = 0 };
|
||||
int rc;
|
||||
|
||||
rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = truncate_upper(dentry, &ia, &lower_ia);
|
||||
if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
|
||||
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
|
@ -978,6 +992,16 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
|
|||
}
|
||||
}
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
|
||||
rc = inode_change_ok(inode, ia);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (ia->ia_valid & ATTR_SIZE) {
|
||||
rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
rc = filemap_write_and_wait(inode->i_mapping);
|
||||
if (rc)
|
||||
|
|
|
@ -109,7 +109,7 @@ int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
|
|||
(*size) += ((unsigned char)(data[1]) + 192);
|
||||
(*length_size) = 2;
|
||||
} else if (data[0] == 255) {
|
||||
/* Five-byte length; we're not supposed to see this */
|
||||
/* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
|
||||
ecryptfs_printk(KERN_ERR, "Five-byte packet length not "
|
||||
"supported\n");
|
||||
rc = -EINVAL;
|
||||
|
@ -126,7 +126,7 @@ out:
|
|||
/**
|
||||
* ecryptfs_write_packet_length
|
||||
* @dest: The byte array target into which to write the length. Must
|
||||
* have at least 5 bytes allocated.
|
||||
* have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated.
|
||||
* @size: The length to write.
|
||||
* @packet_size_length: The number of bytes used to encode the packet
|
||||
* length is written to this address.
|
||||
|
@ -146,6 +146,7 @@ int ecryptfs_write_packet_length(char *dest, size_t size,
|
|||
dest[1] = ((size - 192) % 256);
|
||||
(*packet_size_length) = 2;
|
||||
} else {
|
||||
/* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
|
||||
rc = -EINVAL;
|
||||
ecryptfs_printk(KERN_WARNING,
|
||||
"Unsupported packet size: [%zd]\n", size);
|
||||
|
|
|
@ -218,6 +218,29 @@ out_unlock:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* miscdevfs packet format:
|
||||
* Octet 0: Type
|
||||
* Octets 1-4: network byte order msg_ctx->counter
|
||||
* Octets 5-N0: Size of struct ecryptfs_message to follow
|
||||
* Octets N0-N1: struct ecryptfs_message (including data)
|
||||
*
|
||||
* Octets 5-N1 not written if the packet type does not include a message
|
||||
*/
|
||||
#define PKT_TYPE_SIZE 1
|
||||
#define PKT_CTR_SIZE 4
|
||||
#define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE)
|
||||
#define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
|
||||
+ ECRYPTFS_MIN_PKT_LEN_SIZE)
|
||||
/* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */
|
||||
#define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
|
||||
+ ECRYPTFS_MAX_PKT_LEN_SIZE \
|
||||
+ sizeof(struct ecryptfs_message) \
|
||||
+ 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)
|
||||
#define PKT_TYPE_OFFSET 0
|
||||
#define PKT_CTR_OFFSET PKT_TYPE_SIZE
|
||||
#define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE)
|
||||
|
||||
/**
|
||||
* ecryptfs_miscdev_read - format and send message from queue
|
||||
* @file: fs/ecryptfs/euid miscdevfs handle (ignored)
|
||||
|
@ -237,7 +260,7 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
|
|||
struct ecryptfs_daemon *daemon;
|
||||
struct ecryptfs_msg_ctx *msg_ctx;
|
||||
size_t packet_length_size;
|
||||
char packet_length[3];
|
||||
char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE];
|
||||
size_t i;
|
||||
size_t total_length;
|
||||
uid_t euid = current_euid();
|
||||
|
@ -305,15 +328,8 @@ check_list:
|
|||
packet_length_size = 0;
|
||||
msg_ctx->msg_size = 0;
|
||||
}
|
||||
/* miscdevfs packet format:
|
||||
* Octet 0: Type
|
||||
* Octets 1-4: network byte order msg_ctx->counter
|
||||
* Octets 5-N0: Size of struct ecryptfs_message to follow
|
||||
* Octets N0-N1: struct ecryptfs_message (including data)
|
||||
*
|
||||
* Octets 5-N1 not written if the packet type does not
|
||||
* include a message */
|
||||
total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size);
|
||||
total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size
|
||||
+ msg_ctx->msg_size);
|
||||
if (count < total_length) {
|
||||
rc = 0;
|
||||
printk(KERN_WARNING "%s: Only given user buffer of "
|
||||
|
@ -324,9 +340,10 @@ check_list:
|
|||
rc = -EFAULT;
|
||||
if (put_user(msg_ctx->type, buf))
|
||||
goto out_unlock_msg_ctx;
|
||||
if (put_user(cpu_to_be32(msg_ctx->counter), (__be32 __user *)(buf + 1)))
|
||||
if (put_user(cpu_to_be32(msg_ctx->counter),
|
||||
(__be32 __user *)(&buf[PKT_CTR_OFFSET])))
|
||||
goto out_unlock_msg_ctx;
|
||||
i = 5;
|
||||
i = PKT_TYPE_SIZE + PKT_CTR_SIZE;
|
||||
if (msg_ctx->msg) {
|
||||
if (copy_to_user(&buf[i], packet_length, packet_length_size))
|
||||
goto out_unlock_msg_ctx;
|
||||
|
@ -391,12 +408,6 @@ out:
|
|||
* @count: Amount of data in @buf
|
||||
* @ppos: Pointer to offset in file (ignored)
|
||||
*
|
||||
* miscdevfs packet format:
|
||||
* Octet 0: Type
|
||||
* Octets 1-4: network byte order msg_ctx->counter (0's for non-response)
|
||||
* Octets 5-N0: Size of struct ecryptfs_message to follow
|
||||
* Octets N0-N1: struct ecryptfs_message (including data)
|
||||
*
|
||||
* Returns the number of bytes read from @buf
|
||||
*/
|
||||
static ssize_t
|
||||
|
@ -405,60 +416,78 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
|
|||
{
|
||||
__be32 counter_nbo;
|
||||
u32 seq;
|
||||
size_t packet_size, packet_size_length, i;
|
||||
ssize_t sz = 0;
|
||||
size_t packet_size, packet_size_length;
|
||||
char *data;
|
||||
uid_t euid = current_euid();
|
||||
int rc;
|
||||
unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE];
|
||||
ssize_t rc;
|
||||
|
||||
if (count == 0)
|
||||
goto out;
|
||||
if (count == 0) {
|
||||
return 0;
|
||||
} else if (count == MIN_NON_MSG_PKT_SIZE) {
|
||||
/* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
|
||||
goto memdup;
|
||||
} else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) {
|
||||
printk(KERN_WARNING "%s: Acceptable packet size range is "
|
||||
"[%d-%lu], but amount of data written is [%zu].",
|
||||
__func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET],
|
||||
sizeof(packet_size_peek))) {
|
||||
printk(KERN_WARNING "%s: Error while inspecting packet size\n",
|
||||
__func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
|
||||
&packet_size_length);
|
||||
if (rc) {
|
||||
printk(KERN_WARNING "%s: Error parsing packet length; "
|
||||
"rc = [%zd]\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size)
|
||||
!= count) {
|
||||
printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
|
||||
packet_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memdup:
|
||||
data = memdup_user(buf, count);
|
||||
if (IS_ERR(data)) {
|
||||
printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
|
||||
__func__, PTR_ERR(data));
|
||||
goto out;
|
||||
return PTR_ERR(data);
|
||||
}
|
||||
sz = count;
|
||||
i = 0;
|
||||
switch (data[i++]) {
|
||||
switch (data[PKT_TYPE_OFFSET]) {
|
||||
case ECRYPTFS_MSG_RESPONSE:
|
||||
if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) {
|
||||
if (count < (MIN_MSG_PKT_SIZE
|
||||
+ sizeof(struct ecryptfs_message))) {
|
||||
printk(KERN_WARNING "%s: Minimum acceptable packet "
|
||||
"size is [%zd], but amount of data written is "
|
||||
"only [%zd]. Discarding response packet.\n",
|
||||
__func__,
|
||||
(1 + 4 + 1 + sizeof(struct ecryptfs_message)),
|
||||
count);
|
||||
(MIN_MSG_PKT_SIZE
|
||||
+ sizeof(struct ecryptfs_message)), count);
|
||||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
memcpy(&counter_nbo, &data[i], 4);
|
||||
memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE);
|
||||
seq = be32_to_cpu(counter_nbo);
|
||||
i += 4;
|
||||
rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
|
||||
&packet_size_length);
|
||||
rc = ecryptfs_miscdev_response(
|
||||
&data[PKT_LEN_OFFSET + packet_size_length],
|
||||
packet_size, euid, current_user_ns(),
|
||||
task_pid(current), seq);
|
||||
if (rc) {
|
||||
printk(KERN_WARNING "%s: Error parsing packet length; "
|
||||
"rc = [%d]\n", __func__, rc);
|
||||
goto out_free;
|
||||
}
|
||||
i += packet_size_length;
|
||||
if ((1 + 4 + packet_size_length + packet_size) != count) {
|
||||
printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
|
||||
" + packet_size([%zd]))([%zd]) != "
|
||||
"count([%zd]). Invalid packet format.\n",
|
||||
__func__, packet_size_length, packet_size,
|
||||
(1 + packet_size_length + packet_size), count);
|
||||
goto out_free;
|
||||
}
|
||||
rc = ecryptfs_miscdev_response(&data[i], packet_size,
|
||||
euid, current_user_ns(),
|
||||
task_pid(current), seq);
|
||||
if (rc)
|
||||
printk(KERN_WARNING "%s: Failed to deliver miscdev "
|
||||
"response to requesting operation; rc = [%d]\n",
|
||||
"response to requesting operation; rc = [%zd]\n",
|
||||
__func__, rc);
|
||||
goto out_free;
|
||||
}
|
||||
break;
|
||||
case ECRYPTFS_MSG_HELO:
|
||||
case ECRYPTFS_MSG_QUIT:
|
||||
|
@ -467,12 +496,13 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
|
|||
ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
|
||||
"message of unrecognized type [%d]\n",
|
||||
data[0]);
|
||||
break;
|
||||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
rc = count;
|
||||
out_free:
|
||||
kfree(data);
|
||||
out:
|
||||
return sz;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -130,13 +130,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
|||
pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
|
||||
size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
|
||||
size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
|
||||
size_t total_remaining_bytes = ((offset + size) - pos);
|
||||
loff_t total_remaining_bytes = ((offset + size) - pos);
|
||||
|
||||
if (fatal_signal_pending(current)) {
|
||||
rc = -EINTR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (num_bytes > total_remaining_bytes)
|
||||
num_bytes = total_remaining_bytes;
|
||||
if (pos < offset) {
|
||||
/* remaining zeros to write, up to destination offset */
|
||||
size_t total_remaining_zeros = (offset - pos);
|
||||
loff_t total_remaining_zeros = (offset - pos);
|
||||
|
||||
if (num_bytes > total_remaining_zeros)
|
||||
num_bytes = total_remaining_zeros;
|
||||
|
@ -193,15 +198,19 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
|||
}
|
||||
pos += num_bytes;
|
||||
}
|
||||
if ((offset + size) > ecryptfs_file_size) {
|
||||
i_size_write(ecryptfs_inode, (offset + size));
|
||||
if (pos > ecryptfs_file_size) {
|
||||
i_size_write(ecryptfs_inode, pos);
|
||||
if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
|
||||
rc = ecryptfs_write_inode_size_to_metadata(
|
||||
int rc2;
|
||||
|
||||
rc2 = ecryptfs_write_inode_size_to_metadata(
|
||||
ecryptfs_inode);
|
||||
if (rc) {
|
||||
if (rc2) {
|
||||
printk(KERN_ERR "Problem with "
|
||||
"ecryptfs_write_inode_size_to_metadata; "
|
||||
"rc = [%d]\n", rc);
|
||||
"rc = [%d]\n", rc2);
|
||||
if (!rc)
|
||||
rc = rc2;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -273,76 +282,3 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
|
|||
flush_dcache_page(page_for_ecryptfs);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* ecryptfs_read
|
||||
* @data: The virtual address into which to write the data read (and
|
||||
* possibly decrypted) from the lower file
|
||||
* @offset: The offset in the decrypted view of the file from which to
|
||||
* read into @data
|
||||
* @size: The number of bytes to read into @data
|
||||
* @ecryptfs_file: The eCryptfs file from which to read
|
||||
*
|
||||
* Read an arbitrary amount of data from an arbitrary location in the
|
||||
* eCryptfs page cache. This is done on an extent-by-extent basis;
|
||||
* individual extents are decrypted and read from the lower page
|
||||
* cache (via VFS reads). This function takes care of all the
|
||||
* address translation to locations in the lower filesystem.
|
||||
*
|
||||
* Returns zero on success; non-zero otherwise
|
||||
*/
|
||||
int ecryptfs_read(char *data, loff_t offset, size_t size,
|
||||
struct file *ecryptfs_file)
|
||||
{
|
||||
struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode;
|
||||
struct page *ecryptfs_page;
|
||||
char *ecryptfs_page_virt;
|
||||
loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode);
|
||||
loff_t data_offset = 0;
|
||||
loff_t pos;
|
||||
int rc = 0;
|
||||
|
||||
if ((offset + size) > ecryptfs_file_size) {
|
||||
rc = -EINVAL;
|
||||
printk(KERN_ERR "%s: Attempt to read data past the end of the "
|
||||
"file; offset = [%lld]; size = [%td]; "
|
||||
"ecryptfs_file_size = [%lld]\n",
|
||||
__func__, offset, size, ecryptfs_file_size);
|
||||
goto out;
|
||||
}
|
||||
pos = offset;
|
||||
while (pos < (offset + size)) {
|
||||
pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
|
||||
size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
|
||||
size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
|
||||
size_t total_remaining_bytes = ((offset + size) - pos);
|
||||
|
||||
if (num_bytes > total_remaining_bytes)
|
||||
num_bytes = total_remaining_bytes;
|
||||
ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode,
|
||||
ecryptfs_page_idx);
|
||||
if (IS_ERR(ecryptfs_page)) {
|
||||
rc = PTR_ERR(ecryptfs_page);
|
||||
printk(KERN_ERR "%s: Error getting page at "
|
||||
"index [%ld] from eCryptfs inode "
|
||||
"mapping; rc = [%d]\n", __func__,
|
||||
ecryptfs_page_idx, rc);
|
||||
goto out;
|
||||
}
|
||||
ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
|
||||
memcpy((data + data_offset),
|
||||
((char *)ecryptfs_page_virt + start_offset_in_page),
|
||||
num_bytes);
|
||||
kunmap_atomic(ecryptfs_page_virt, KM_USER0);
|
||||
flush_dcache_page(ecryptfs_page);
|
||||
SetPageUptodate(ecryptfs_page);
|
||||
unlock_page(ecryptfs_page);
|
||||
page_cache_release(ecryptfs_page);
|
||||
pos += num_bytes;
|
||||
data_offset += num_bytes;
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче