From patchwork Wed Jun 28 00:24:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Alcantara X-Patchwork-Id: 13295113 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 AA319EB64D9 for ; Wed, 28 Jun 2023 00:25:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229495AbjF1AZP (ORCPT ); Tue, 27 Jun 2023 20:25:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60646 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229998AbjF1AZO (ORCPT ); Tue, 27 Jun 2023 20:25:14 -0400 Received: from mx.manguebit.com (mx.manguebit.com [167.235.159.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 47E11296B for ; Tue, 27 Jun 2023 17:25:10 -0700 (PDT) From: Paulo Alcantara DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=manguebit.com; s=dkim; t=1687911903; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=FLyGagQGGychTGKAdAB93meS/kugJhrMmMdQYJ3jgOs=; b=pIXFhRQxy2e7WeIEQBC7hL5o8PKlmX6Opsf8IwyA5LbWA1+wB7SdRZE9btoVa21puhxqBZ c7env4gOv8TUF5q+sDOTg2cPNWUJx23vDVMqG5u0ed079TxABPNfwJUCK7ucf3zIXMxxMp VZ8UzIjyokFFxqM0PIotzzfVbS5Qu69lBiIrm6IOR0mwzAndErEhdhaVdk9mir/Hqtz3Lb NhjMUvcnLX3p2R6Q6FnHw8DYOC2E8xqQBPdm3h3RTTtGRE8+yClsxFRnljQW1M8HTMnfry mb1sh2FFt6g+gLuvYX3Jg6CFYB4cvGPhFY0Ihy3oM3B0REZm6Ku2ESMZUv/SPg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=manguebit.com; s=dkim; t=1687911903; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=FLyGagQGGychTGKAdAB93meS/kugJhrMmMdQYJ3jgOs=; b=oEUTyP+37TAY4Ih/EQ7eykr7OuQQ+kiG28ex8VWHFB3lfqhyThKFxEdSAPOKKBgygiCBx8 auUMod8H5syMFE6mUeJi9Zkx4HVZUMRAbgRHLYnuvPa0Yi70cVuL+idCy6TUc8VOsFCBWk AvpGypNbq5rRLnoNSCvXguRBdbHBG98LqPog0pKy8uEwJY26Bq4B6gCyQuoLJDkGwXv+3h q+YIKSrlG4QbHdkgXgv1jQQjm/M1vKnZkVeHG0D7iBK+oZ3V8HizLmpd/HxH8gNLWDU+Go kF7G4PmaZOQzwbX9OxSVbGaNgs7cPhPJNAtLeWHbpmemcqAkWS18ZqjjhZo4yQ== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pc@manguebit.com smtp.mailfrom=pc@manguebit.com ARC-Seal: i=1; s=dkim; d=manguebit.com; t=1687911903; a=rsa-sha256; cv=none; b=h8XKPBfYux9MEI4XJLyzVsm9CjoJQXTu2PKnea/exFJU04nzsOBFpfCbnrJ1AhqP4NbZD8 9WZbHbDnYqHLj2PthFxelLODWzib4tgpb7J18nTk6WxD3vm/HEUPBo9Jnj8YUD6M50T9ll tZqrt991GXhpv3//RzyVqfSCc12ajjVnXwCp2DjflmqvSi0KMH056JKZR7LxVUxSyQucgg 7j+YnIfxUTboh8C3cWMNuSZoTlHMaI39ESckzSJEu0zCQxo6ie4eh5sB29C1LkVDSswFFW Glisa6X1JL6WH767dVlddQzjBhpoG7Atxk7A2GFUXq5LvhnAsRVmt5XOZdZkzw== To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, Paulo Alcantara Subject: [PATCH 1/4] smb: client: fix parsing of source mount option Date: Tue, 27 Jun 2023 21:24:47 -0300 Message-ID: <20230628002450.18781-1-pc@manguebit.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Handle trailing and leading separators when parsing UNC and prefix paths in smb3_parse_devname(). Then, store the sanitised paths in smb3_fs_context::source. This fixes the following cases $ mount //srv/share// /mnt/1 -o ... $ cat /mnt/1/d0/f0 cat: /mnt/1/d0/f0: Invalid argument The -EINVAL was returned because the client sent SMB2_CREATE "\\d0\f0" rather than SMB2_CREATE "\d0\f0". $ mount //srv//share /mnt/1 -o ... mount: Invalid argument The -EINVAL was returned correctly although the client only realised it after sending a couple of bad requests rather than bailing out earlier when parsing mount options. Signed-off-by: Paulo Alcantara (SUSE) --- fs/smb/client/cifs_dfs_ref.c | 28 +++++++++++------ fs/smb/client/cifsproto.h | 2 ++ fs/smb/client/dfs.c | 38 ++--------------------- fs/smb/client/fs_context.c | 59 ++++++++++++++++++++++++++++++------ fs/smb/client/misc.c | 17 +++++++---- 5 files changed, 84 insertions(+), 60 deletions(-) diff --git a/fs/smb/client/cifs_dfs_ref.c b/fs/smb/client/cifs_dfs_ref.c index 0329a907bdfe..b1c2499b1c3b 100644 --- a/fs/smb/client/cifs_dfs_ref.c +++ b/fs/smb/client/cifs_dfs_ref.c @@ -118,12 +118,12 @@ cifs_build_devname(char *nodename, const char *prepath) return dev; } -static int set_dest_addr(struct smb3_fs_context *ctx, const char *full_path) +static int set_dest_addr(struct smb3_fs_context *ctx) { struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; int rc; - rc = dns_resolve_server_name_to_ip(full_path, addr, NULL); + rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL); if (!rc) cifs_set_port(addr, ctx->port); return rc; @@ -171,10 +171,9 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) mnt = ERR_CAST(full_path); goto out; } - cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path); tmp = *cur_ctx; - tmp.source = full_path; + tmp.source = NULL; tmp.leaf_fullpath = NULL; tmp.UNC = tmp.prepath = NULL; tmp.dfs_root_ses = NULL; @@ -185,13 +184,22 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) goto out; } - rc = set_dest_addr(ctx, full_path); - if (rc) { - mnt = ERR_PTR(rc); - goto out; - } - rc = smb3_parse_devname(full_path, ctx); + if (rc) { + mnt = ERR_PTR(rc); + goto out; + } + + ctx->source = smb3_fs_context_fullpath(ctx, '/'); + if (IS_ERR(ctx->source)) { + mnt = ERR_CAST(ctx->source); + ctx->source = NULL; + goto out; + } + cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s dstaddr=%pISpc\n", + __func__, ctx->source, ctx->UNC, ctx->prepath, &ctx->dstaddr); + + rc = set_dest_addr(ctx); if (!rc) mnt = fc_mount(fc); else diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index d127aded2f28..293c54867d94 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -85,6 +85,8 @@ extern void release_mid(struct mid_q_entry *mid); extern void cifs_wake_up_task(struct mid_q_entry *mid); extern int cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid); +extern char *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx, + char dirsep); extern int smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx); extern int smb3_parse_opt(const char *options, const char *key, char **val); extern int cifs_ipaddr_cmp(struct sockaddr *srcaddr, struct sockaddr *rhs); diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c index 2390b2fedd6a..d741f396c527 100644 --- a/fs/smb/client/dfs.c +++ b/fs/smb/client/dfs.c @@ -54,39 +54,6 @@ int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_para return rc; } -/* - * cifs_build_path_to_root returns full path to root when we do not have an - * existing connection (tcon) - */ -static char *build_unc_path_to_root(const struct smb3_fs_context *ctx, - const struct cifs_sb_info *cifs_sb, bool useppath) -{ - char *full_path, *pos; - unsigned int pplen = useppath && ctx->prepath ? strlen(ctx->prepath) + 1 : 0; - unsigned int unc_len = strnlen(ctx->UNC, MAX_TREE_SIZE + 1); - - if (unc_len > MAX_TREE_SIZE) - return ERR_PTR(-EINVAL); - - full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL); - if (full_path == NULL) - return ERR_PTR(-ENOMEM); - - memcpy(full_path, ctx->UNC, unc_len); - pos = full_path + unc_len; - - if (pplen) { - *pos = CIFS_DIR_SEP(cifs_sb); - memcpy(pos + 1, ctx->prepath, pplen); - pos += pplen; - } - - *pos = '\0'; /* add trailing null */ - convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); - cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path); - return full_path; -} - static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path) { struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; @@ -179,6 +146,7 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) struct TCP_Server_Info *server; struct cifs_tcon *tcon; char *origin_fullpath = NULL; + char sep = CIFS_DIR_SEP(cifs_sb); int num_links = 0; int rc; @@ -186,7 +154,7 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) if (IS_ERR(ref_path)) return PTR_ERR(ref_path); - full_path = build_unc_path_to_root(ctx, cifs_sb, true); + full_path = smb3_fs_context_fullpath(ctx, sep); if (IS_ERR(full_path)) { rc = PTR_ERR(full_path); full_path = NULL; @@ -228,7 +196,7 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) kfree(full_path); ref_path = full_path = NULL; - full_path = build_unc_path_to_root(ctx, cifs_sb, true); + full_path = smb3_fs_context_fullpath(ctx, sep); if (IS_ERR(full_path)) { rc = PTR_ERR(full_path); full_path = NULL; diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index 226d71e12db0..a4b80babd03e 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -442,14 +442,17 @@ int smb3_parse_opt(const char *options, const char *key, char **val) * but there are some bugs that prevent rename from working if there are * multiple delimiters. * - * Returns a sanitized duplicate of @path. @gfp indicates the GFP_* flags - * for kstrdup. + * Return a sanitized duplicate of @path or NULL for empty prefix paths. + * Otherwise, return ERR_PTR. + * + * @gfp indicates the GFP_* flags for kstrdup. * The caller is responsible for freeing the original. */ #define IS_DELIM(c) ((c) == '/' || (c) == '\\') char *cifs_sanitize_prepath(char *prepath, gfp_t gfp) { char *cursor1 = prepath, *cursor2 = prepath; + char *s; /* skip all prepended delimiters */ while (IS_DELIM(*cursor1)) @@ -470,8 +473,39 @@ char *cifs_sanitize_prepath(char *prepath, gfp_t gfp) if (IS_DELIM(*(cursor2 - 1))) cursor2--; - *(cursor2) = '\0'; - return kstrdup(prepath, gfp); + *cursor2 = '\0'; + if (!*prepath) + return NULL; + s = kstrdup(prepath, gfp); + if (!s) + return ERR_PTR(-ENOMEM); + return s; +} + +/* + * Return full path based on the values of @ctx->{UNC,prepath}. + * + * It is assumed that both values were already parsed by smb3_parse_devname(). + */ +char *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx, char dirsep) +{ + size_t ulen, plen; + char *s; + + ulen = strlen(ctx->UNC); + plen = ctx->prepath ? strlen(ctx->prepath) + 1 : 0; + + s = kmalloc(ulen + plen + 1, GFP_KERNEL); + if (!s) + return ERR_PTR(-ENOMEM); + memcpy(s, ctx->UNC, ulen); + if (plen) { + s[ulen] = dirsep; + memcpy(s + ulen + 1, ctx->prepath, plen); + } + s[ulen + plen] = '\0'; + convert_delimiter(s, dirsep); + return s; } /* @@ -485,6 +519,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) char *pos; const char *delims = "/\\"; size_t len; + int rc; if (unlikely(!devname || !*devname)) { cifs_dbg(VFS, "Device name not specified\n"); @@ -512,6 +547,8 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) /* now go until next delimiter or end of string */ len = strcspn(pos, delims); + if (!len) + return -EINVAL; /* move "pos" up to delimiter or NULL */ pos += len; @@ -534,8 +571,11 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) return 0; ctx->prepath = cifs_sanitize_prepath(pos, GFP_KERNEL); - if (!ctx->prepath) - return -ENOMEM; + if (IS_ERR(ctx->prepath)) { + rc = PTR_ERR(ctx->prepath); + ctx->prepath = NULL; + return rc; + } return 0; } @@ -1150,12 +1190,13 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, cifs_errorf(fc, "Unknown error parsing devname\n"); goto cifs_parse_mount_err; } - ctx->source = kstrdup(param->string, GFP_KERNEL); - if (ctx->source == NULL) { + ctx->source = smb3_fs_context_fullpath(ctx, '/'); + if (IS_ERR(ctx->source)) { + ctx->source = NULL; cifs_errorf(fc, "OOM when copying UNC string\n"); goto cifs_parse_mount_err; } - fc->source = kstrdup(param->string, GFP_KERNEL); + fc->source = kstrdup(ctx->source, GFP_KERNEL); if (fc->source == NULL) { cifs_errorf(fc, "OOM when copying UNC string\n"); goto cifs_parse_mount_err; diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index cd914be905b2..609d0c0d9eca 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -1198,16 +1198,21 @@ int match_target_ip(struct TCP_Server_Info *server, int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix) { + int rc; + kfree(cifs_sb->prepath); + cifs_sb->prepath = NULL; if (prefix && *prefix) { cifs_sb->prepath = cifs_sanitize_prepath(prefix, GFP_ATOMIC); - if (!cifs_sb->prepath) - return -ENOMEM; - - convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); - } else - cifs_sb->prepath = NULL; + if (IS_ERR(cifs_sb->prepath)) { + rc = PTR_ERR(cifs_sb->prepath); + cifs_sb->prepath = NULL; + return rc; + } + if (cifs_sb->prepath) + convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); + } cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; return 0; From patchwork Wed Jun 28 00:24:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Alcantara X-Patchwork-Id: 13295114 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 9B1DAC0015E for ; Wed, 28 Jun 2023 00:25:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230403AbjF1AZQ (ORCPT ); Tue, 27 Jun 2023 20:25:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230401AbjF1AZO (ORCPT ); Tue, 27 Jun 2023 20:25:14 -0400 Received: from mx.manguebit.com (mx.manguebit.com [167.235.159.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8C93126BC for ; Tue, 27 Jun 2023 17:25:11 -0700 (PDT) From: Paulo Alcantara DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=manguebit.com; s=dkim; t=1687911910; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=egWw9iBC97+iu1C89lJyAYU8tObTsqIBXbqUeoZfZ5U=; b=XJUpejsIG8of/gT6LvZA8WfjFN8hzkymTzJeHJgOfIyAeY80rTHGQOmqm/GP1gB2Et5IQI 1VoORrFbRu3nELO+3KsA01DIxcq0QhUIyS8hrz/hRw00LZ///V6tAYASpM1ewylQ8lPLoa qpczEcLkZiZWYM40SmyCNrQ/L4LIk4RDdPPn7Q4z5KG1knFkT2pS9ciIbbq1OWwJKUIFgD 9xXt+25Kzw4dfO3YyA7PxAKPA0DWPCG8SPOdlOPwS5/LmY0jdc1AGwEFGaZPXFucQaGf1m wYieJxIJeLGptGj8PiVGRZU6HaL6R2JXl/9l4EDTjozFMbcs6MCtDGO1HL4sSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=manguebit.com; s=dkim; t=1687911910; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=egWw9iBC97+iu1C89lJyAYU8tObTsqIBXbqUeoZfZ5U=; b=RG/gqMJICDi24qHii1ej1hnhmwOsrKWayXlkh0OUvVXAPe0t/vBATYlvjbM+92GUWLtCfw 1jdyz/wKBSZ6Lr1TntxoINbzChSumTkCXR7nGwLHvFw34PgpkMFcYYcyFopjm221thOcln o9HrmumzQYbp28KjJZk0GSm3b0ByDF9vtXG5I0FZe5XlWrl10r9ZDoB9qiwsjiatU3DayL PkKhMx3oUukE1bCrnjdhOG0KsUoGV+uKAe9uc8dJPIIfUJZ9mxoqfviLwcpuuvzh+zPch6 /Bpi0f9PCZKje5voRL4HX3gf7gs04nevY6GtlpOalkIRbvcNmCBkss2eKYwUzA== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pc@manguebit.com smtp.mailfrom=pc@manguebit.com ARC-Seal: i=1; s=dkim; d=manguebit.com; t=1687911910; a=rsa-sha256; cv=none; b=n9NqYa/kA/S/8E5H4da+EhBqpjMkpadwr4VjZve5/jlXL1ADIps6KPnlvEWIAIEU41DBYX ZV/U/0UYaqSaojRBPCUpEibQ1MqwVLAqLEkoHW5Lh6DTryJ/F+OGgT4qsvHxethUUcevXM v29TN0g+Vq0aAV8fcciN5hWjzwlWlHGm2yo1AYAs0MPs5TBVA/C7N9LSEcD7AJIQnHFJx7 BUoKruRxTzEffZuKLYSi/2AFSFb9s2ClAEyIqvAWjzeyu0gtCyPiWkz6yXXj+4rJHPB6PK 6EaexP1hND5IMQ/gUUrfzBGIVFMa87hjqEIWOopV7te238h6we2S1tgbZ5klFA== To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, Paulo Alcantara Subject: [PATCH 2/4] smb: client: fix shared DFS root mounts with different prefixes Date: Tue, 27 Jun 2023 21:24:48 -0300 Message-ID: <20230628002450.18781-2-pc@manguebit.com> In-Reply-To: <20230628002450.18781-1-pc@manguebit.com> References: <20230628002450.18781-1-pc@manguebit.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org When having two DFS root mounts that are connected to same namespace, same mount options but different prefix paths, we can't really use the shared @server->origin_fullpath when chasing DFS links in them. Move the origin_fullpath field to cifs_tcon structure so when having shared DFS root mounts with different prefix paths, and we need to chase any DFS links, dfs_get_automount_devname() will pick up the correct full path out of the @tcon that will be used for the new mount. Before patch mount.cifs //dom/dfs/dir /mnt/1 -o ... mount.cifs //dom/dfs /mnt/2 -o ... # shared server, ses, tcon # server: origin_fullpath=//dom/dfs/dir # @server->origin_fullpath + '/dir/link1' $ ls /mnt/2/dir/link1 ls: cannot open directory '/mnt/2/dir/link1': No such file or directory After patch mount.cifs //dom/dfs/dir /mnt/1 -o ... mount.cifs //dom/dfs /mnt/2 -o ... # shared server & ses # tcon_1: origin_fullpath=//dom/dfs/dir # tcon_2: origin_fullpath=//dom/dfs # @tcon_2->origin_fullpath + '/dir/link1' $ ls /mnt/2/dir/link1 dir0 dir1 dir10 dir3 dir5 dir6 dir7 dir9 target2_file.txt tsub Fixes: 8e3554150d6c ("cifs: fix sharing of DFS connections") Signed-off-by: Paulo Alcantara (SUSE) --- fs/smb/client/cifs_debug.c | 16 +++++---- fs/smb/client/cifsglob.h | 10 +++--- fs/smb/client/cifsproto.h | 2 +- fs/smb/client/connect.c | 70 ++++++++++++++++++++++---------------- fs/smb/client/dfs.c | 30 +++++----------- fs/smb/client/dfs.h | 19 +++++------ fs/smb/client/dfs_cache.c | 8 +++-- fs/smb/client/misc.c | 37 +++++++++++++++----- 8 files changed, 105 insertions(+), 87 deletions(-) diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c index 2c771c84b970..f82dd7e0ec77 100644 --- a/fs/smb/client/cifs_debug.c +++ b/fs/smb/client/cifs_debug.c @@ -123,6 +123,12 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon) seq_puts(m, " nosparse"); if (tcon->need_reconnect) seq_puts(m, "\tDISCONNECTED "); + spin_lock(&tcon->tc_lock); + if (tcon->origin_fullpath) { + seq_printf(m, "\n\tDFS origin fullpath: %s", + tcon->origin_fullpath); + } + spin_unlock(&tcon->tc_lock); seq_putc(m, '\n'); } @@ -465,13 +471,9 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) seq_printf(m, "\nIn Send: %d In MaxReq Wait: %d", atomic_read(&server->in_send), atomic_read(&server->num_waiters)); - if (IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)) { - if (server->origin_fullpath) - seq_printf(m, "\nDFS origin full path: %s", - server->origin_fullpath); - if (server->leaf_fullpath) - seq_printf(m, "\nDFS leaf full path: %s", - server->leaf_fullpath); + if (server->leaf_fullpath) { + seq_printf(m, "\nDFS leaf full path: %s", + server->leaf_fullpath); } seq_printf(m, "\n\n\tSessions: "); diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 30e7f350f95a..cb38c29b9a73 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -736,23 +736,20 @@ struct TCP_Server_Info { #endif struct mutex refpath_lock; /* protects leaf_fullpath */ /* - * origin_fullpath: Canonical copy of smb3_fs_context::source. - * It is used for matching existing DFS tcons. - * * leaf_fullpath: Canonical DFS referral path related to this * connection. * It is used in DFS cache refresher, reconnect and may * change due to nested DFS links. * - * Both protected by @refpath_lock and @srv_lock. The @refpath_lock is - * mosly used for not requiring a copy of @leaf_fullpath when getting + * Protected by @refpath_lock and @srv_lock. The @refpath_lock is + * mostly used for not requiring a copy of @leaf_fullpath when getting * cached or new DFS referrals (which might also sleep during I/O). * While @srv_lock is held for making string and NULL comparions against * both fields as in mount(2) and cache refresh. * * format: \\HOST\SHARE[\OPTIONAL PATH] */ - char *origin_fullpath, *leaf_fullpath; + char *leaf_fullpath; }; static inline bool is_smb1(struct TCP_Server_Info *server) @@ -1206,6 +1203,7 @@ struct cifs_tcon { struct delayed_work dfs_cache_work; #endif struct delayed_work query_interfaces; /* query interfaces workqueue job */ + char *origin_fullpath; /* canonical copy of smb3_fs_context::source */ }; /* diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 293c54867d94..2dc390839aca 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -652,7 +652,7 @@ int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov, int resp_buftype, struct cifs_search_info *srch_inf); -struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server); +struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon); void cifs_put_tcp_super(struct super_block *sb); int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix); char *extract_hostname(const char *unc); diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index ca77aaa1d91c..60f5c8652cd7 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -996,7 +996,6 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) */ } - kfree(server->origin_fullpath); kfree(server->leaf_fullpath); kfree(server); @@ -1436,7 +1435,9 @@ match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) } /* this function must be called with srv_lock held */ -static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) +static int match_server(struct TCP_Server_Info *server, + struct smb3_fs_context *ctx, + bool match_super) { struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; @@ -1467,36 +1468,38 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context * (struct sockaddr *)&server->srcaddr)) return 0; /* - * - Match for an DFS tcon (@server->origin_fullpath). - * - Match for an DFS root server connection (@server->leaf_fullpath). - * - If none of the above and @ctx->leaf_fullpath is set, then - * it is a new DFS connection. - * - If 'nodfs' mount option was passed, then match only connections - * that have no DFS referrals set - * (e.g. can't failover to other targets). + * When matching cifs.ko superblocks (@match_super == true), we can't + * really match either @server->leaf_fullpath or @server->dstaddr + * directly since this @server might belong to a completely different + * server -- in case of domain-based DFS referrals or DFS links -- as + * provided earlier by mount(2) through 'source' and 'ip' options. + * + * Otherwise, match the DFS referral in @server->leaf_fullpath or the + * destination address in @server->dstaddr. + * + * When using 'nodfs' mount option, we avoid sharing it with DFS + * connections as they might failover. */ - if (!ctx->nodfs) { - if (ctx->source && server->origin_fullpath) { - if (!dfs_src_pathname_equal(ctx->source, - server->origin_fullpath)) + if (!match_super) { + if (!ctx->nodfs) { + if (server->leaf_fullpath) { + if (!ctx->leaf_fullpath || + strcasecmp(server->leaf_fullpath, + ctx->leaf_fullpath)) + return 0; + } else if (ctx->leaf_fullpath) { return 0; + } } else if (server->leaf_fullpath) { - if (!ctx->leaf_fullpath || - strcasecmp(server->leaf_fullpath, - ctx->leaf_fullpath)) - return 0; - } else if (ctx->leaf_fullpath) { return 0; } - } else if (server->origin_fullpath || server->leaf_fullpath) { - return 0; } /* * Match for a regular connection (address/hostname/port) which has no * DFS referrals set. */ - if (!server->origin_fullpath && !server->leaf_fullpath && + if (!server->leaf_fullpath && (strcasecmp(server->hostname, ctx->server_hostname) || !match_server_address(server, addr) || !match_port(server, addr))) @@ -1532,7 +1535,8 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx) * Skip ses channels since they're only handled in lower layers * (e.g. cifs_send_recv). */ - if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) { + if (CIFS_SERVER_IS_CHAN(server) || + !match_server(server, ctx, false)) { spin_unlock(&server->srv_lock); continue; } @@ -2321,10 +2325,16 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) if (tcon->status == TID_EXITING) return 0; - /* Skip UNC validation when matching DFS connections or superblocks */ - if (!server->origin_fullpath && !server->leaf_fullpath && - strncmp(tcon->tree_name, ctx->UNC, MAX_TREE_SIZE)) + + if (tcon->origin_fullpath) { + if (!ctx->source || + !dfs_src_pathname_equal(ctx->source, + tcon->origin_fullpath)) + return 0; + } else if (!server->leaf_fullpath && + strncmp(tcon->tree_name, ctx->UNC, MAX_TREE_SIZE)) { return 0; + } if (tcon->seal != ctx->seal) return 0; if (tcon->snapshot_time != ctx->snapshot_time) @@ -2726,7 +2736,7 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) } static int match_prepath(struct super_block *sb, - struct TCP_Server_Info *server, + struct cifs_tcon *tcon, struct cifs_mnt_data *mnt_data) { struct smb3_fs_context *ctx = mnt_data->ctx; @@ -2737,8 +2747,8 @@ static int match_prepath(struct super_block *sb, bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && new->prepath; - if (server->origin_fullpath && - dfs_src_pathname_equal(server->origin_fullpath, ctx->source)) + if (tcon->origin_fullpath && + dfs_src_pathname_equal(tcon->origin_fullpath, ctx->source)) return 1; if (old_set && new_set && !strcmp(new->prepath, old->prepath)) @@ -2787,10 +2797,10 @@ cifs_match_super(struct super_block *sb, void *data) spin_lock(&ses->ses_lock); spin_lock(&ses->chan_lock); spin_lock(&tcon->tc_lock); - if (!match_server(tcp_srv, ctx) || + if (!match_server(tcp_srv, ctx, true) || !match_session(ses, ctx) || !match_tcon(tcon, ctx) || - !match_prepath(sb, tcp_srv, mnt_data)) { + !match_prepath(sb, tcon, mnt_data)) { rc = 0; goto out; } diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c index d741f396c527..afbaef05a1f1 100644 --- a/fs/smb/client/dfs.c +++ b/fs/smb/client/dfs.c @@ -217,14 +217,12 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) server = mnt_ctx->server; tcon = mnt_ctx->tcon; - mutex_lock(&server->refpath_lock); - spin_lock(&server->srv_lock); - if (!server->origin_fullpath) { - server->origin_fullpath = origin_fullpath; + spin_lock(&tcon->tc_lock); + if (!tcon->origin_fullpath) { + tcon->origin_fullpath = origin_fullpath; origin_fullpath = NULL; } - spin_unlock(&server->srv_lock); - mutex_unlock(&server->refpath_lock); + spin_unlock(&tcon->tc_lock); if (list_empty(&tcon->dfs_ses_list)) { list_replace_init(&mnt_ctx->dfs_ses_list, @@ -247,18 +245,13 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) { struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; struct cifs_ses *ses; - char *source = ctx->source; bool nodfs = ctx->nodfs; int rc; *isdfs = false; - /* Temporarily set @ctx->source to NULL as we're not matching DFS - * superblocks yet. See cifs_match_super() and match_server(). - */ - ctx->source = NULL; rc = get_session(mnt_ctx, NULL); if (rc) - goto out; + return rc; ctx->dfs_root_ses = mnt_ctx->ses; /* @@ -272,7 +265,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) rc = dfs_get_referral(mnt_ctx, ctx->UNC + 1, NULL, NULL); if (rc) { if (rc != -ENOENT && rc != -EOPNOTSUPP && rc != -EIO) - goto out; + return rc; nodfs = true; } } @@ -280,7 +273,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) rc = cifs_mount_get_tcon(mnt_ctx); if (!rc) rc = cifs_is_path_remote(mnt_ctx); - goto out; + return rc; } *isdfs = true; @@ -296,12 +289,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) rc = __dfs_mount_share(mnt_ctx); if (ses == ctx->dfs_root_ses) cifs_put_smb_ses(ses); -out: - /* - * Restore previous value of @ctx->source so DFS superblock can be - * matched in cifs_match_super(). - */ - ctx->source = source; + return rc; } @@ -571,7 +559,7 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru goto out; } - sb = cifs_get_tcp_super(server); + sb = cifs_get_tcon_super(tcon); if (IS_ERR(sb)) { rc = PTR_ERR(sb); cifs_dbg(VFS, "%s: could not find superblock: %d\n", __func__, rc); diff --git a/fs/smb/client/dfs.h b/fs/smb/client/dfs.h index 1c90df5ecfbd..98e9d2aca6a7 100644 --- a/fs/smb/client/dfs.h +++ b/fs/smb/client/dfs.h @@ -39,16 +39,15 @@ static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page) { struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - struct TCP_Server_Info *server = tcon->ses->server; size_t len; char *s; - spin_lock(&server->srv_lock); - if (unlikely(!server->origin_fullpath)) { - spin_unlock(&server->srv_lock); + spin_lock(&tcon->tc_lock); + if (unlikely(!tcon->origin_fullpath)) { + spin_unlock(&tcon->tc_lock); return ERR_PTR(-EREMOTE); } - spin_unlock(&server->srv_lock); + spin_unlock(&tcon->tc_lock); s = dentry_path_raw(dentry, page, PATH_MAX); if (IS_ERR(s)) @@ -57,16 +56,16 @@ static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page) if (!s[1]) s++; - spin_lock(&server->srv_lock); - len = strlen(server->origin_fullpath); + spin_lock(&tcon->tc_lock); + len = strlen(tcon->origin_fullpath); if (s < (char *)page + len) { - spin_unlock(&server->srv_lock); + spin_unlock(&tcon->tc_lock); return ERR_PTR(-ENAMETOOLONG); } s -= len; - memcpy(s, server->origin_fullpath, len); - spin_unlock(&server->srv_lock); + memcpy(s, tcon->origin_fullpath, len); + spin_unlock(&tcon->tc_lock); convert_delimiter(s, '/'); return s; diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c index 1513b2709889..33adf43a01f1 100644 --- a/fs/smb/client/dfs_cache.c +++ b/fs/smb/client/dfs_cache.c @@ -1248,18 +1248,20 @@ static int refresh_tcon(struct cifs_tcon *tcon, bool force_refresh) int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb) { struct cifs_tcon *tcon; - struct TCP_Server_Info *server; if (!cifs_sb || !cifs_sb->master_tlink) return -EINVAL; tcon = cifs_sb_master_tcon(cifs_sb); - server = tcon->ses->server; - if (!server->origin_fullpath) { + spin_lock(&tcon->tc_lock); + if (!tcon->origin_fullpath) { + spin_unlock(&tcon->tc_lock); cifs_dbg(FYI, "%s: not a dfs mount\n", __func__); return 0; } + spin_unlock(&tcon->tc_lock); + /* * After reconnecting to a different server, unique ids won't match anymore, so we disable * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE). diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 609d0c0d9eca..27245326ffd0 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -156,6 +156,7 @@ tconInfoFree(struct cifs_tcon *tcon) #ifdef CONFIG_CIFS_DFS_UPCALL dfs_put_root_smb_sessions(&tcon->dfs_ses_list); #endif + kfree(tcon->origin_fullpath); kfree(tcon); } @@ -1106,20 +1107,25 @@ struct super_cb_data { struct super_block *sb; }; -static void tcp_super_cb(struct super_block *sb, void *arg) +static void tcon_super_cb(struct super_block *sb, void *arg) { struct super_cb_data *sd = arg; - struct TCP_Server_Info *server = sd->data; struct cifs_sb_info *cifs_sb; - struct cifs_tcon *tcon; + struct cifs_tcon *t1 = sd->data, *t2; if (sd->sb) return; cifs_sb = CIFS_SB(sb); - tcon = cifs_sb_master_tcon(cifs_sb); - if (tcon->ses->server == server) + t2 = cifs_sb_master_tcon(cifs_sb); + + spin_lock(&t2->tc_lock); + if (t1->ses == t2->ses && + t1->ses->server == t2->ses->server && + t2->origin_fullpath && + dfs_src_pathname_equal(t2->origin_fullpath, t1->origin_fullpath)) sd->sb = sb; + spin_unlock(&t2->tc_lock); } static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *), @@ -1154,9 +1160,15 @@ static void __cifs_put_super(struct super_block *sb) cifs_sb_deactive(sb); } -struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server) +struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon) { - return __cifs_get_super(tcp_super_cb, server); + spin_lock(&tcon->tc_lock); + if (unlikely(!tcon->origin_fullpath)) { + spin_unlock(&tcon->tc_lock); + return ERR_PTR(-ENOENT); + } + spin_unlock(&tcon->tc_lock); + return __cifs_get_super(tcon_super_cb, tcon); } void cifs_put_tcp_super(struct super_block *sb) @@ -1243,9 +1255,16 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid, */ if (strlen(full_path) < 2 || !cifs_sb || (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) || - !is_tcon_dfs(tcon) || !ses->server->origin_fullpath) + !is_tcon_dfs(tcon)) return 0; + spin_lock(&tcon->tc_lock); + if (!tcon->origin_fullpath) { + spin_unlock(&tcon->tc_lock); + return 0; + } + spin_unlock(&tcon->tc_lock); + /* * Slow path - tcon is DFS and @full_path has prefix path, so attempt * to get a referral to figure out whether it is an DFS link. @@ -1269,7 +1288,7 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid, /* * XXX: we are not using dfs_cache_find() here because we might - * end filling all the DFS cache and thus potentially + * end up filling all the DFS cache and thus potentially * removing cached DFS targets that the client would eventually * need during failover. */ From patchwork Wed Jun 28 00:24:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Alcantara X-Patchwork-Id: 13295116 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 A7F6FEB64DC for ; Wed, 28 Jun 2023 00:25:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230401AbjF1AZR (ORCPT ); Tue, 27 Jun 2023 20:25:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60680 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230405AbjF1AZQ (ORCPT ); Tue, 27 Jun 2023 20:25:16 -0400 Received: from mx.manguebit.com (mx.manguebit.com [167.235.159.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 621022728 for ; Tue, 27 Jun 2023 17:25:15 -0700 (PDT) From: Paulo Alcantara DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=manguebit.com; s=dkim; t=1687911911; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vjpwrEwjGLoRuhV3Dp39DD6epcioRRaNILQC+qjWAbg=; b=fY/6409GVJGY/G1ndOMMz8EtYzpQ7WAB3Sz3ZwolocrrF0WF/wwtW1U9bt+KBBDHxC1YAf WaaxynBUNp0WHVsEv7Ts8O6xalnC/ypo0ntb2dqn9yceN2/pj9IwIiSojo1U6E7Xc7AI3c 2gw6dR/YNqO+9zukdeJUavmXIqJtNhj9hzbGajWRpgCokR4b7y4oM3+0TtCPz0+LmPyN9Q xkALjy7tg/mfOA/i68m/O6+TXmnXWu1g8oJ73WmcL3Y9OAiORosbqb/1B96OxMdwZJDTb4 pfd0+osF6RrKcGzv62vgiI0Y6c5OkAJoKPr3I9+TAmMCuI9YfvbuKo55E3N3Pg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=manguebit.com; s=dkim; t=1687911911; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vjpwrEwjGLoRuhV3Dp39DD6epcioRRaNILQC+qjWAbg=; b=lDXC4DdNqfLdnw/j89gY4qB1BxwUtn5cS/Re5rbcJKD3Qo3l3CafQ/7V3pfPsa/gGEuORo EVILYOQ6xANHeGdZ6kSUCxPRF/fuALIMqg0OeqEaRnudrT5Al6aDcKVa8BcHGLkEOIDMk8 jHkL+YxYX7ndxxQgYLVXvgmWTjEnZgh/vWfylGV/IApTPqhHZwDuDeCrFtvcI7/PoAOlZB UpGgjVmv7IOOAK/kTtpS1o6b7EtDQ/JGmjghSLes0+RJxREG0kbctpDK/KCWB8i9/RKheq c8KIc13C1Rpt66sMNdWyr+Y8I9QulQwwjxjjvKCpMqn7I6fN1CbDgJxlBps57Q== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pc@manguebit.com smtp.mailfrom=pc@manguebit.com ARC-Seal: i=1; s=dkim; d=manguebit.com; t=1687911911; a=rsa-sha256; cv=none; b=s/BGicgR8Z1ikIiCbETvscvIu00VXtDpjV22cmKpIz4jQHwG6X+plR4xrLVxB2AemHoOH9 Zj/prW/hk19R58ca65HnhI93ZQmkIdxYLmD4Y0yA24ITtsQ46oaEQz9ogwfHa85p8MixPE 38Pwml0FYthsEzF7j3ZRyNm2ABCe2VQ49okh1/IEdCbeSkhanPTUAToK1TzVMbEAnRdwuX 8qnv93YVDfzMeZ1IT2sUeYsbF+ElCpaDO7Vaxk5dP60+mN8UEadMYskh8+LtNJh4ylnm8T EdwgugUFJpqNZ8NK41/D+wEPn3zlkAN5+Hhed9+cUQ76UKXd6WUargGzz/SSJQ== To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, Paulo Alcantara Subject: [PATCH 3/4] smb: client: fix broken file attrs with nodfs mounts Date: Tue, 27 Jun 2023 21:24:49 -0300 Message-ID: <20230628002450.18781-3-pc@manguebit.com> In-Reply-To: <20230628002450.18781-1-pc@manguebit.com> References: <20230628002450.18781-1-pc@manguebit.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org *_get_inode_info() functions expect -EREMOTE when query path info calls find a DFS link, regardless whether !CONFIG_CIFS_DFS_UPCALL or 'nodfs' mount option. Otherwise, those files will miss the fake DFS file attributes. Before patch $ mount.cifs //srv/dfs /mnt/1 -o ...,nodfs $ ls -l /mnt/1 ls: cannot access '/mnt/1/link': Operation not supported total 0 -rwxr-xr-x 1 root root 0 Jul 26 2022 dfstest2_file1.txt drwxr-xr-x 2 root root 0 Aug 8 2022 dir1 d????????? ? ? ? ? ? link After patch $ mount.cifs //srv/dfs /mnt/1 -o ...,nodfs $ ls -l /mnt/1 total 0 -rwxr-xr-x 1 root root 0 Jul 26 2022 dfstest2_file1.txt drwxr-xr-x 2 root root 0 Aug 8 2022 dir1 drwx--x--x 2 root root 0 Jun 26 20:29 link Fixes: c877ce47e137 ("cifs: reduce roundtrips on create/qinfo requests") Signed-off-by: Paulo Alcantara (SUSE) --- fs/smb/client/smb2inode.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index 7e3ac4cb4efa..8e696fbd72fa 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -609,9 +609,6 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, if (islink) rc = -EREMOTE; } - if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb && - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)) - rc = -EOPNOTSUPP; } out: From patchwork Wed Jun 28 00:24:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Alcantara X-Patchwork-Id: 13295115 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 2493DC001DB for ; Wed, 28 Jun 2023 00:25:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230384AbjF1AZS (ORCPT ); Tue, 27 Jun 2023 20:25:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60670 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229998AbjF1AZP (ORCPT ); Tue, 27 Jun 2023 20:25:15 -0400 Received: from mx.manguebit.com (mx.manguebit.com [167.235.159.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 005672704 for ; Tue, 27 Jun 2023 17:25:14 -0700 (PDT) From: Paulo Alcantara DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=manguebit.com; s=dkim; t=1687911913; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=asVZYqVn6NqWCsWUz8xil3gCXbx1Fr+LFBXjP5BH58M=; b=Yzz3B5GzEgChTGAD00ru/SbWau4z2HPco55HUj+NumTDNLjNmlH5a4BNb+bZhe75CSLjYw caO+AJChtiJ5egLlhX+qwtYW9f1fpD86Ky/KJa8RzPKM7vGLGlNeg+aJ4TwRaDXR/YrBHM Q32gTOKNclE8jloyrFIu7KDQvbf94XMymTNcSeVYHs4CuUygR9EmD8ZjRwAlzjbQjusMuh u7pSfS+c0+GIrS8ek3Mt+qfP9BJCCQ2Dk61gP0y50pUbKyv037GJB8T3eMwJyN725Xo6JX RqqYh99+CKAu8YoG2EgNVEdO93uOurSikUBq/DDOzO2dwtKmpduT0AqEbcS1YQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=manguebit.com; s=dkim; t=1687911913; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=asVZYqVn6NqWCsWUz8xil3gCXbx1Fr+LFBXjP5BH58M=; b=OnwYnBh1WjIhdU9JOOKTQzCmfreJbj4O+ZB00qKeSJfcIWKzC8gfGX6IbVduuKdM+17jDM BovMrAJXoiDfdr+dSobKn5ylNccuTi6/DgnyVNwAvLhjSftnMHzrc7ZT+8qj2b7fAafUkc 4SKtNkjr4bKyY/aDkKq+aV3nGll8DVkrIauoJkihnbRUB6JTUhYLS/cMjtm732FH6bYp5U lznKXbkpDaZvyLMudW3CbltJS7x+yq2T7gynbrOj0bud5bZ1YRuEiQEtFJXCx0QHV74cOY btjP8JzVNF9FAZpSgq1U08onAQntPz0ARghdUHK66dQBpyBxbtTKdT8iGOAduQ== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pc@manguebit.com smtp.mailfrom=pc@manguebit.com ARC-Seal: i=1; s=dkim; d=manguebit.com; t=1687911913; a=rsa-sha256; cv=none; b=LCQ/yjTsi4ccCulWxTLbwOl97gfpcWdQo3bIAQb13sjvUCMAA+xgNIo89iL3oxeBoADpkv KVlF9eJ22hVRMEoo7Uj9KLd6atLc5Aa2NNwOvq7BPRhjjxdmx6AcFfdUr2Dyj8lpeEi9UB gp67it3THQ5I5Vd8Sumy3iRFw0rcZkgHsjF/lh9F+WjagM0jKOQAhoyTR4NDAGN7kcP5cL 56/R7e6oaWJ4ZLBLFxykEpus3ASn3ryqEP2GVGBWWeowx+WSM5ZxWP4SR+nznR68pJ4fHl 4AOpRFsRqZty7E3bywePwe0YVk7l8ECfFAGcisOI6n48vlH/nY8n0xbVnMZwJQ== To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, Paulo Alcantara Subject: [PATCH 4/4] smb: client: improve DFS mount check Date: Tue, 27 Jun 2023 21:24:50 -0300 Message-ID: <20230628002450.18781-4-pc@manguebit.com> In-Reply-To: <20230628002450.18781-1-pc@manguebit.com> References: <20230628002450.18781-1-pc@manguebit.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Some servers may return error codes from REQ_GET_DFS_REFERRAL requests that are unexpected by the client, so to make it easier, assume non-DFS mounts when the client can't get the initial DFS referral of @ctx->UNC in dfs_mount_share(). Signed-off-by: Paulo Alcantara (SUSE) --- fs/smb/client/dfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c index afbaef05a1f1..a7f2e0608adf 100644 --- a/fs/smb/client/dfs.c +++ b/fs/smb/client/dfs.c @@ -264,8 +264,9 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) if (!nodfs) { rc = dfs_get_referral(mnt_ctx, ctx->UNC + 1, NULL, NULL); if (rc) { - if (rc != -ENOENT && rc != -EOPNOTSUPP && rc != -EIO) - return rc; + cifs_dbg(FYI, "%s: no dfs referral for %s: %d\n", + __func__, ctx->UNC + 1, rc); + cifs_dbg(FYI, "%s: assuming non-dfs mount...\n", __func__); nodfs = true; } }