mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
eCryptfs: Propagate vfs_read and vfs_write return codes
Errors returned from vfs_read() and vfs_write() calls to the lower filesystem were being masked as -EINVAL. This caused some confusion to users who saw EINVAL instead of ENOSPC when the disk was full, for instance. Also, the actual bytes read or written were not accessible by callers to ecryptfs_read_lower() and ecryptfs_write_lower(), which may be useful in some cases. This patch updates the error handling logic where those functions are called in order to accept positive return codes indicating success. Cc: Eric Sandeen <esandeen@redhat.com> Acked-by: Serge Hallyn <serue@us.ibm.com> Cc: ecryptfs-devel@lists.launchpad.net Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
This commit is contained in:
parent
3891959846
commit
96a7b9c2f5
3 changed files with 26 additions and 29 deletions
|
@ -509,13 +509,14 @@ int ecryptfs_encrypt_page(struct page *page)
|
||||||
+ extent_offset), crypt_stat);
|
+ extent_offset), crypt_stat);
|
||||||
rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,
|
rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,
|
||||||
offset, crypt_stat->extent_size);
|
offset, crypt_stat->extent_size);
|
||||||
if (rc) {
|
if (rc < 0) {
|
||||||
ecryptfs_printk(KERN_ERR, "Error attempting "
|
ecryptfs_printk(KERN_ERR, "Error attempting "
|
||||||
"to write lower page; rc = [%d]"
|
"to write lower page; rc = [%d]"
|
||||||
"\n", rc);
|
"\n", rc);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
if (enc_extent_page) {
|
if (enc_extent_page) {
|
||||||
kunmap(enc_extent_page);
|
kunmap(enc_extent_page);
|
||||||
|
@ -631,7 +632,7 @@ int ecryptfs_decrypt_page(struct page *page)
|
||||||
rc = ecryptfs_read_lower(enc_extent_virt, offset,
|
rc = ecryptfs_read_lower(enc_extent_virt, offset,
|
||||||
crypt_stat->extent_size,
|
crypt_stat->extent_size,
|
||||||
ecryptfs_inode);
|
ecryptfs_inode);
|
||||||
if (rc) {
|
if (rc < 0) {
|
||||||
ecryptfs_printk(KERN_ERR, "Error attempting "
|
ecryptfs_printk(KERN_ERR, "Error attempting "
|
||||||
"to read lower page; rc = [%d]"
|
"to read lower page; rc = [%d]"
|
||||||
"\n", rc);
|
"\n", rc);
|
||||||
|
@ -1213,14 +1214,15 @@ int ecryptfs_read_and_validate_header_region(char *data,
|
||||||
crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;
|
crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;
|
||||||
rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size,
|
rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size,
|
||||||
ecryptfs_inode);
|
ecryptfs_inode);
|
||||||
if (rc) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n",
|
printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
|
if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
}
|
} else
|
||||||
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1315,10 +1317,11 @@ ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry,
|
||||||
|
|
||||||
rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
|
rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
|
||||||
0, virt_len);
|
0, virt_len);
|
||||||
if (rc)
|
if (rc < 0)
|
||||||
printk(KERN_ERR "%s: Error attempting to write header "
|
printk(KERN_ERR "%s: Error attempting to write header "
|
||||||
"information to lower file; rc = [%d]\n", __func__,
|
"information to lower file; rc = [%d]\n", __func__, rc);
|
||||||
rc);
|
else
|
||||||
|
rc = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1598,7 +1601,7 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
||||||
}
|
}
|
||||||
rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size,
|
rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size,
|
||||||
ecryptfs_inode);
|
ecryptfs_inode);
|
||||||
if (!rc)
|
if (rc >= 0)
|
||||||
rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
|
rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
|
||||||
ecryptfs_dentry,
|
ecryptfs_dentry,
|
||||||
ECRYPTFS_VALIDATE_HEADER_SIZE);
|
ECRYPTFS_VALIDATE_HEADER_SIZE);
|
||||||
|
|
|
@ -396,9 +396,11 @@ static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
|
||||||
rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
|
rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
|
||||||
sizeof(u64));
|
sizeof(u64));
|
||||||
kfree(file_size_virt);
|
kfree(file_size_virt);
|
||||||
if (rc)
|
if (rc < 0)
|
||||||
printk(KERN_ERR "%s: Error writing file size to header; "
|
printk(KERN_ERR "%s: Error writing file size to header; "
|
||||||
"rc = [%d]\n", __func__, rc);
|
"rc = [%d]\n", __func__, rc);
|
||||||
|
else
|
||||||
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,15 +34,14 @@
|
||||||
*
|
*
|
||||||
* Write data to the lower file.
|
* Write data to the lower file.
|
||||||
*
|
*
|
||||||
* Returns zero on success; non-zero on error
|
* Returns bytes written on success; less than zero on error
|
||||||
*/
|
*/
|
||||||
int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
|
int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
|
||||||
loff_t offset, size_t size)
|
loff_t offset, size_t size)
|
||||||
{
|
{
|
||||||
struct ecryptfs_inode_info *inode_info;
|
struct ecryptfs_inode_info *inode_info;
|
||||||
ssize_t octets_written;
|
|
||||||
mm_segment_t fs_save;
|
mm_segment_t fs_save;
|
||||||
int rc = 0;
|
ssize_t rc;
|
||||||
|
|
||||||
inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
|
inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
|
||||||
mutex_lock(&inode_info->lower_file_mutex);
|
mutex_lock(&inode_info->lower_file_mutex);
|
||||||
|
@ -50,14 +49,9 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
|
||||||
inode_info->lower_file->f_pos = offset;
|
inode_info->lower_file->f_pos = offset;
|
||||||
fs_save = get_fs();
|
fs_save = get_fs();
|
||||||
set_fs(get_ds());
|
set_fs(get_ds());
|
||||||
octets_written = vfs_write(inode_info->lower_file, data, size,
|
rc = vfs_write(inode_info->lower_file, data, size,
|
||||||
&inode_info->lower_file->f_pos);
|
&inode_info->lower_file->f_pos);
|
||||||
set_fs(fs_save);
|
set_fs(fs_save);
|
||||||
if (octets_written < 0) {
|
|
||||||
printk(KERN_ERR "%s: octets_written = [%td]; "
|
|
||||||
"expected [%td]\n", __func__, octets_written, size);
|
|
||||||
rc = -EINVAL;
|
|
||||||
}
|
|
||||||
mutex_unlock(&inode_info->lower_file_mutex);
|
mutex_unlock(&inode_info->lower_file_mutex);
|
||||||
mark_inode_dirty_sync(ecryptfs_inode);
|
mark_inode_dirty_sync(ecryptfs_inode);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -91,6 +85,8 @@ int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
|
||||||
+ offset_in_page);
|
+ offset_in_page);
|
||||||
virt = kmap(page_for_lower);
|
virt = kmap(page_for_lower);
|
||||||
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
|
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
|
||||||
|
if (rc > 0)
|
||||||
|
rc = 0;
|
||||||
kunmap(page_for_lower);
|
kunmap(page_for_lower);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -229,30 +225,24 @@ out:
|
||||||
* Read @size bytes of data at byte offset @offset from the lower
|
* Read @size bytes of data at byte offset @offset from the lower
|
||||||
* inode into memory location @data.
|
* inode into memory location @data.
|
||||||
*
|
*
|
||||||
* Returns zero on success; non-zero on error
|
* Returns bytes read on success; 0 on EOF; less than zero on error
|
||||||
*/
|
*/
|
||||||
int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
|
int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
|
||||||
struct inode *ecryptfs_inode)
|
struct inode *ecryptfs_inode)
|
||||||
{
|
{
|
||||||
struct ecryptfs_inode_info *inode_info =
|
struct ecryptfs_inode_info *inode_info =
|
||||||
ecryptfs_inode_to_private(ecryptfs_inode);
|
ecryptfs_inode_to_private(ecryptfs_inode);
|
||||||
ssize_t octets_read;
|
|
||||||
mm_segment_t fs_save;
|
mm_segment_t fs_save;
|
||||||
int rc = 0;
|
ssize_t rc;
|
||||||
|
|
||||||
mutex_lock(&inode_info->lower_file_mutex);
|
mutex_lock(&inode_info->lower_file_mutex);
|
||||||
BUG_ON(!inode_info->lower_file);
|
BUG_ON(!inode_info->lower_file);
|
||||||
inode_info->lower_file->f_pos = offset;
|
inode_info->lower_file->f_pos = offset;
|
||||||
fs_save = get_fs();
|
fs_save = get_fs();
|
||||||
set_fs(get_ds());
|
set_fs(get_ds());
|
||||||
octets_read = vfs_read(inode_info->lower_file, data, size,
|
rc = vfs_read(inode_info->lower_file, data, size,
|
||||||
&inode_info->lower_file->f_pos);
|
&inode_info->lower_file->f_pos);
|
||||||
set_fs(fs_save);
|
set_fs(fs_save);
|
||||||
if (octets_read < 0) {
|
|
||||||
printk(KERN_ERR "%s: octets_read = [%td]; "
|
|
||||||
"expected [%td]\n", __func__, octets_read, size);
|
|
||||||
rc = -EINVAL;
|
|
||||||
}
|
|
||||||
mutex_unlock(&inode_info->lower_file_mutex);
|
mutex_unlock(&inode_info->lower_file_mutex);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -284,6 +274,8 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
|
||||||
offset = ((((loff_t)page_index) << PAGE_CACHE_SHIFT) + offset_in_page);
|
offset = ((((loff_t)page_index) << PAGE_CACHE_SHIFT) + offset_in_page);
|
||||||
virt = kmap(page_for_ecryptfs);
|
virt = kmap(page_for_ecryptfs);
|
||||||
rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode);
|
rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode);
|
||||||
|
if (rc > 0)
|
||||||
|
rc = 0;
|
||||||
kunmap(page_for_ecryptfs);
|
kunmap(page_for_ecryptfs);
|
||||||
flush_dcache_page(page_for_ecryptfs);
|
flush_dcache_page(page_for_ecryptfs);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
Loading…
Reference in a new issue