From 60cc4460525e84ca67a2cf48ecb5c9443e1fa01c Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 11 Jun 2024 23:05:06 +0900 Subject: [PATCH] ksmbd: fix missing use of get_write in in smb2_set_ea() Fix an issue where get_write is not used in smb2_set_ea(). Fixes: 6fc0a265e1b9 ("ksmbd: fix potential circular locking issue in smb2_set_ea()") Cc: stable@vger.kernel.org Reported-by: Wang Zhaolong Signed-off-by: Namjae Jeon --- smb2pdu.c | 9 +++++---- vfs.c | 20 ++++++++++++-------- vfs.h | 3 ++- vfs_cache.c | 3 ++- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/smb2pdu.c b/smb2pdu.c index c41228f51..0a524008c 100644 --- a/smb2pdu.c +++ b/smb2pdu.c @@ -2397,7 +2397,8 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len, rc = ksmbd_vfs_remove_xattr(user_ns, #endif path, - attr_name); + attr_name, + get_write); if (rc < 0) { ksmbd_debug(SMB, @@ -2417,7 +2418,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len, #endif path, attr_name, value, le16_to_cpu(eabuf->EaValueLength), - 0, true); + 0, get_write); if (rc < 0) { ksmbd_debug(SMB, "ksmbd_vfs_setxattr is failed(%d)\n", @@ -2526,9 +2527,9 @@ static int smb2_remove_smb_xattrs(const struct path *path) !strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN)) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0) - err = ksmbd_vfs_remove_xattr(idmap, path, name); + err = ksmbd_vfs_remove_xattr(idmap, path, name, true); #else - err = ksmbd_vfs_remove_xattr(user_ns, path, name); + err = ksmbd_vfs_remove_xattr(user_ns, path, name, true); #endif if (err) ksmbd_debug(SMB, "remove xattr failed : %s\n", diff --git a/vfs.c b/vfs.c index d0867c329..e415211dd 100644 --- a/vfs.c +++ b/vfs.c @@ -2017,7 +2017,7 @@ int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns, err = vfs_remove_acl(user_ns, path->dentry, name); #endif #else - err = ksmbd_vfs_remove_xattr(user_ns, path, name); + err = ksmbd_vfs_remove_xattr(user_ns, path, name, false); #endif if (err) ksmbd_debug(SMB, @@ -2055,9 +2055,9 @@ int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns, if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0) - err = ksmbd_vfs_remove_xattr(idmap, path, name); + err = ksmbd_vfs_remove_xattr(idmap, path, name, true); #else - err = ksmbd_vfs_remove_xattr(user_ns, path, name); + err = ksmbd_vfs_remove_xattr(user_ns, path, name, true); #endif if (err) ksmbd_debug(SMB, "remove xattr failed : %s\n", name); @@ -2502,13 +2502,16 @@ int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap, #else int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns, #endif - const struct path *path, char *attr_name) + const struct path *path, char *attr_name, + bool get_write) { int err; - err = mnt_want_write(path->mnt); - if (err) - return err; + if (get_write == true) { + err = mnt_want_write(path->mnt); + if (err) + return err; + } #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0) @@ -2519,7 +2522,8 @@ int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns, #else err = vfs_removexattr(path->dentry, attr_name); #endif - mnt_drop_write(path->mnt); + if (get_write == true) + mnt_drop_write(path->mnt); return err; } diff --git a/vfs.h b/vfs.h index eb5b291af..728016cb7 100644 --- a/vfs.h +++ b/vfs.h @@ -234,7 +234,8 @@ int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap, #else int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns, #endif - const struct path *path, char *attr_name); + const struct path *path, char *attr_name, + bool get_write); #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name, unsigned int flags, struct path *parent_path, diff --git a/vfs_cache.c b/vfs_cache.c index db87911d1..250a3153d 100644 --- a/vfs_cache.c +++ b/vfs_cache.c @@ -272,7 +272,8 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp) err = ksmbd_vfs_remove_xattr(file_mnt_user_ns(filp), #endif &filp->f_path, - fp->stream.name); + fp->stream.name, + true); if (err) pr_err("remove xattr failed : %s\n", fp->stream.name);