From patchwork Sun Oct 2 23:09:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Atte_Heikkil=C3=A4?= X-Patchwork-Id: 12997006 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B8BFBC433FE for ; Sun, 2 Oct 2022 23:15:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230015AbiJBXPY (ORCPT ); Sun, 2 Oct 2022 19:15:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230238AbiJBXPD (ORCPT ); Sun, 2 Oct 2022 19:15:03 -0400 Received: from mail-lf1-x12e.google.com (mail-lf1-x12e.google.com [IPv6:2a00:1450:4864:20::12e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1AE57F01C for ; Sun, 2 Oct 2022 16:09:49 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id k10so14300657lfm.4 for ; Sun, 02 Oct 2022 16:09:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date; bh=p/2dL60qd+wJ7GEonoJrcZ4zKkkT91mYsAprJ4MZThc=; b=FXg5JRQn1fgj/vhN4LF2EVzYyY29l9X0mgtIUqo1PYKjv165Pr8iWcRqKJzb4C9y9n +5pRBhEL2tDRd1poeD4BXu1VrMeKEnZczJRHpCA+4zX8Y4/PpIvE9cbQDuYxUW7wT+uv EGTtIgnrJsHXHF0khSr5Fb1lMRwPMRvJMdfD+UsdqN5tcABvYrU0P+iY5W9riUqEZIeU cqT84wCu1UXkEWrH21Oqm/5c/Ppk15mSBTMd5mPo9cJr8Fc7tXsE9hy7xts4IWJtMd4Y iwSCfmXEpC2zZlrF3vI5aO8kiSyKfqsCIuoIFQa+77QZni99zyhW11djSCElRuJeJCJU vweQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date; bh=p/2dL60qd+wJ7GEonoJrcZ4zKkkT91mYsAprJ4MZThc=; b=Vj81/ONcOOls+/Nn39J6wP1dCZUV4PjH7+YPiifH+trwXc7kUqPPAn2N9H2aUN2OKL HmAxSpydG15J3jDJXkoycmiooxZhwrKELN6gaGE8sXbXRFpA0cWfXUM6x3mAqRLPtBu/ +BKcxvv4KPNqQJIXNXvpdmdyUtStd3frGTofKzb57dnVPfRYLB7E3fo8V/rG/NK6Lrs8 7oxYWn7TaKi8vA4bAFA5Tg8KhbipLruOdmPgKkrHAzh15RDCtfLC73qmZ2zzE3l8RBAk lgtNPnCWn93I6jPpEEVMsv+Yr4O0+NaGkkdqBRcNGOthx7WAS2BojbDq/dRnzR8sJ/gy q6zg== X-Gm-Message-State: ACrzQf17UpeN/Be69tj5mlVQlts/l3Y2cFbhHttjHtPWX1LvSr1yd86h pGNYFseKrC46u1QcbxCHxqqrlM+AMYg= X-Google-Smtp-Source: AMsMyM7BhT0T6QWlVMQ+1EBLt5x5WEKGV4mSIfCDl/Y2L2iARP139XTAWBbHGHpwC535HFLBwYq1Mw== X-Received: by 2002:a05:6512:39c5:b0:4a2:e51:4e5c with SMTP id k5-20020a05651239c500b004a20e514e5cmr5030619lfu.657.1664752187306; Sun, 02 Oct 2022 16:09:47 -0700 (PDT) Received: from pohjola.lan (mobile-user-2e84be-149.dhcp.inet.fi. [46.132.190.149]) by smtp.gmail.com with ESMTPSA id n5-20020a0565120ac500b00492d7a7b4e3sm1215129lfu.4.2022.10.02.16.09.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Oct 2022 16:09:46 -0700 (PDT) From: =?utf-8?q?Atte_Heikkil=C3=A4?= To: linux-cifs@vger.kernel.org Cc: linkinjeon@kernel.org, =?utf-8?q?Atte_Heikkil=C3=A4?= Subject: [PATCH v5] ksmbd: validate share name from share config response Date: Mon, 3 Oct 2022 02:09:34 +0300 Message-Id: <20221002230934.367900-1-atteh.mailbox@gmail.com> X-Mailer: git-send-email 2.37.3 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org 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ä Acked-by: Namjae Jeon Acked-by: Tom Talpey --- v5: - do not call kfree() for ERR_PTR() v4: - check for ksmbd_casefold_sharename() error with IS_ERR() v3: - removed initial strcmp() check since it could only save a call to ksmbd_casefold_sharename() for matching ASCII-only share names v2: - no changes were made fs/ksmbd/ksmbd_netlink.h | 3 ++- fs/ksmbd/mgmt/share_config.c | 22 +++++++++++++++++++--- fs/ksmbd/mgmt/share_config.h | 4 +++- fs/ksmbd/mgmt/tree_connect.c | 4 ++-- fs/ksmbd/misc.c | 4 ++-- fs/ksmbd/misc.h | 1 + 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h index e0cbcfa98c7e..ff07c67f4565 100644 --- a/fs/ksmbd/ksmbd_netlink.h +++ b/fs/ksmbd/ksmbd_netlink.h @@ -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[]; }; diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c index 5d039704c23c..328a412259dc 100644 --- a/fs/ksmbd/mgmt/share_config.c +++ b/fs/ksmbd/mgmt/share_config.c @@ -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 @@ static struct ksmbd_share_config *share_config_request(const char *name) 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, diff --git a/fs/ksmbd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h index 7f7e89ecfe61..3fd338293942 100644 --- a/fs/ksmbd/mgmt/share_config.h +++ b/fs/ksmbd/mgmt/share_config.h @@ -9,6 +9,7 @@ #include #include #include +#include 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__ */ diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c index 867c0286b901..8ce17b3fb8da 100644 --- a/fs/ksmbd/mgmt/tree_connect.c +++ b/fs/ksmbd/mgmt/tree_connect.c @@ -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; diff --git a/fs/ksmbd/misc.c b/fs/ksmbd/misc.c index 28459b1efaa8..9e8afaa686e3 100644 --- a/fs/ksmbd/misc.c +++ b/fs/ksmbd/misc.c @@ -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); } /** diff --git a/fs/ksmbd/misc.h b/fs/ksmbd/misc.h index cc72f4e6baf2..1facfcd21200 100644 --- a/fs/ksmbd/misc.h +++ b/fs/ksmbd/misc.h @@ -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);