diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 89178f5d371a..7d746a10c369 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -196,11 +196,26 @@ int configfs_symlink(const struct mnt_idmap *idmap, struct inode *dir, * * AV, a thoroughly annoyed bastard. */ + + /* Put the reference back, retake and check after relocking*/ + config_item_put(parent_item); + parent_item = NULL; inode_unlock(dir); ret = get_target(symname, &target_item, &target_sd, dentry->d_sb); inode_lock(dir); if (ret) - goto out_put; + goto out_put; /* config_item_put on NULL, no problem */ + + if (IS_DEADDIR(dir)) { + ret = -ENOENT; + goto out_put_target; + } + + parent_item = configfs_get_config_item(dentry->d_parent); + if (!parent_item) { + ret = -ENOENT; + goto out_put_target; + } if (dentry->d_inode || d_unhashed(dentry)) ret = -EEXIST; @@ -218,6 +233,7 @@ int configfs_symlink(const struct mnt_idmap *idmap, struct inode *dir, target_item); } +out_put_target: configfs_put(target_sd); config_item_put(target_item);