aboutsummaryrefslogtreecommitdiffstats
diff options
authorHenrique Carvalho <henrique.carvalho@suse.com>2026-05-27 09:26:42 -0300
committerSteve French <stfrench@microsoft.com>2026-05-27 17:16:36 -0500
commit76efb52e058d4fccd44e4d9efa334cb1ff71f4b8 (patch)
treee3db245c67b005d9f55e2b5e03ee0cf65a46a776
parent3608379bf0982e84e8f415a6c21f324bcbdc6a38 (diff)
downloadlinux-next-history-76efb52e058d4fccd44e4d9efa334cb1ff71f4b8.tar.gz
smb: client: fix conflicting option validation for new mount API
Apply conflicting option validation consistently across all the new mount API paths, for both mount and remount. Some checks were only applied during initial mount validation, while others were handled during option parsing, causing mount and remount/reconfigure to behave differently. Move the conflicting option checks into smb3_handle_conflicting_options() and call it from the common validation paths, including for multichannel/max_channels handling. Fixes: 24e0a1eff9e2 ("cifs: switch to new mount api") Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/smb/client/fs_context.c102
1 files changed, 53 insertions, 49 deletions
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index 2f86158f85d7b..fd4b13cd654d9 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -693,6 +693,41 @@ static int smb3_handle_conflicting_options(struct fs_context *fc)
{
struct smb3_fs_context *ctx = smb3_fc2context(fc);
+ if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
+ cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (ctx->multiuser && !IS_ENABLED(CONFIG_KEYS)) {
+ cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (ctx->multiuser && ctx->upcall_target == UPTARGET_MOUNT) {
+ cifs_errorf(fc, "multiuser mount option not supported with upcalltarget set as 'mount'\n");
+ return -EINVAL;
+ }
+
+ if (ctx->uid_specified && !ctx->forceuid_specified) {
+ ctx->override_uid = 1;
+ pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n");
+ }
+
+ if (ctx->gid_specified && !ctx->forcegid_specified) {
+ ctx->override_gid = 1;
+ pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n");
+ }
+
+ if (ctx->override_uid && !ctx->uid_specified) {
+ ctx->override_uid = 0;
+ pr_notice("ignoring forceuid mount option specified with no uid= option\n");
+ }
+
+ if (ctx->override_gid && !ctx->gid_specified) {
+ ctx->override_gid = 0;
+ pr_notice("ignoring forcegid mount option specified with no gid= option\n");
+ }
+
if (ctx->multichannel_specified) {
if (ctx->multichannel) {
if (!ctx->max_channels_specified) {
@@ -711,19 +746,14 @@ static int smb3_handle_conflicting_options(struct fs_context *fc)
return -EINVAL;
}
}
- } else {
- if (ctx->max_channels_specified) {
- if (ctx->max_channels > 1)
- ctx->multichannel = true;
- else
- ctx->multichannel = false;
- } else {
+ } else if (ctx->max_channels_specified) {
+ if (ctx->max_channels > 1)
+ ctx->multichannel = true;
+ else
ctx->multichannel = false;
- ctx->max_channels = 1;
- }
}
- //resetting default values as remount doesn't initialize fs_context again
+ /* clear parse-time latches so they don't persist across remounts */
ctx->multichannel_specified = false;
ctx->max_channels_specified = false;
@@ -804,28 +834,23 @@ static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
if (ret < 0)
break;
}
- return ret ?: smb3_handle_conflicting_options(fc);
+ return ret;
}
/*
- * Validate the preparsed information in the config.
+ * smb3_fs_context_validate - check initial-mount-only constraints:
+ * UNC presence, address resolution, dialect warnings
+ *
+ * @fc: generic mount context
*/
static int smb3_fs_context_validate(struct fs_context *fc)
{
struct smb3_fs_context *ctx = smb3_fc2context(fc);
+ int rc;
- if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
- cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");
- return -EOPNOTSUPP;
- }
-
-#ifndef CONFIG_KEYS
- /* Muliuser mounts require CONFIG_KEYS support */
- if (ctx->multiuser) {
- cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
- return -1;
- }
-#endif
+ rc = smb3_handle_conflicting_options(fc);
+ if (rc)
+ return rc;
if (ctx->got_version == false)
pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
@@ -860,26 +885,6 @@ static int smb3_fs_context_validate(struct fs_context *fc)
/* set the port that we got earlier */
cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
- if (ctx->uid_specified && !ctx->forceuid_specified) {
- ctx->override_uid = 1;
- pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n");
- }
-
- if (ctx->gid_specified && !ctx->forcegid_specified) {
- ctx->override_gid = 1;
- pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n");
- }
-
- if (ctx->override_uid && !ctx->uid_specified) {
- ctx->override_uid = 0;
- pr_notice("ignoring forceuid mount option specified with no uid= option\n");
- }
-
- if (ctx->override_gid && !ctx->gid_specified) {
- ctx->override_gid = 0;
- pr_notice("ignoring forcegid mount option specified with no gid= option\n");
- }
-
return 0;
}
@@ -1078,6 +1083,10 @@ static int smb3_reconfigure(struct fs_context *fc)
if (rc)
return rc;
+ rc = smb3_handle_conflicting_options(fc);
+ if (rc)
+ return rc;
+
old_ctx = kzalloc_obj(*old_ctx);
if (!old_ctx)
return -ENOMEM;
@@ -1933,11 +1942,6 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
}
/* case Opt_ignore: - is ignored as expected ... */
- if (ctx->multiuser && ctx->upcall_target == UPTARGET_MOUNT) {
- cifs_errorf(fc, "multiuser mount option not supported with upcalltarget set as 'mount'\n");
- goto cifs_parse_mount_err;
- }
-
return 0;
cifs_parse_mount_err: