Commit 9b030e20 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6:
  eCryptfs: Turn lower lookup error messages into debug messages
  eCryptfs: Copy lower directory inode times and size on link
  ecryptfs: fix use with tmpfs by removing d_drop from ecryptfs_destroy_inode
  ecryptfs: fix error code for missing xattrs in lower fs
  eCryptfs: Decrypt symlink target for stat size
  eCryptfs: Strip metadata in xattr flag in encrypted view
  eCryptfs: Clear buffer before reading in metadata xattr
  eCryptfs: Rename ecryptfs_crypt_stat.num_header_bytes_at_front
  eCryptfs: Fix metadata in xattr feature regression
parents 76e506a7 9f37622f
...@@ -382,8 +382,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, ...@@ -382,8 +382,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num, static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
struct ecryptfs_crypt_stat *crypt_stat) struct ecryptfs_crypt_stat *crypt_stat)
{ {
(*offset) = (crypt_stat->num_header_bytes_at_front (*offset) = ecryptfs_lower_header_size(crypt_stat)
+ (crypt_stat->extent_size * extent_num)); + (crypt_stat->extent_size * extent_num);
} }
/** /**
...@@ -835,13 +835,13 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat) ...@@ -835,13 +835,13 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat)
set_extent_mask_and_shift(crypt_stat); set_extent_mask_and_shift(crypt_stat);
crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES; crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
crypt_stat->num_header_bytes_at_front = 0; crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
else { else {
if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)
crypt_stat->num_header_bytes_at_front = crypt_stat->metadata_size =
ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
else else
crypt_stat->num_header_bytes_at_front = PAGE_CACHE_SIZE; crypt_stat->metadata_size = PAGE_CACHE_SIZE;
} }
} }
...@@ -1108,9 +1108,9 @@ static void write_ecryptfs_marker(char *page_virt, size_t *written) ...@@ -1108,9 +1108,9 @@ static void write_ecryptfs_marker(char *page_virt, size_t *written)
(*written) = MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; (*written) = MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
} }
static void void ecryptfs_write_crypt_stat_flags(char *page_virt,
write_ecryptfs_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_crypt_stat *crypt_stat,
size_t *written) size_t *written)
{ {
u32 flags = 0; u32 flags = 0;
int i; int i;
...@@ -1238,8 +1238,7 @@ ecryptfs_write_header_metadata(char *virt, ...@@ -1238,8 +1238,7 @@ ecryptfs_write_header_metadata(char *virt,
header_extent_size = (u32)crypt_stat->extent_size; header_extent_size = (u32)crypt_stat->extent_size;
num_header_extents_at_front = num_header_extents_at_front =
(u16)(crypt_stat->num_header_bytes_at_front (u16)(crypt_stat->metadata_size / crypt_stat->extent_size);
/ crypt_stat->extent_size);
put_unaligned_be32(header_extent_size, virt); put_unaligned_be32(header_extent_size, virt);
virt += 4; virt += 4;
put_unaligned_be16(num_header_extents_at_front, virt); put_unaligned_be16(num_header_extents_at_front, virt);
...@@ -1292,7 +1291,8 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t max, ...@@ -1292,7 +1291,8 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t max,
offset = ECRYPTFS_FILE_SIZE_BYTES; offset = ECRYPTFS_FILE_SIZE_BYTES;
write_ecryptfs_marker((page_virt + offset), &written); write_ecryptfs_marker((page_virt + offset), &written);
offset += written; offset += written;
write_ecryptfs_flags((page_virt + offset), crypt_stat, &written); ecryptfs_write_crypt_stat_flags((page_virt + offset), crypt_stat,
&written);
offset += written; offset += written;
ecryptfs_write_header_metadata((page_virt + offset), crypt_stat, ecryptfs_write_header_metadata((page_virt + offset), crypt_stat,
&written); &written);
...@@ -1382,7 +1382,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) ...@@ -1382,7 +1382,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
virt_len = crypt_stat->num_header_bytes_at_front; virt_len = crypt_stat->metadata_size;
order = get_order(virt_len); order = get_order(virt_len);
/* Released in this function */ /* Released in this function */
virt = (char *)ecryptfs_get_zeroed_pages(GFP_KERNEL, order); virt = (char *)ecryptfs_get_zeroed_pages(GFP_KERNEL, order);
...@@ -1428,16 +1428,15 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, ...@@ -1428,16 +1428,15 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
header_extent_size = get_unaligned_be32(virt); header_extent_size = get_unaligned_be32(virt);
virt += sizeof(__be32); virt += sizeof(__be32);
num_header_extents_at_front = get_unaligned_be16(virt); num_header_extents_at_front = get_unaligned_be16(virt);
crypt_stat->num_header_bytes_at_front = crypt_stat->metadata_size = (((size_t)num_header_extents_at_front
(((size_t)num_header_extents_at_front * (size_t)header_extent_size));
* (size_t)header_extent_size));
(*bytes_read) = (sizeof(__be32) + sizeof(__be16)); (*bytes_read) = (sizeof(__be32) + sizeof(__be16));
if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE) if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
&& (crypt_stat->num_header_bytes_at_front && (crypt_stat->metadata_size
< ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) { < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
rc = -EINVAL; rc = -EINVAL;
printk(KERN_WARNING "Invalid header size: [%zd]\n", printk(KERN_WARNING "Invalid header size: [%zd]\n",
crypt_stat->num_header_bytes_at_front); crypt_stat->metadata_size);
} }
return rc; return rc;
} }
...@@ -1452,8 +1451,7 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, ...@@ -1452,8 +1451,7 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
*/ */
static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
{ {
crypt_stat->num_header_bytes_at_front = crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
} }
/** /**
...@@ -1607,6 +1605,7 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) ...@@ -1607,6 +1605,7 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
ecryptfs_dentry, ecryptfs_dentry,
ECRYPTFS_VALIDATE_HEADER_SIZE); ECRYPTFS_VALIDATE_HEADER_SIZE);
if (rc) { if (rc) {
memset(page_virt, 0, PAGE_CACHE_SIZE);
rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode); rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode);
if (rc) { if (rc) {
printk(KERN_DEBUG "Valid eCryptfs headers not found in " printk(KERN_DEBUG "Valid eCryptfs headers not found in "
......
...@@ -273,7 +273,7 @@ struct ecryptfs_crypt_stat { ...@@ -273,7 +273,7 @@ struct ecryptfs_crypt_stat {
u32 flags; u32 flags;
unsigned int file_version; unsigned int file_version;
size_t iv_bytes; size_t iv_bytes;
size_t num_header_bytes_at_front; size_t metadata_size;
size_t extent_size; /* Data extent size; default is 4096 */ size_t extent_size; /* Data extent size; default is 4096 */
size_t key_size; size_t key_size;
size_t extent_shift; size_t extent_shift;
...@@ -464,6 +464,14 @@ struct ecryptfs_daemon { ...@@ -464,6 +464,14 @@ struct ecryptfs_daemon {
extern struct mutex ecryptfs_daemon_hash_mux; extern struct mutex ecryptfs_daemon_hash_mux;
static inline size_t
ecryptfs_lower_header_size(struct ecryptfs_crypt_stat *crypt_stat)
{
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
return 0;
return crypt_stat->metadata_size;
}
static inline struct ecryptfs_file_info * static inline struct ecryptfs_file_info *
ecryptfs_file_to_private(struct file *file) ecryptfs_file_to_private(struct file *file)
{ {
...@@ -651,6 +659,9 @@ int ecryptfs_decrypt_page(struct page *page); ...@@ -651,6 +659,9 @@ int ecryptfs_decrypt_page(struct page *page);
int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry); int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry);
int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry); int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry);
int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry); int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry);
void ecryptfs_write_crypt_stat_flags(char *page_virt,
struct ecryptfs_crypt_stat *crypt_stat,
size_t *written);
int ecryptfs_read_and_validate_header_region(char *data, int ecryptfs_read_and_validate_header_region(char *data,
struct inode *ecryptfs_inode); struct inode *ecryptfs_inode);
int ecryptfs_read_and_validate_xattr_region(char *page_virt, int ecryptfs_read_and_validate_xattr_region(char *page_virt,
......
...@@ -324,6 +324,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, ...@@ -324,6 +324,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
rc = ecryptfs_read_and_validate_header_region(page_virt, rc = ecryptfs_read_and_validate_header_region(page_virt,
ecryptfs_dentry->d_inode); ecryptfs_dentry->d_inode);
if (rc) { if (rc) {
memset(page_virt, 0, PAGE_CACHE_SIZE);
rc = ecryptfs_read_and_validate_xattr_region(page_virt, rc = ecryptfs_read_and_validate_xattr_region(page_virt,
ecryptfs_dentry); ecryptfs_dentry);
if (rc) { if (rc) {
...@@ -336,7 +337,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, ...@@ -336,7 +337,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
ecryptfs_dentry->d_sb)->mount_crypt_stat; ecryptfs_dentry->d_sb)->mount_crypt_stat;
if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
file_size = (crypt_stat->num_header_bytes_at_front file_size = (crypt_stat->metadata_size
+ i_size_read(lower_dentry->d_inode)); + i_size_read(lower_dentry->d_inode));
else else
file_size = i_size_read(lower_dentry->d_inode); file_size = i_size_read(lower_dentry->d_inode);
...@@ -388,9 +389,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, ...@@ -388,9 +389,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
if (IS_ERR(lower_dentry)) { if (IS_ERR(lower_dentry)) {
rc = PTR_ERR(lower_dentry); rc = PTR_ERR(lower_dentry);
printk(KERN_ERR "%s: lookup_one_len() returned [%d] on " ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
"lower_dentry = [%s]\n", __func__, rc, "[%d] on lower_dentry = [%s]\n", __func__, rc,
ecryptfs_dentry->d_name.name); encrypted_and_encoded_name);
goto out_d_drop; goto out_d_drop;
} }
if (lower_dentry->d_inode) if (lower_dentry->d_inode)
...@@ -417,9 +418,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, ...@@ -417,9 +418,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
if (IS_ERR(lower_dentry)) { if (IS_ERR(lower_dentry)) {
rc = PTR_ERR(lower_dentry); rc = PTR_ERR(lower_dentry);
printk(KERN_ERR "%s: lookup_one_len() returned [%d] on " ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
"lower_dentry = [%s]\n", __func__, rc, "[%d] on lower_dentry = [%s]\n", __func__, rc,
encrypted_and_encoded_name); encrypted_and_encoded_name);
goto out_d_drop; goto out_d_drop;
} }
lookup_and_interpose: lookup_and_interpose:
...@@ -456,8 +457,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -456,8 +457,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0); rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
if (rc) if (rc)
goto out_lock; goto out_lock;
fsstack_copy_attr_times(dir, lower_new_dentry->d_inode); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
fsstack_copy_inode_size(dir, lower_new_dentry->d_inode); fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
old_dentry->d_inode->i_nlink = old_dentry->d_inode->i_nlink =
ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink; ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink;
i_size_write(new_dentry->d_inode, file_size_save); i_size_write(new_dentry->d_inode, file_size_save);
...@@ -648,38 +649,17 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -648,38 +649,17 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return rc; return rc;
} }
static int static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) size_t *bufsiz)
{ {
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
char *lower_buf; char *lower_buf;
size_t lower_bufsiz; size_t lower_bufsiz = PATH_MAX;
struct dentry *lower_dentry;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
char *plaintext_name;
size_t plaintext_name_size;
mm_segment_t old_fs; mm_segment_t old_fs;
int rc; int rc;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
if (!lower_dentry->d_inode->i_op->readlink) {
rc = -EINVAL;
goto out;
}
mount_crypt_stat = &ecryptfs_superblock_to_private(
dentry->d_sb)->mount_crypt_stat;
/*
* If the lower filename is encrypted, it will result in a significantly
* longer name. If needed, truncate the name after decode and decrypt.
*/
if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
lower_bufsiz = PATH_MAX;
else
lower_bufsiz = bufsiz;
/* Released in this function */
lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
if (lower_buf == NULL) { if (!lower_buf) {
printk(KERN_ERR "%s: Out of memory whilst attempting to "
"kmalloc [%zd] bytes\n", __func__, lower_bufsiz);
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
} }
...@@ -689,29 +669,31 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) ...@@ -689,29 +669,31 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
(char __user *)lower_buf, (char __user *)lower_buf,
lower_bufsiz); lower_bufsiz);
set_fs(old_fs); set_fs(old_fs);
if (rc >= 0) { if (rc < 0)
rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, goto out;
&plaintext_name_size, lower_bufsiz = rc;
dentry, lower_buf, rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry,
rc); lower_buf, lower_bufsiz);
if (rc) { out:
printk(KERN_ERR "%s: Error attempting to decode and "
"decrypt filename; rc = [%d]\n", __func__,
rc);
goto out_free_lower_buf;
}
/* Check for bufsiz <= 0 done in sys_readlinkat() */
rc = copy_to_user(buf, plaintext_name,
min((size_t) bufsiz, plaintext_name_size));
if (rc)
rc = -EFAULT;
else
rc = plaintext_name_size;
kfree(plaintext_name);
fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);
}
out_free_lower_buf:
kfree(lower_buf); kfree(lower_buf);
return rc;
}
static int
ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
{
char *kbuf;
size_t kbufsiz, copied;
int rc;
rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz);
if (rc)
goto out;
copied = min_t(size_t, bufsiz, kbufsiz);
rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied;
kfree(kbuf);
fsstack_copy_attr_atime(dentry->d_inode,
ecryptfs_dentry_to_lower(dentry)->d_inode);
out: out:
return rc; return rc;
} }
...@@ -769,7 +751,7 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat, ...@@ -769,7 +751,7 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat,
{ {
loff_t lower_size; loff_t lower_size;
lower_size = crypt_stat->num_header_bytes_at_front; lower_size = ecryptfs_lower_header_size(crypt_stat);
if (upper_size != 0) { if (upper_size != 0) {
loff_t num_extents; loff_t num_extents;
...@@ -1016,6 +998,28 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) ...@@ -1016,6 +998,28 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
return rc; return rc;
} }
int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
int rc = 0;
mount_crypt_stat = &ecryptfs_superblock_to_private(
dentry->d_sb)->mount_crypt_stat;
generic_fillattr(dentry->d_inode, stat);
if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
char *target;
size_t targetsiz;
rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz);
if (!rc) {
kfree(target);
stat->size = targetsiz;
}
}
return rc;
}
int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat) struct kstat *stat)
{ {
...@@ -1040,7 +1044,7 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, ...@@ -1040,7 +1044,7 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
lower_dentry = ecryptfs_dentry_to_lower(dentry); lower_dentry = ecryptfs_dentry_to_lower(dentry);
if (!lower_dentry->d_inode->i_op->setxattr) { if (!lower_dentry->d_inode->i_op->setxattr) {
rc = -ENOSYS; rc = -EOPNOTSUPP;
goto out; goto out;
} }
mutex_lock(&lower_dentry->d_inode->i_mutex); mutex_lock(&lower_dentry->d_inode->i_mutex);
...@@ -1058,7 +1062,7 @@ ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name, ...@@ -1058,7 +1062,7 @@ ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name,
int rc = 0; int rc = 0;
if (!lower_dentry->d_inode->i_op->getxattr) { if (!lower_dentry->d_inode->i_op->getxattr) {
rc = -ENOSYS; rc = -EOPNOTSUPP;
goto out; goto out;
} }
mutex_lock(&lower_dentry->d_inode->i_mutex); mutex_lock(&lower_dentry->d_inode->i_mutex);
...@@ -1085,7 +1089,7 @@ ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size) ...@@ -1085,7 +1089,7 @@ ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size)
lower_dentry = ecryptfs_dentry_to_lower(dentry); lower_dentry = ecryptfs_dentry_to_lower(dentry);
if (!lower_dentry->d_inode->i_op->listxattr) { if (!lower_dentry->d_inode->i_op->listxattr) {
rc = -ENOSYS; rc = -EOPNOTSUPP;
goto out; goto out;
} }
mutex_lock(&lower_dentry->d_inode->i_mutex); mutex_lock(&lower_dentry->d_inode->i_mutex);
...@@ -1102,7 +1106,7 @@ static int ecryptfs_removexattr(struct dentry *dentry, const char *name) ...@@ -1102,7 +1106,7 @@ static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
lower_dentry = ecryptfs_dentry_to_lower(dentry); lower_dentry = ecryptfs_dentry_to_lower(dentry);
if (!lower_dentry->d_inode->i_op->removexattr) { if (!lower_dentry->d_inode->i_op->removexattr) {
rc = -ENOSYS; rc = -EOPNOTSUPP;
goto out; goto out;
} }
mutex_lock(&lower_dentry->d_inode->i_mutex); mutex_lock(&lower_dentry->d_inode->i_mutex);
...@@ -1133,6 +1137,7 @@ const struct inode_operations ecryptfs_symlink_iops = { ...@@ -1133,6 +1137,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
.put_link = ecryptfs_put_link, .put_link = ecryptfs_put_link,
.permission = ecryptfs_permission, .permission = ecryptfs_permission,
.setattr = ecryptfs_setattr, .setattr = ecryptfs_setattr,
.getattr = ecryptfs_getattr_link,
.setxattr = ecryptfs_setxattr, .setxattr = ecryptfs_setxattr,
.getxattr = ecryptfs_getxattr, .getxattr = ecryptfs_getxattr,
.listxattr = ecryptfs_listxattr, .listxattr = ecryptfs_listxattr,
......
...@@ -83,6 +83,19 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) ...@@ -83,6 +83,19 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
return rc; return rc;
} }
static void strip_xattr_flag(char *page_virt,
struct ecryptfs_crypt_stat *crypt_stat)
{
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
size_t written;
crypt_stat->flags &= ~ECRYPTFS_METADATA_IN_XATTR;
ecryptfs_write_crypt_stat_flags(page_virt, crypt_stat,
&written);
crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
}
}
/** /**
* Header Extent: * Header Extent:
* Octets 0-7: Unencrypted file size (big-endian) * Octets 0-7: Unencrypted file size (big-endian)
...@@ -98,19 +111,6 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) ...@@ -98,19 +111,6 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
* (big-endian) * (big-endian)
* Octet 26: Begin RFC 2440 authentication token packet set * Octet 26: Begin RFC 2440 authentication token packet set
*/ */
static void set_header_info(char *page_virt,
struct ecryptfs_crypt_stat *crypt_stat)
{
size_t written;
size_t save_num_header_bytes_at_front =
crypt_stat->num_header_bytes_at_front;
crypt_stat->num_header_bytes_at_front =
ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written);
crypt_stat->num_header_bytes_at_front =
save_num_header_bytes_at_front;
}
/** /**
* ecryptfs_copy_up_encrypted_with_header * ecryptfs_copy_up_encrypted_with_header
...@@ -136,8 +136,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, ...@@ -136,8 +136,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
* num_extents_per_page) * num_extents_per_page)
+ extent_num_in_page); + extent_num_in_page);
size_t num_header_extents_at_front = size_t num_header_extents_at_front =
(crypt_stat->num_header_bytes_at_front (crypt_stat->metadata_size / crypt_stat->extent_size);
/ crypt_stat->extent_size);
if (view_extent_num < num_header_extents_at_front) { if (view_extent_num < num_header_extents_at_front) {
/* This is a header extent */ /* This is a header extent */
...@@ -147,9 +146,14 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, ...@@ -147,9 +146,14 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
memset(page_virt, 0, PAGE_CACHE_SIZE); memset(page_virt, 0, PAGE_CACHE_SIZE);
/* TODO: Support more than one header extent */ /* TODO: Support more than one header extent */
if (view_extent_num == 0) { if (view_extent_num == 0) {
size_t written;
rc = ecryptfs_read_xattr_region( rc = ecryptfs_read_xattr_region(
page_virt, page->mapping->host); page_virt, page->mapping->host);
set_header_info(page_virt, crypt_stat); strip_xattr_flag(page_virt + 16, crypt_stat);
ecryptfs_write_header_metadata(page_virt + 20,
crypt_stat,
&written);
} }
kunmap_atomic(page_virt, KM_USER0); kunmap_atomic(page_virt, KM_USER0);
flush_dcache_page(page); flush_dcache_page(page);
...@@ -162,7 +166,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, ...@@ -162,7 +166,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
/* This is an encrypted data extent */ /* This is an encrypted data extent */
loff_t lower_offset = loff_t lower_offset =
((view_extent_num * crypt_stat->extent_size) ((view_extent_num * crypt_stat->extent_size)
- crypt_stat->num_header_bytes_at_front); - crypt_stat->metadata_size);
rc = ecryptfs_read_lower_page_segment( rc = ecryptfs_read_lower_page_segment(
page, (lower_offset >> PAGE_CACHE_SHIFT), page, (lower_offset >> PAGE_CACHE_SHIFT),
......
...@@ -86,7 +86,6 @@ static void ecryptfs_destroy_inode(struct inode *inode) ...@@ -86,7 +86,6 @@ static void ecryptfs_destroy_inode(struct inode *inode)
if (lower_dentry->d_inode) { if (lower_dentry->d_inode) {
fput(inode_info->lower_file); fput(inode_info->lower_file);
inode_info->lower_file = NULL; inode_info->lower_file = NULL;
d_drop(lower_dentry);
} }
} }
ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
......
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