diff options
| author | Henrique Carvalho <henrique.carvalho@suse.com> | 2026-05-27 09:26:42 -0300 |
|---|---|---|
| committer | Steve French <stfrench@microsoft.com> | 2026-05-27 17:16:36 -0500 |
| commit | 76efb52e058d4fccd44e4d9efa334cb1ff71f4b8 (patch) | |
| tree | e3db245c67b005d9f55e2b5e03ee0cf65a46a776 | |
| parent | 3608379bf0982e84e8f415a6c21f324bcbdc6a38 (diff) | |
| download | linux-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.c | 102 |
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: |
