Commit bd8f0a46 authored by Tyler Hicks's avatar Tyler Hicks Committed by Greg Kroah-Hartman

eCryptfs: Make truncate path killable

commit 5e6f0d76 upstream.

ecryptfs_write() handles the truncation of eCryptfs inodes. It grabs a
page, zeroes out the appropriate portions, and then encrypts the page
before writing it to the lower filesystem. It was unkillable and due to
the lack of sparse file support could result in tying up a large portion
of system resources, while encrypting pages of zeros, with no way for
the truncate operation to be stopped from userspace.

This patch adds the ability for ecryptfs_write() to detect a pending
fatal signal and return as gracefully as possible. The intent is to
leave the lower file in a useable state, while still allowing a user to
break out of the encryption loop. If a pending fatal signal is detected,
the eCryptfs inode size is updated to reflect the modified inode size
and then -EINTR is returned.
Signed-off-by: default avatarTyler Hicks <tyhicks@canonical.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7727d2c0
...@@ -136,6 +136,11 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset, ...@@ -136,6 +136,11 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
size_t total_remaining_bytes = ((offset + size) - pos); size_t total_remaining_bytes = ((offset + size) - pos);
if (fatal_signal_pending(current)) {
rc = -EINTR;
break;
}
if (num_bytes > total_remaining_bytes) if (num_bytes > total_remaining_bytes)
num_bytes = total_remaining_bytes; num_bytes = total_remaining_bytes;
if (pos < offset) { if (pos < offset) {
...@@ -197,15 +202,19 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset, ...@@ -197,15 +202,19 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
} }
pos += num_bytes; pos += num_bytes;
} }
if ((offset + size) > ecryptfs_file_size) { if (pos > ecryptfs_file_size) {
i_size_write(ecryptfs_inode, (offset + size)); i_size_write(ecryptfs_inode, pos);
if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
rc = ecryptfs_write_inode_size_to_metadata( int rc2;
rc2 = ecryptfs_write_inode_size_to_metadata(
ecryptfs_inode); ecryptfs_inode);
if (rc) { if (rc2) {
printk(KERN_ERR "Problem with " printk(KERN_ERR "Problem with "
"ecryptfs_write_inode_size_to_metadata; " "ecryptfs_write_inode_size_to_metadata; "
"rc = [%d]\n", rc); "rc = [%d]\n", rc2);
if (!rc)
rc = rc2;
goto out; goto out;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment