Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd2e49e9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents 71e9e6a5 5be79de2
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -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
@@ -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);
+6 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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;
};
@@ -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);
@@ -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,
+12 −13
Original line number Diff line number Diff line
@@ -191,10 +191,10 @@ 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;
@@ -202,9 +202,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
	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);
@@ -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;
		}
@@ -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));
@@ -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;
+32 −28
Original line number Diff line number Diff line
@@ -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;
}
@@ -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(
@@ -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 */
@@ -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;
@@ -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;
}

@@ -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);
@@ -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;
@@ -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) {
@@ -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;
}

@@ -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)) {
@@ -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);
+3 −3
Original line number Diff line number Diff line
@@ -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
 */
@@ -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;
Loading