ksmbd: make utf-8 file name comparison work in __caseless_lookup()
Case-insensitive file name lookups with __caseless_lookup() use strncasecmp() for file name comparison. strncasecmp() assumes an ISO8859-1-compatible encoding, which is not the case here as UTF-8 is always used. As such, use of strncasecmp() here produces correct results only if both strings use characters in the ASCII range only. Fix this by using utf8_strncasecmp() if CONFIG_UNICODE is set. On failure or if CONFIG_UNICODE is not set, fallback to strncasecmp(). Also, as we are adding an include for `linux/unicode.h', include it in `fs/ksmbd/connection.h' as well since it should be explicit there. Signed-off-by: Atte Heikkilä <atteh.mailbox@gmail.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
7c88c1e0ab
commit
dbab80e207
|
@ -14,6 +14,7 @@
|
||||||
#include <net/request_sock.h>
|
#include <net/request_sock.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/nls.h>
|
#include <linux/nls.h>
|
||||||
|
#include <linux/unicode.h>
|
||||||
|
|
||||||
#include "smb_common.h"
|
#include "smb_common.h"
|
||||||
#include "ksmbd_work.h"
|
#include "ksmbd_work.h"
|
||||||
|
|
|
@ -1145,12 +1145,23 @@ static int __caseless_lookup(struct dir_context *ctx, const char *name,
|
||||||
unsigned int d_type)
|
unsigned int d_type)
|
||||||
{
|
{
|
||||||
struct ksmbd_readdir_data *buf;
|
struct ksmbd_readdir_data *buf;
|
||||||
|
int cmp = -EINVAL;
|
||||||
|
|
||||||
buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
|
buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
|
||||||
|
|
||||||
if (buf->used != namlen)
|
if (buf->used != namlen)
|
||||||
return 0;
|
return 0;
|
||||||
if (!strncasecmp((char *)buf->private, name, namlen)) {
|
if (IS_ENABLED(CONFIG_UNICODE) && buf->um) {
|
||||||
|
const struct qstr q_buf = {.name = buf->private,
|
||||||
|
.len = buf->used};
|
||||||
|
const struct qstr q_name = {.name = name,
|
||||||
|
.len = namlen};
|
||||||
|
|
||||||
|
cmp = utf8_strncasecmp(buf->um, &q_buf, &q_name);
|
||||||
|
}
|
||||||
|
if (cmp < 0)
|
||||||
|
cmp = strncasecmp((char *)buf->private, name, namlen);
|
||||||
|
if (!cmp) {
|
||||||
memcpy((char *)buf->private, name, namlen);
|
memcpy((char *)buf->private, name, namlen);
|
||||||
buf->dirent_count = 1;
|
buf->dirent_count = 1;
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
@ -1166,7 +1177,8 @@ static int __caseless_lookup(struct dir_context *ctx, const char *name,
|
||||||
*
|
*
|
||||||
* Return: 0 on success, otherwise error
|
* Return: 0 on success, otherwise error
|
||||||
*/
|
*/
|
||||||
static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name, size_t namelen)
|
static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
|
||||||
|
size_t namelen, struct unicode_map *um)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct file *dfilp;
|
struct file *dfilp;
|
||||||
|
@ -1176,6 +1188,7 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name, size_t na
|
||||||
.private = name,
|
.private = name,
|
||||||
.used = namelen,
|
.used = namelen,
|
||||||
.dirent_count = 0,
|
.dirent_count = 0,
|
||||||
|
.um = um,
|
||||||
};
|
};
|
||||||
|
|
||||||
dfilp = dentry_open(dir, flags, current_cred());
|
dfilp = dentry_open(dir, flags, current_cred());
|
||||||
|
@ -1238,7 +1251,8 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err = ksmbd_vfs_lookup_in_dir(&parent, filename,
|
err = ksmbd_vfs_lookup_in_dir(&parent, filename,
|
||||||
filename_len);
|
filename_len,
|
||||||
|
work->conn->um);
|
||||||
path_put(&parent);
|
path_put(&parent);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <uapi/linux/xattr.h>
|
#include <uapi/linux/xattr.h>
|
||||||
#include <linux/posix_acl.h>
|
#include <linux/posix_acl.h>
|
||||||
|
#include <linux/unicode.h>
|
||||||
|
|
||||||
#include "smbacl.h"
|
#include "smbacl.h"
|
||||||
#include "xattr.h"
|
#include "xattr.h"
|
||||||
|
@ -60,6 +61,7 @@ struct ksmbd_readdir_data {
|
||||||
unsigned int used;
|
unsigned int used;
|
||||||
unsigned int dirent_count;
|
unsigned int dirent_count;
|
||||||
unsigned int file_attr;
|
unsigned int file_attr;
|
||||||
|
struct unicode_map *um;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ksmbd kstat wrapper to get valid create time when reading dir entry */
|
/* ksmbd kstat wrapper to get valid create time when reading dir entry */
|
||||||
|
|
Loading…
Reference in New Issue