An overlay inode with elevated i_count may outlive its overlay dentry. Since the only reference to OVL_I(inode)->lower was held by the lower dentry object in the overlay dentry (oe->lowerstack[0]), releasing the overlay dentry could leave a live inode with reference to freed lower inode. This may materialize to a bug when a disconnected dentry is obtained from decoding an NFS file handle and a new allocated real inode has the same address as the freed inode in OVL_I(inode)->lower, by which the overlay inode is hashed. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/overlayfs/super.c | 1 + fs/overlayfs/util.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 96136528861f..f152b817e4d0 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -216,6 +216,7 @@ static void ovl_destroy_inode(struct inode *inode) struct ovl_inode *oi = OVL_I(inode); dput(oi->__upperdentry); + iput(oi->lower); kfree(oi->redirect); ovl_dir_cache_free(inode); mutex_destroy(&oi->lock); diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index ce4ac3846b14..d6fe01ece7e8 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -291,7 +291,7 @@ void ovl_inode_init(struct inode *inode, struct dentry *upperdentry, if (upperdentry) OVL_I(inode)->__upperdentry = upperdentry; if (lowerdentry) - OVL_I(inode)->lower = d_inode(lowerdentry); + OVL_I(inode)->lower = igrab(d_inode(lowerdentry)); ovl_copyattr(d_inode(upperdentry ?: lowerdentry), inode); } -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html