From: Hyunchul Lee hyc.lee@gmail.com
mainline inclusion from mainline-5.15-rc1 commit a6a5fa77805b291afc90291a6ae705b1759b9735 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I60T7G CVE: NA
Reference: https://git.kernel.org/torvalds/linux/c/a6a5fa77805b
-------------------------------
Some vfs help functions lookup a file with LOOKUP_FOLLOW regardless of the "follow symlinks" option.
Signed-off-by: Hyunchul Lee hyc.lee@gmail.com Signed-off-by: Namjae Jeon namjae.jeon@samsung.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Jason Yan yanaijie@huawei.com Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com --- fs/cifsd/smb2pdu.c | 6 +++++- fs/cifsd/vfs.c | 24 ++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/fs/cifsd/smb2pdu.c b/fs/cifsd/smb2pdu.c index 212cdffd27bc..f68e2638d629 100644 --- a/fs/cifsd/smb2pdu.c +++ b/fs/cifsd/smb2pdu.c @@ -4583,8 +4583,12 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, struct path path; int rc = 0, len; int fs_infoclass_size = 0; + int lookup_flags = 0;
- rc = ksmbd_vfs_kern_path(share->path, LOOKUP_FOLLOW, &path, 0); + if (test_share_config_flag(share, KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS)) + lookup_flags = LOOKUP_FOLLOW; + + rc = ksmbd_vfs_kern_path(share->path, lookup_flags, &path, 0); if (rc) { ksmbd_err("cannot create vfs path\n"); return -EIO; diff --git a/fs/cifsd/vfs.c b/fs/cifsd/vfs.c index 355e1a5a893b..291953eff5fa 100644 --- a/fs/cifsd/vfs.c +++ b/fs/cifsd/vfs.c @@ -572,11 +572,16 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name) struct path path; struct dentry *dentry, *parent; int err; + int flags = 0;
if (ksmbd_override_fsids(work)) return -ENOMEM;
- err = kern_path(name, LOOKUP_FOLLOW, &path); + if (test_share_config_flag(work->tcon->share_conf, + KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS)) + flags = LOOKUP_FOLLOW; + + err = kern_path(name, flags, &path); if (err) { ksmbd_debug(VFS, "can't get %s, err %d\n", name, err); ksmbd_revert_fsids(work); @@ -634,11 +639,16 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname, struct path oldpath, newpath; struct dentry *dentry; int err; + int flags = 0;
if (ksmbd_override_fsids(work)) return -ENOMEM;
- err = kern_path(oldname, LOOKUP_FOLLOW, &oldpath); + if (test_share_config_flag(work->tcon->share_conf, + KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS)) + flags = LOOKUP_FOLLOW; + + err = kern_path(oldname, flags, &oldpath); if (err) { ksmbd_err("cannot get linux path for %s, err = %d\n", oldname, err); @@ -646,7 +656,7 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname, }
dentry = kern_path_create(AT_FDCWD, newname, &newpath, - LOOKUP_FOLLOW | LOOKUP_REVAL); + flags | LOOKUP_REVAL); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); ksmbd_err("path create err for %s, err %d\n", newname, err); @@ -749,6 +759,7 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp, struct dentry *src_dent, *trap_dent, *src_child; char *dst_name; int err; + int flags;
dst_name = extract_last_component(newname); if (!dst_name) @@ -757,7 +768,12 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp, src_dent_parent = dget_parent(fp->filp->f_path.dentry); src_dent = fp->filp->f_path.dentry;
- err = kern_path(newname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &dst_path); + flags = LOOKUP_DIRECTORY; + if (test_share_config_flag(work->tcon->share_conf, + KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS)) + flags |= LOOKUP_FOLLOW; + + err = kern_path(newname, flags, &dst_path); if (err) { ksmbd_debug(VFS, "Cannot get path for %s [%d]\n", newname, err); goto out;