diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-06-06 12:31:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-06-06 12:31:15 -0700 |
commit | 5d6b501fe5421c5df662e2935f55f5e3d2b5e012 (patch) | |
tree | b585152e88b791047ca679eacdd958b70674cf7b /fs/overlayfs/inode.c | |
parent | 211758573b01f4cd27308464573d112ef85e0e1a (diff) | |
parent | 5d3211b651a012bc77410ebf097b7271a7ce5c95 (diff) | |
download | linux-5d6b501fe5421c5df662e2935f55f5e3d2b5e012.tar.gz linux-5d6b501fe5421c5df662e2935f55f5e3d2b5e012.tar.bz2 linux-5d6b501fe5421c5df662e2935f55f5e3d2b5e012.zip |
Merge tag 'ovl-fixes-5.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs fixes from Miklos Szeredi:
"Here's one fix for a class of bugs triggered by syzcaller, and one
that makes xfstests fail less"
* tag 'ovl-fixes-5.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ovl: doc: add non-standard corner cases
ovl: detect overlapping layers
ovl: support the FS_IOC_FS[SG]ETXATTR ioctls
Diffstat (limited to 'fs/overlayfs/inode.c')
-rw-r--r-- | fs/overlayfs/inode.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index b48273e846ad..f7eba21effa5 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -777,6 +777,54 @@ struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real, return inode; } +bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir) +{ + struct inode *key = d_inode(dir); + struct inode *trap; + bool res; + + trap = ilookup5(sb, (unsigned long) key, ovl_inode_test, key); + if (!trap) + return false; + + res = IS_DEADDIR(trap) && !ovl_inode_upper(trap) && + !ovl_inode_lower(trap); + + iput(trap); + return res; +} + +/* + * Create an inode cache entry for layer root dir, that will intentionally + * fail ovl_verify_inode(), so any lookup that will find some layer root + * will fail. + */ +struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir) +{ + struct inode *key = d_inode(dir); + struct inode *trap; + + if (!d_is_dir(dir)) + return ERR_PTR(-ENOTDIR); + + trap = iget5_locked(sb, (unsigned long) key, ovl_inode_test, + ovl_inode_set, key); + if (!trap) + return ERR_PTR(-ENOMEM); + + if (!(trap->i_state & I_NEW)) { + /* Conflicting layer roots? */ + iput(trap); + return ERR_PTR(-ELOOP); + } + + trap->i_mode = S_IFDIR; + trap->i_flags = S_DEAD; + unlock_new_inode(trap); + + return trap; +} + /* * Does overlay inode need to be hashed by lower inode? */ |