[PATCH] Pass the f_flags from the upper open to the lower open.

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

 



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.

This is a patch against git://kernel.ubuntu.com/ubuntu/ubuntu-precise.git
I can make one against git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
if you prefer?

---
 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 461c268..1ca30d9 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -688,8 +688,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 0747a43..27dadff 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -233,7 +233,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 2707fa9..267814c 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -265,7 +265,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 "
@@ -329,7 +329,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 "
@@ -827,7 +827,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;
@@ -995,7 +995,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 0dbe58a..4845f5c 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -126,6 +126,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.
  *
@@ -134,7 +136,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;
@@ -146,6 +149,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
        dget(lower_dentry);
        mntget(lower_mnt);
        flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
+       flags |= (upper_file_flags & FMODE_NONOTIFY);
        (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
        if (!IS_ERR(*lower_file))
                goto out;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 9e3d2ee..cbb598a 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


--
Douglas Leeder



________________________________

Sophos Limited, The Pentagon, Abingdon Science Park, Abingdon, OX14 3YP, United Kingdom.
Company Reg No 2096520. VAT Reg No GB 991 2418 08.
��.n��������+%������w��{.n����r����y�ʇڙ���f���h������_�(�階�ݢj"��������G����?���&��



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

  Powered by Linux