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����?���&��