From: Namjae Jeon namjae.jeon@samsung.com
mainline inclusion from mainline-5.15-rc1 commit b24c93358035e3c20630a45c0bcdbb45aad9707d category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I60T7G CVE: NA
Reference: https://git.kernel.org/torvalds/linux/c/b24c93358035
-------------------------------
When iterating through a directory, a file's name may not be null-terminated (depending on the underlying filesystem implementation).
Modify match_pattern to take the string's length into account when matching it against the request pattern.
Signed-off-by: Marios Makassikis mmakassikis@freebox.fr 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/misc.c | 7 +++++-- fs/cifsd/misc.h | 2 +- fs/cifsd/smb2pdu.c | 2 +- fs/cifsd/smb_common.c | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/fs/cifsd/misc.c b/fs/cifsd/misc.c index 68983b08d519..189b90414976 100644 --- a/fs/cifsd/misc.c +++ b/fs/cifsd/misc.c @@ -22,20 +22,22 @@ * TODO : implement consideration about DOS_DOT, DOS_QM and DOS_STAR * * @string: string to compare with a pattern + * @len: string length * @pattern: pattern string which might include wildcard '*' and '?' * * Return: 0 if pattern matched with the string, otherwise non zero value */ -int match_pattern(const char *str, const char *pattern) +int match_pattern(const char *str, size_t len, const char *pattern) { const char *s = str; const char *p = pattern; bool star = false;
- while (*s) { + while (*s && len) { switch (*p) { case '?': s++; + len--; p++; break; case '*': @@ -48,6 +50,7 @@ int match_pattern(const char *str, const char *pattern) default: if (tolower(*s) == tolower(*p)) { s++; + len--; p++; } else { if (!star) diff --git a/fs/cifsd/misc.h b/fs/cifsd/misc.h index 41b3dac2f5fc..73b21709b6c9 100644 --- a/fs/cifsd/misc.h +++ b/fs/cifsd/misc.h @@ -11,7 +11,7 @@ struct nls_table; struct kstat; struct ksmbd_file;
-int match_pattern(const char *str, const char *pattern); +int match_pattern(const char *str, size_t len, const char *pattern);
int ksmbd_validate_filename(char *filename);
diff --git a/fs/cifsd/smb2pdu.c b/fs/cifsd/smb2pdu.c index 4ec45c3fa00e..32816baa8a99 100644 --- a/fs/cifsd/smb2pdu.c +++ b/fs/cifsd/smb2pdu.c @@ -3837,7 +3837,7 @@ static int __query_dir(struct dir_context *ctx, return 0; if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name)) return 0; - if (!match_pattern(name, priv->search_pattern)) + if (!match_pattern(name, namlen, priv->search_pattern)) return 0;
d_info->name = name; diff --git a/fs/cifsd/smb_common.c b/fs/cifsd/smb_common.c index f779aae3fd6c..2f58ef003238 100644 --- a/fs/cifsd/smb_common.c +++ b/fs/cifsd/smb_common.c @@ -294,7 +294,8 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, d_info->name_len = 2; }
- if (!match_pattern(d_info->name, search_pattern)) { + if (!match_pattern(d_info->name, d_info->name_len, + search_pattern)) { dir->dot_dotdot[i] = 1; continue; }