Re: ecryptfs and fanotify

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 14/08/12 21:27, Tyler C Hicks wrote:
On 2012-08-14 17:01:14, Douglas Leeder wrote:

So I've looked at the path required for that and I guess it involves
passing file->f_flags from ecryptfs_open through:
  * ecryptfs_get_lower_file (main.c)
  * ecryptfs_init_lower_file (main.c)
  * ecryptfs_privileged_open (kthread.c)

Does that look like the correct to you, Tyler?

Yeah, that should be the full list.

However, I don't think this approach will work with the current
eCryptfs design. eCryptfs only keeps one lower file open per inode. That
means that there could be 10 file descriptors opened for a given
eCryptfs file but there is still only one lower file opened that
everything is multiplexed through.

I don't like the design, but it has been that way for years and I
haven't touched it. For your approach to work, I think eCryptfs would
need to be changed to have a 1-to-1 mapping of upper files to lower
files.


I've attached my patch to pass the flags though, and apply the
FMODE_NONOTIFY flag to the lower access.

The other callers of ecryptfs_get_lower_file just pass in zero, so
will continue with the existing behaviour.

What do you think?

--
Douglas Leeder, Senior Software Engineer

________________________________

Sophos Limited, The Pentagon, Abingdon Science Park, Abingdon, OX14 3YP, United Kingdom.
Company Reg No 2096520. VAT Reg No GB 991 2418 08.
>From 8d204f86caefbbbe918ecd36ff1dfeacaa71eefd Mon Sep 17 00:00:00 2001
From: Douglas Leeder <douglas.leeder@xxxxxxxxxx>
Date: Mon, 20 Aug 2012 15:33:29 +0100
Subject: [PATCH] Pass the f_flags from the upper open to the lower open.

Ensure that if the upper open happens with FMODE_NONOTIFY set,
then the lower open also does that.
This should prevent the dead-lock with fanotify and ecryptfs.
---
 fs/ecryptfs/ecryptfs_kernel.h |    5 +++--
 fs/ecryptfs/file.c            |    2 +-
 fs/ecryptfs/inode.c           |    8 ++++----
 fs/ecryptfs/kthread.c         |    6 +++++-
 fs/ecryptfs/main.c            |    8 ++++----
 5 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index cfb4b9f..651477a 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -668,8 +668,9 @@ void ecryptfs_destroy_kthread(void);
 int ecryptfs_privileged_open(struct file **lower_file,
 			     struct dentry *lower_dentry,
 			     struct vfsmount *lower_mnt,
-			     const struct cred *cred);
-int ecryptfs_get_lower_file(struct dentry *dentry, struct inode *inode);
+			     const struct cred *cred,
+			     unsigned int upper_file_flags);
+int ecryptfs_get_lower_file(struct dentry *dentry, struct inode *inode, unsigned int upper_file_flags);
 void ecryptfs_put_lower_file(struct inode *inode);
 int
 ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 44ce5c6..aa8aad5 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -232,7 +232,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
 				      | ECRYPTFS_ENCRYPTED);
 	}
 	mutex_unlock(&crypt_stat->cs_mutex);
-	rc = ecryptfs_get_lower_file(ecryptfs_dentry, inode);
+	rc = ecryptfs_get_lower_file(ecryptfs_dentry, inode, file->f_flags);
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to initialize "
 			"the lower file for the dentry with name "
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 534b129..847ced2 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -246,7 +246,7 @@ int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
 				"context; rc = [%d]\n", rc);
 		goto out;
 	}
-	rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode);
+	rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode, 0);
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to initialize "
 			"the lower file for the dentry with name "
@@ -309,7 +309,7 @@ static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode)
 	struct ecryptfs_crypt_stat *crypt_stat;
 	int rc;
 
-	rc = ecryptfs_get_lower_file(dentry, inode);
+	rc = ecryptfs_get_lower_file(dentry, inode, 0);
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to initialize "
 			"the lower file for the dentry with name "
@@ -767,7 +767,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
 		lower_ia->ia_valid &= ~ATTR_SIZE;
 		return 0;
 	}
-	rc = ecryptfs_get_lower_file(dentry, inode);
+	rc = ecryptfs_get_lower_file(dentry, inode, 0);
 	if (rc)
 		return rc;
 	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
@@ -935,7 +935,7 @@ 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, inode);
+		rc = ecryptfs_get_lower_file(dentry, inode, 0);
 		if (rc) {
 			mutex_unlock(&crypt_stat->cs_mutex);
 			goto out;
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
index 809e67d..83e9914 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -122,6 +122,8 @@ void ecryptfs_destroy_kthread(void)
  * @lower_file: Result of dentry_open by root on lower dentry
  * @lower_dentry: Lower dentry for file to open
  * @lower_mnt: Lower vfsmount for file to open
+ * @cred
+ * @upper_file_flags: Upper file flags for the open
  *
  * This function gets a r/w file opened againt the lower dentry.
  *
@@ -130,7 +132,8 @@ void ecryptfs_destroy_kthread(void)
 int ecryptfs_privileged_open(struct file **lower_file,
 			     struct dentry *lower_dentry,
 			     struct vfsmount *lower_mnt,
-			     const struct cred *cred)
+			     const struct cred *cred,
+			     unsigned int upper_file_flags)
 {
 	struct ecryptfs_open_req req;
 	int flags = O_LARGEFILE;
@@ -145,6 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
 	 * lower file is fput() when all eCryptfs files for the inode are
 	 * released. */
 	flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
+	flags |= (upper_file_flags & FMODE_NONOTIFY);
 	(*lower_file) = dentry_open(&req.path, flags, cred);
 	if (!IS_ERR(*lower_file))
 		goto out;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 2768138..0ceebcc 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -117,7 +117,7 @@ void __ecryptfs_printk(const char *fmt, ...)
  * Returns zero on success; non-zero otherwise
  */
 static int ecryptfs_init_lower_file(struct dentry *dentry,
-				    struct file **lower_file)
+				    struct file **lower_file, unsigned int upper_file_flags)
 {
 	const struct cred *cred = current_cred();
 	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
@@ -125,7 +125,7 @@ static int ecryptfs_init_lower_file(struct dentry *dentry,
 	int rc;
 
 	rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt,
-				      cred);
+				      cred, upper_file_flags);
 	if (rc) {
 		printk(KERN_ERR "Error opening lower file "
 		       "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
@@ -135,7 +135,7 @@ static int ecryptfs_init_lower_file(struct dentry *dentry,
 	return rc;
 }
 
-int ecryptfs_get_lower_file(struct dentry *dentry, struct inode *inode)
+int ecryptfs_get_lower_file(struct dentry *dentry, struct inode *inode, unsigned int upper_file_flags)
 {
 	struct ecryptfs_inode_info *inode_info;
 	int count, rc = 0;
@@ -147,7 +147,7 @@ int ecryptfs_get_lower_file(struct dentry *dentry, struct inode *inode)
 		rc = -EINVAL;
 	else if (count == 1) {
 		rc = ecryptfs_init_lower_file(dentry,
-					      &inode_info->lower_file);
+					      &inode_info->lower_file,upper_file_flags);
 		if (rc)
 			atomic_set(&inode_info->lower_file_count, 0);
 	}
-- 
1.7.9.5


[Index of Archives]     [Linux Crypto]     [Device Mapper Crypto]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux