From: Greg Kroah-Hartman Date: Thu, 20 Jul 2023 18:10:24 +0000 (+0200) Subject: 6.4-stable patches X-Git-Tag: v5.15.121~88 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8814931463e5e9ab744a2a5f9b6f0f8d0edec77c;p=thirdparty%2Fkernel%2Fstable-queue.git 6.4-stable patches added patches: cifs-fix-session-state-check-in-smb2_find_smb_ses.patch drm-client-send-hotplug-event-after-registering-a-client.patch smb-client-fix-parsing-of-source-mount-option.patch smb-client-improve-dfs-mount-check.patch --- diff --git a/queue-6.4/cifs-fix-session-state-check-in-smb2_find_smb_ses.patch b/queue-6.4/cifs-fix-session-state-check-in-smb2_find_smb_ses.patch new file mode 100644 index 00000000000..297cf02bd25 --- /dev/null +++ b/queue-6.4/cifs-fix-session-state-check-in-smb2_find_smb_ses.patch @@ -0,0 +1,37 @@ +From 66be5c48ee1b5b8c919cc329fe6d32e16badaa40 Mon Sep 17 00:00:00 2001 +From: Winston Wen +Date: Mon, 26 Jun 2023 11:42:57 +0800 +Subject: cifs: fix session state check in smb2_find_smb_ses + +From: Winston Wen + +commit 66be5c48ee1b5b8c919cc329fe6d32e16badaa40 upstream. + +Chech the session state and skip it if it's exiting. + +Signed-off-by: Winston Wen +Reviewed-by: Shyam Prasad N +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/smb2transport.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/fs/smb/client/smb2transport.c ++++ b/fs/smb/client/smb2transport.c +@@ -153,7 +153,14 @@ smb2_find_smb_ses_unlocked(struct TCP_Se + list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + if (ses->Suid != ses_id) + continue; ++ ++ spin_lock(&ses->ses_lock); ++ if (ses->ses_status == SES_EXITING) { ++ spin_unlock(&ses->ses_lock); ++ continue; ++ } + ++ses->ses_count; ++ spin_unlock(&ses->ses_lock); + return ses; + } + diff --git a/queue-6.4/drm-client-send-hotplug-event-after-registering-a-client.patch b/queue-6.4/drm-client-send-hotplug-event-after-registering-a-client.patch new file mode 100644 index 00000000000..48ebe7a5bc4 --- /dev/null +++ b/queue-6.4/drm-client-send-hotplug-event-after-registering-a-client.patch @@ -0,0 +1,254 @@ +From 27655b9bb9f0d9c32b8de8bec649b676898c52d5 Mon Sep 17 00:00:00 2001 +From: Thomas Zimmermann +Date: Mon, 10 Jul 2023 11:10:17 +0200 +Subject: drm/client: Send hotplug event after registering a client +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Zimmermann + +commit 27655b9bb9f0d9c32b8de8bec649b676898c52d5 upstream. + +Generate a hotplug event after registering a client to allow the +client to configure its display. Remove the hotplug calls from the +existing clients for fbdev emulation. This change fixes a concurrency +bug between registering a client and receiving events from the DRM +core. The bug is present in the fbdev emulation of all drivers. + +The fbdev emulation currently generates a hotplug event before +registering the client to the device. For each new output, the DRM +core sends an additional hotplug event to each registered client. + +If the DRM core detects first output between sending the artificial +hotplug and registering the device, the output's hotplug event gets +lost. If this is the first output, the fbdev console display remains +dark. This has been observed with amdgpu and fbdev-generic. + +Fix this by adding hotplug generation directly to the client's +register helper drm_client_register(). Registering the client and +receiving events are serialized by struct drm_device.clientlist_mutex. +So an output is either configured by the initial hotplug event, or +the client has already been registered. + +The bug was originally added in commit 6e3f17ee73f7 ("drm/fb-helper: +generic: Call drm_client_add() after setup is done"), in which adding +a client and receiving a hotplug event switched order. It was hidden, +as most hardware and drivers have at least on static output configured. +Other drivers didn't use the internal DRM client or still had struct +drm_mode_config_funcs.output_poll_changed set. That callback handled +hotplug events as well. After not setting the callback in amdgpu in +commit 0e3172bac3f4 ("drm/amdgpu: Don't set struct +drm_driver.output_poll_changed"), amdgpu did not show a framebuffer +console if output events got lost. The bug got copy-pasted from +fbdev-generic into the other fbdev emulation. + +Reported-by: Moritz Duge +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2649 +Fixes: 6e3f17ee73f7 ("drm/fb-helper: generic: Call drm_client_add() after setup is done") +Fixes: 8ab59da26bc0 ("drm/fb-helper: Move generic fbdev emulation into separate source file") +Fixes: b79fe9abd58b ("drm/fbdev-dma: Implement fbdev emulation for GEM DMA helpers") +Fixes: 63c381552f69 ("drm/armada: Implement fbdev emulation as in-kernel client") +Fixes: 49953b70e7d3 ("drm/exynos: Implement fbdev emulation as in-kernel client") +Fixes: 8f1aaccb04b7 ("drm/gma500: Implement client-based fbdev emulation") +Fixes: 940b869c2f2f ("drm/msm: Implement fbdev emulation as in-kernel client") +Fixes: 9e69bcd88e45 ("drm/omapdrm: Implement fbdev emulation as in-kernel client") +Fixes: e317a69fe891 ("drm/radeon: Implement client-based fbdev emulation") +Fixes: 71ec16f45ef8 ("drm/tegra: Implement fbdev emulation as in-kernel client") +Fixes: 0e3172bac3f4 ("drm/amdgpu: Don't set struct drm_driver.output_poll_changed") +Signed-off-by: Thomas Zimmermann +Tested-by: Moritz Duge +Tested-by: Torsten Krah +Tested-by: Paul Schyska +Cc: Daniel Vetter +Cc: David Airlie +Cc: Noralf Trønnes +Cc: Maarten Lankhorst +Cc: Maxime Ripard +Cc: Javier Martinez Canillas +Cc: Russell King +Cc: Inki Dae +Cc: Seung-Woo Kim +Cc: Kyungmin Park +Cc: Krzysztof Kozlowski +Cc: Patrik Jakobsson +Cc: Rob Clark +Cc: Abhinav Kumar +Cc: Dmitry Baryshkov +Cc: Tomi Valkeinen +Cc: Alex Deucher +Cc: "Christian König" +Cc: "Pan, Xinhui" +Cc: Thierry Reding +Cc: Mikko Perttunen +Cc: dri-devel@lists.freedesktop.org +Cc: linux-kernel@vger.kernel.org +Cc: linux-arm-kernel@lists.infradead.org +Cc: linux-samsung-soc@vger.kernel.org +Cc: linux-arm-msm@vger.kernel.org +Cc: freedreno@lists.freedesktop.org +Cc: amd-gfx@lists.freedesktop.org +Cc: linux-tegra@vger.kernel.org +Cc: dri-devel@lists.freedesktop.org +Cc: # v5.2+ +Reviewed-by: Javier Martinez Canillas +Reviewed-by: Dmitry Baryshkov # msm +Link: https://patchwork.freedesktop.org/patch/msgid/20230710091029.27503-1-tzimmermann@suse.de +[ Dropped changes to drivers/gpu/drm/armada/armada_fbdev.c as + 174c3c38e3a2 drm/armada: Initialize fbdev DRM client + was introduced in 6.5-rc1 ] +Signed-off-by: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/drm_client.c | 21 +++++++++++++++++++++ + drivers/gpu/drm/drm_fbdev_dma.c | 4 ---- + drivers/gpu/drm/drm_fbdev_generic.c | 4 ---- + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 ---- + drivers/gpu/drm/gma500/fbdev.c | 4 ---- + drivers/gpu/drm/msm/msm_fbdev.c | 4 ---- + drivers/gpu/drm/omapdrm/omap_fbdev.c | 4 ---- + drivers/gpu/drm/radeon/radeon_fbdev.c | 4 ---- + drivers/gpu/drm/tegra/fbdev.c | 4 ---- + 9 files changed, 21 insertions(+), 32 deletions(-) + +--- a/drivers/gpu/drm/drm_client.c ++++ b/drivers/gpu/drm/drm_client.c +@@ -122,13 +122,34 @@ EXPORT_SYMBOL(drm_client_init); + * drm_client_register() it is no longer permissible to call drm_client_release() + * directly (outside the unregister callback), instead cleanup will happen + * automatically on driver unload. ++ * ++ * Registering a client generates a hotplug event that allows the client ++ * to set up its display from pre-existing outputs. The client must have ++ * initialized its state to able to handle the hotplug event successfully. + */ + void drm_client_register(struct drm_client_dev *client) + { + struct drm_device *dev = client->dev; ++ int ret; + + mutex_lock(&dev->clientlist_mutex); + list_add(&client->list, &dev->clientlist); ++ ++ if (client->funcs && client->funcs->hotplug) { ++ /* ++ * Perform an initial hotplug event to pick up the ++ * display configuration for the client. This step ++ * has to be performed *after* registering the client ++ * in the list of clients, or a concurrent hotplug ++ * event might be lost; leaving the display off. ++ * ++ * Hold the clientlist_mutex as for a regular hotplug ++ * event. ++ */ ++ ret = client->funcs->hotplug(client); ++ if (ret) ++ drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); ++ } + mutex_unlock(&dev->clientlist_mutex); + } + EXPORT_SYMBOL(drm_client_register); +--- a/drivers/gpu/drm/drm_fbdev_dma.c ++++ b/drivers/gpu/drm/drm_fbdev_dma.c +@@ -253,10 +253,6 @@ void drm_fbdev_dma_setup(struct drm_devi + goto err_drm_client_init; + } + +- ret = drm_fbdev_dma_client_hotplug(&fb_helper->client); +- if (ret) +- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); +- + drm_client_register(&fb_helper->client); + + return; +--- a/drivers/gpu/drm/drm_fbdev_generic.c ++++ b/drivers/gpu/drm/drm_fbdev_generic.c +@@ -340,10 +340,6 @@ void drm_fbdev_generic_setup(struct drm_ + goto err_drm_client_init; + } + +- ret = drm_fbdev_generic_client_hotplug(&fb_helper->client); +- if (ret) +- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); +- + drm_client_register(&fb_helper->client); + + return; +--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +@@ -216,10 +216,6 @@ void exynos_drm_fbdev_setup(struct drm_d + if (ret) + goto err_drm_client_init; + +- ret = exynos_drm_fbdev_client_hotplug(&fb_helper->client); +- if (ret) +- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); +- + drm_client_register(&fb_helper->client); + + return; +--- a/drivers/gpu/drm/gma500/fbdev.c ++++ b/drivers/gpu/drm/gma500/fbdev.c +@@ -330,10 +330,6 @@ void psb_fbdev_setup(struct drm_psb_priv + goto err_drm_fb_helper_unprepare; + } + +- ret = psb_fbdev_client_hotplug(&fb_helper->client); +- if (ret) +- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); +- + drm_client_register(&fb_helper->client); + + return; +--- a/drivers/gpu/drm/msm/msm_fbdev.c ++++ b/drivers/gpu/drm/msm/msm_fbdev.c +@@ -227,10 +227,6 @@ void msm_fbdev_setup(struct drm_device * + goto err_drm_fb_helper_unprepare; + } + +- ret = msm_fbdev_client_hotplug(&helper->client); +- if (ret) +- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); +- + drm_client_register(&helper->client); + + return; +--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c ++++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c +@@ -323,10 +323,6 @@ void omap_fbdev_setup(struct drm_device + + INIT_WORK(&fbdev->work, pan_worker); + +- ret = omap_fbdev_client_hotplug(&helper->client); +- if (ret) +- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); +- + drm_client_register(&helper->client); + + return; +--- a/drivers/gpu/drm/radeon/radeon_fbdev.c ++++ b/drivers/gpu/drm/radeon/radeon_fbdev.c +@@ -386,10 +386,6 @@ void radeon_fbdev_setup(struct radeon_de + goto err_drm_client_init; + } + +- ret = radeon_fbdev_client_hotplug(&fb_helper->client); +- if (ret) +- drm_dbg_kms(rdev->ddev, "client hotplug ret=%d\n", ret); +- + drm_client_register(&fb_helper->client); + + return; +--- a/drivers/gpu/drm/tegra/fbdev.c ++++ b/drivers/gpu/drm/tegra/fbdev.c +@@ -227,10 +227,6 @@ void tegra_fbdev_setup(struct drm_device + if (ret) + goto err_drm_client_init; + +- ret = tegra_fbdev_client_hotplug(&helper->client); +- if (ret) +- drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); +- + drm_client_register(&helper->client); + + return; diff --git a/queue-6.4/series b/queue-6.4/series index 9f3cf737c56..4cb3d8cca28 100644 --- a/queue-6.4/series +++ b/queue-6.4/series @@ -105,3 +105,7 @@ wifi-rtw89-debug-fix-error-code-in-rtw89_debug_priv_.patch net-sched-sch_qfq-reintroduce-lmax-bound-check-for-m.patch net-sched-sch_qfq-account-for-stab-overhead-in-qfq_e.patch nvme-pci-fix-dma-direction-of-unmapping-integrity-da.patch +smb-client-improve-dfs-mount-check.patch +cifs-fix-session-state-check-in-smb2_find_smb_ses.patch +smb-client-fix-parsing-of-source-mount-option.patch +drm-client-send-hotplug-event-after-registering-a-client.patch diff --git a/queue-6.4/smb-client-fix-parsing-of-source-mount-option.patch b/queue-6.4/smb-client-fix-parsing-of-source-mount-option.patch new file mode 100644 index 00000000000..e598be084d6 --- /dev/null +++ b/queue-6.4/smb-client-fix-parsing-of-source-mount-option.patch @@ -0,0 +1,316 @@ +From 49024ec8795ed2bd7217c249ef50a70c4e25d662 Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Tue, 27 Jun 2023 21:24:47 -0300 +Subject: smb: client: fix parsing of source mount option + +From: Paulo Alcantara + +commit 49024ec8795ed2bd7217c249ef50a70c4e25d662 upstream. + +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) +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/cifs_dfs_ref.c | 20 ++++++++++---- + 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, 80 insertions(+), 56 deletions(-) + +--- 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 + 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_auto + 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_auto + goto out; + } + +- rc = set_dest_addr(ctx, full_path); ++ rc = smb3_parse_devname(full_path, ctx); + if (rc) { + mnt = ERR_PTR(rc); + goto out; + } + +- rc = smb3_parse_devname(full_path, ctx); ++ 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 +--- a/fs/smb/client/cifsproto.h ++++ b/fs/smb/client/cifsproto.h +@@ -85,6 +85,8 @@ extern void release_mid(struct mid_q_ent + 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); +--- a/fs/smb/client/dfs.c ++++ b/fs/smb/client/dfs.c +@@ -54,39 +54,6 @@ out: + 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 + 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 + 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 + 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; +--- a/fs/smb/client/fs_context.c ++++ b/fs/smb/client/fs_context.c +@@ -441,14 +441,17 @@ out: + * 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)) +@@ -469,8 +472,39 @@ char *cifs_sanitize_prepath(char *prepat + 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; + } + + /* +@@ -484,6 +518,7 @@ smb3_parse_devname(const char *devname, + char *pos; + const char *delims = "/\\"; + size_t len; ++ int rc; + + if (unlikely(!devname || !*devname)) { + cifs_dbg(VFS, "Device name not specified\n"); +@@ -511,6 +546,8 @@ smb3_parse_devname(const char *devname, + + /* 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; +@@ -533,8 +570,11 @@ smb3_parse_devname(const char *devname, + 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; + } +@@ -1146,12 +1186,13 @@ static int smb3_fs_context_parse_param(s + 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; +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -1211,16 +1211,21 @@ int match_target_ip(struct TCP_Server_In + + 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; diff --git a/queue-6.4/smb-client-improve-dfs-mount-check.patch b/queue-6.4/smb-client-improve-dfs-mount-check.patch new file mode 100644 index 00000000000..89693c4c027 --- /dev/null +++ b/queue-6.4/smb-client-improve-dfs-mount-check.patch @@ -0,0 +1,35 @@ +From 5f2a0afa9890e728428db2ed9281bddca242e90b Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Tue, 27 Jun 2023 21:24:50 -0300 +Subject: smb: client: improve DFS mount check + +From: Paulo Alcantara + +commit 5f2a0afa9890e728428db2ed9281bddca242e90b upstream. + +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) +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/dfs.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/fs/smb/client/dfs.c ++++ b/fs/smb/client/dfs.c +@@ -296,8 +296,9 @@ int dfs_mount_share(struct cifs_mount_ct + 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; + } + }