@@ -197,6 +197,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);
@@ -260,7 +260,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);
}
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@gmail.com> --- fs/overlayfs/super.c | 1 + fs/overlayfs/util.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)