Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/ecryptfs/ecryptfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6:
  eCryptfs: Flush dirty pages in setattr
  eCryptfs: Handle failed metadata read in lookup
  eCryptfs: Add reference counting to lower files
  eCryptfs: dput dentries returned from dget_parent
  eCryptfs: Remove extra d_delete in ecryptfs_rmdir
  • Loading branch information
torvalds committed Apr 26, 2011
2 parents 71e9e6a + 5be79de commit cd2e49e
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 79 deletions.
21 changes: 21 additions & 0 deletions fs/ecryptfs/crypto.c
Expand Up @@ -1452,6 +1452,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
}

void ecryptfs_i_size_init(const char *page_virt, struct inode *inode)
{
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
struct ecryptfs_crypt_stat *crypt_stat;
u64 file_size;

crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
mount_crypt_stat =
&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
file_size = i_size_read(ecryptfs_inode_to_lower(inode));
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
file_size += crypt_stat->metadata_size;
} else
file_size = get_unaligned_be64(page_virt);
i_size_write(inode, (loff_t)file_size);
crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED;
}

/**
* ecryptfs_read_headers_virt
* @page_virt: The virtual address into which to read the headers
Expand Down Expand Up @@ -1482,6 +1501,8 @@ static int ecryptfs_read_headers_virt(char *page_virt,
rc = -EINVAL;
goto out;
}
if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED))
ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);
offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset),
&bytes_read);
Expand Down
7 changes: 6 additions & 1 deletion fs/ecryptfs/ecryptfs_kernel.h
Expand Up @@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat {
#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800
#define ECRYPTFS_ENCFN_USE_FEK 0x00001000
#define ECRYPTFS_UNLINK_SIGS 0x00002000
#define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000
u32 flags;
unsigned int file_version;
size_t iv_bytes;
Expand All @@ -295,6 +296,8 @@ struct ecryptfs_crypt_stat {
struct ecryptfs_inode_info {
struct inode vfs_inode;
struct inode *wii_inode;
struct mutex lower_file_mutex;
atomic_t lower_file_count;
struct file *lower_file;
struct ecryptfs_crypt_stat crypt_stat;
};
Expand Down Expand Up @@ -626,6 +629,7 @@ struct ecryptfs_open_req {
int ecryptfs_interpose(struct dentry *hidden_dentry,
struct dentry *this_dentry, struct super_block *sb,
u32 flags);
void ecryptfs_i_size_init(const char *page_virt, struct inode *inode);
int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
struct dentry *lower_dentry,
struct inode *ecryptfs_dir_inode);
Expand Down Expand Up @@ -757,7 +761,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
struct dentry *lower_dentry,
struct vfsmount *lower_mnt,
const struct cred *cred);
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry);
void ecryptfs_put_lower_file(struct inode *inode);
int
ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
size_t *packet_size,
Expand Down
25 changes: 12 additions & 13 deletions fs/ecryptfs/file.c
Expand Up @@ -191,20 +191,20 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
| ECRYPTFS_ENCRYPTED);
}
mutex_unlock(&crypt_stat->cs_mutex);
rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
rc = ecryptfs_get_lower_file(ecryptfs_dentry);
if (rc) {
printk(KERN_ERR "%s: Error attempting to initialize "
"the persistent file for the dentry with name "
"the lower file for the dentry with name "
"[%s]; rc = [%d]\n", __func__,
ecryptfs_dentry->d_name.name, rc);
goto out_free;
}
if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE)
== O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) {
rc = -EPERM;
printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
printk(KERN_WARNING "%s: Lower file is RO; eCryptfs "
"file must hence be opened RO\n", __func__);
goto out_free;
goto out_put;
}
ecryptfs_set_file_lower(
file, ecryptfs_inode_to_private(inode)->lower_file);
Expand Down Expand Up @@ -232,10 +232,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
"Plaintext passthrough mode is not "
"enabled; returning -EIO\n");
mutex_unlock(&crypt_stat->cs_mutex);
goto out_free;
goto out_put;
}
rc = 0;
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
| ECRYPTFS_ENCRYPTED);
mutex_unlock(&crypt_stat->cs_mutex);
goto out;
}
Expand All @@ -245,6 +246,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
"[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
(unsigned long long)i_size_read(inode));
goto out;
out_put:
ecryptfs_put_lower_file(inode);
out_free:
kmem_cache_free(ecryptfs_file_info_cache,
ecryptfs_file_to_private(file));
Expand All @@ -254,17 +257,13 @@ static int ecryptfs_open(struct inode *inode, struct file *file)

static int ecryptfs_flush(struct file *file, fl_owner_t td)
{
int rc = 0;
struct file *lower_file = NULL;

lower_file = ecryptfs_file_to_lower(file);
if (lower_file->f_op && lower_file->f_op->flush)
rc = lower_file->f_op->flush(lower_file, td);
return rc;
return file->f_mode & FMODE_WRITE
? filemap_write_and_wait(file->f_mapping) : 0;
}

static int ecryptfs_release(struct inode *inode, struct file *file)
{
ecryptfs_put_lower_file(inode);
kmem_cache_free(ecryptfs_file_info_cache,
ecryptfs_file_to_private(file));
return 0;
Expand Down
60 changes: 32 additions & 28 deletions fs/ecryptfs/inode.c
Expand Up @@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
"context; rc = [%d]\n", rc);
goto out;
}
rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
rc = ecryptfs_get_lower_file(ecryptfs_dentry);
if (rc) {
printk(KERN_ERR "%s: Error attempting to initialize "
"the persistent file for the dentry with name "
"the lower file for the dentry with name "
"[%s]; rc = [%d]\n", __func__,
ecryptfs_dentry->d_name.name, rc);
goto out;
}
rc = ecryptfs_write_metadata(ecryptfs_dentry);
if (rc) {
if (rc)
printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
goto out;
}
ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
out:
return rc;
}
Expand Down Expand Up @@ -226,11 +225,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
struct dentry *lower_dir_dentry;
struct vfsmount *lower_mnt;
struct inode *lower_inode;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
struct ecryptfs_crypt_stat *crypt_stat;
char *page_virt = NULL;
u64 file_size;
int rc = 0;
int put_lower = 0, rc = 0;

lower_dir_dentry = lower_dentry->d_parent;
lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(
Expand Down Expand Up @@ -277,14 +274,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
rc = -ENOMEM;
goto out;
}
rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
rc = ecryptfs_get_lower_file(ecryptfs_dentry);
if (rc) {
printk(KERN_ERR "%s: Error attempting to initialize "
"the persistent file for the dentry with name "
"the lower file for the dentry with name "
"[%s]; rc = [%d]\n", __func__,
ecryptfs_dentry->d_name.name, rc);
goto out_free_kmem;
}
put_lower = 1;
crypt_stat = &ecryptfs_inode_to_private(
ecryptfs_dentry->d_inode)->crypt_stat;
/* TODO: lock for crypt_stat comparison */
Expand All @@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
}
crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
}
mount_crypt_stat = &ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
file_size = (crypt_stat->metadata_size
+ i_size_read(lower_dentry->d_inode));
else
file_size = i_size_read(lower_dentry->d_inode);
} else {
file_size = get_unaligned_be64(page_virt);
}
i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size);
ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);
out_free_kmem:
kmem_cache_free(ecryptfs_header_cache_2, page_virt);
goto out;
Expand All @@ -322,6 +309,8 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
mntput(lower_mnt);
d_drop(ecryptfs_dentry);
out:
if (put_lower)
ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
return rc;
}

