]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ksmbd: validate share name from share config response
authorAtte Heikkilä <atteh.mailbox@gmail.com>
Sun, 2 Oct 2022 23:09:34 +0000 (02:09 +0300)
committerSteve French <stfrench@microsoft.com>
Wed, 5 Oct 2022 06:15:44 +0000 (01:15 -0500)
Share config response may contain the share name without casefolding as
it is known to the user space daemon. When it is present, casefold and
compare it to the share name the share config request was made with. If
they differ, we have a share config which is incompatible with the way
share config caching is done. This is the case when CONFIG_UNICODE is
not set, the share name contains non-ASCII characters, and those non-
ASCII characters do not match those in the share name known to user
space. In other words, when CONFIG_UNICODE is not set, UTF-8 share
names now work but are only case-insensitive in the ASCII range.

Signed-off-by: Atte Heikkilä <atteh.mailbox@gmail.com>
Acked-by: Tom Talpey <tom@talpey.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/ksmbd/ksmbd_netlink.h
fs/ksmbd/mgmt/share_config.c
fs/ksmbd/mgmt/share_config.h
fs/ksmbd/mgmt/tree_connect.c
fs/ksmbd/misc.c
fs/ksmbd/misc.h

index e0cbcfa98c7ebb64e506404d9c476afcdede782f..ff07c67f4565e6c353727eeb438b6f3cbe929db0 100644 (file)
@@ -163,7 +163,8 @@ struct ksmbd_share_config_response {
        __u16   force_directory_mode;
        __u16   force_uid;
        __u16   force_gid;
-       __u32   reserved[128];          /* Reserved room */
+       __s8    share_name[KSMBD_REQ_MAX_SHARE_NAME];
+       __u32   reserved[112];          /* Reserved room */
        __u32   veto_list_sz;
        __s8    ____payload[];
 };
index 5d039704c23c3398a16d290fe1475605f79ea1ce..328a412259dc1b935eb2ce3eee2977d39155157b 100644 (file)
@@ -16,6 +16,7 @@
 #include "user_config.h"
 #include "user_session.h"
 #include "../transport_ipc.h"
+#include "../misc.h"
 
 #define SHARE_HASH_BITS                3
 static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
@@ -119,7 +120,8 @@ static int parse_veto_list(struct ksmbd_share_config *share,
        return 0;
 }
 
-static struct ksmbd_share_config *share_config_request(const char *name)
+static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
+                                                      const char *name)
 {
        struct ksmbd_share_config_response *resp;
        struct ksmbd_share_config *share = NULL;
@@ -133,6 +135,19 @@ static struct ksmbd_share_config *share_config_request(const char *name)
        if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
                goto out;
 
+       if (*resp->share_name) {
+               char *cf_resp_name;
+               bool equal;
+
+               cf_resp_name = ksmbd_casefold_sharename(um, resp->share_name);
+               if (IS_ERR(cf_resp_name))
+                       goto out;
+               equal = !strcmp(cf_resp_name, name);
+               kfree(cf_resp_name);
+               if (!equal)
+                       goto out;
+       }
+
        share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
        if (!share)
                goto out;
@@ -190,7 +205,8 @@ out:
        return share;
 }
 
-struct ksmbd_share_config *ksmbd_share_config_get(const char *name)
+struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
+                                                 const char *name)
 {
        struct ksmbd_share_config *share;
 
@@ -202,7 +218,7 @@ struct ksmbd_share_config *ksmbd_share_config_get(const char *name)
 
        if (share)
                return share;
-       return share_config_request(name);
+       return share_config_request(um, name);
 }
 
 bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
index 7f7e89ecfe6166b275dbb8ae3d8648abd0a53968..3fd33829394219bbbbe2203c02f770b7e9912c7a 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/workqueue.h>
 #include <linux/hashtable.h>
 #include <linux/path.h>
+#include <linux/unicode.h>
 
 struct ksmbd_share_config {
        char                    *name;
@@ -74,7 +75,8 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
        __ksmbd_share_config_put(share);
 }
 
-struct ksmbd_share_config *ksmbd_share_config_get(const char *name);
+struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
+                                                 const char *name);
 bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
                               const char *filename);
 #endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
index 867c0286b901d76483e8bb6ec90b2eed9bd0a0e8..8ce17b3fb8dad4b7e0f8a8fa03d11c4b82294397 100644 (file)
@@ -26,7 +26,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
        struct sockaddr *peer_addr;
        int ret;
 
-       sc = ksmbd_share_config_get(share_name);
+       sc = ksmbd_share_config_get(conn->um, share_name);
        if (!sc)
                return status;
 
@@ -61,7 +61,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
                struct ksmbd_share_config *new_sc;
 
                ksmbd_share_config_del(sc);
-               new_sc = ksmbd_share_config_get(share_name);
+               new_sc = ksmbd_share_config_get(conn->um, share_name);
                if (!new_sc) {
                        pr_err("Failed to update stale share config\n");
                        status.ret = -ESTALE;
index 28459b1efaa88ede96ceb340b0ff38d02d8039d7..9e8afaa686e3aa8c12e908348aa38b34168ec367 100644 (file)
@@ -227,7 +227,7 @@ void ksmbd_conv_path_to_windows(char *path)
        strreplace(path, '/', '\\');
 }
 
-static char *casefold_sharename(struct unicode_map *um, const char *name)
+char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name)
 {
        char *cf_name;
        int cf_len;
@@ -273,7 +273,7 @@ char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename)
                name = (pos + 1);
 
        /* caller has to free the memory */
-       return casefold_sharename(um, name);
+       return ksmbd_casefold_sharename(um, name);
 }
 
 /**
index cc72f4e6baf23f212148d1fc42784b3ad43d01c2..1facfcd21200fd1af3f4c062da4bfb9d0b3e69c4 100644 (file)
@@ -20,6 +20,7 @@ int get_nlink(struct kstat *st);
 void ksmbd_conv_path_to_unix(char *path);
 void ksmbd_strip_last_slash(char *path);
 void ksmbd_conv_path_to_windows(char *path);
+char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name);
 char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
 char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);