open(O_CREAT) without O_EXCL follows a trailing symlink and, when the symlink target does not exist, creates it. Refuse to create through a dangling symlink for directories. In lookup_open() a negative target reached with nd->depth > 0 was arrived at by following a trailing symlink; since the dentry is negative the symlink is dangling. Set create_error to -ELOOP in that case. Reusing the existing create_error path strips O_CREAT for both the generic and ->atomic_open create paths and only reports the error when the target is actually negative, so opening an existing target through a symlink, interior symlinks, and O_EXCL (which never follows the trailing link) are all unaffected. Suggested-by: Christian Brauner (Amutable) Signed-off-by: Jori Koolstra --- fs/namei.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/namei.c b/fs/namei.c index c4b242205707..fef826c04eb5 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4535,6 +4535,11 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file, dentry, mode, create_dir); else create_error = -EROFS; + /* Refuse to create a directory through a dangling (trailing) + * symlink. For regular files this has been allowed historically + * on O_CREAT without O_EXCL. */ + if (unlikely(nd->depth) && create_dir && !create_error) + create_error = -ELOOP; } if (create_error) open_flag &= ~O_CREAT; -- 2.54.0