Expand Down Expand Up @@ -538,8 +527,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
dget(lower_dentry);
rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
dput(lower_dentry);
if (!rc)
d_delete(lower_dentry);
fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
unlock_dir(lower_dir_dentry);
Expand Down Expand Up @@ -610,8 +597,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
out_lock:
unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
dput(lower_new_dentry->d_parent);
dput(lower_old_dentry->d_parent);
dput(lower_new_dir_dentry);
dput(lower_old_dir_dentry);
dput(lower_new_dentry);
dput(lower_old_dentry);
return rc;
Expand Down Expand Up @@ -759,8 +746,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,

if (unlikely((ia->ia_size == i_size))) {
lower_ia->ia_valid &= ~ATTR_SIZE;
goto out;
return 0;
}
rc = ecryptfs_get_lower_file(dentry);
if (rc)
return rc;
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
/* Switch on growing or shrinking file */
if (ia->ia_size > i_size) {
Expand Down Expand Up @@ -838,6 +828,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
lower_ia->ia_valid &= ~ATTR_SIZE;
}
out:
ecryptfs_put_lower_file(inode);
return rc;
}

Expand Down Expand Up @@ -913,7 +904,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)

mount_crypt_stat = &ecryptfs_superblock_to_private(
dentry->d_sb)->mount_crypt_stat;
rc = ecryptfs_get_lower_file(dentry);
if (rc) {
mutex_unlock(&crypt_stat->cs_mutex);
goto out;
}
rc = ecryptfs_read_metadata(dentry);
ecryptfs_put_lower_file(inode);
if (rc) {
if (!(mount_crypt_stat->flags
& ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
Expand All @@ -927,10 +924,17 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
goto out;
}
rc = 0;
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
| ECRYPTFS_ENCRYPTED);
}
}
mutex_unlock(&crypt_stat->cs_mutex);
if (S_ISREG(inode->i_mode)) {
rc = filemap_write_and_wait(inode->i_mapping);
if (rc)
goto out;
fsstack_copy_attr_all(inode, lower_inode);
}
memcpy(&lower_ia, ia, sizeof(lower_ia));
if (ia->ia_valid & ATTR_FILE)
lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
Expand Down
6 changes: 3 additions & 3 deletions fs/ecryptfs/kthread.c
Expand Up @@ -44,7 +44,7 @@ static struct task_struct *ecryptfs_kthread;
* @ignored: ignored
*
* The eCryptfs kernel thread that has the responsibility of getting
* the lower persistent file with RW permissions.
* the lower file with RW permissions.
*
* Returns zero on success; non-zero otherwise
*/
Expand Down Expand Up @@ -141,8 +141,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
int rc = 0;

/* Corresponding dput() and mntput() are done when the
* persistent file is fput() when the eCryptfs inode is
* destroyed. */
* lower file is fput() when all eCryptfs files for the inode are
* released. */
dget(lower_dentry);
mntget(lower_mnt);
flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
Expand Down

0 comments on commit cd2e49e

Please sign in to comment.