[PATCH nvme-7.3 v3 4/4] nvme-fabrics: add helper for DH-CHAP secret options

From: raoxu

Date: Mon Aug 31 2026 - 03:16:46 EST


From: Xu Rao <raoxu@xxxxxxxxxxxxx>

The dhchap_secret and dhchap_ctrl_secret options share the same string
replacement and DHHC-1 validation rules. The replacement step can reuse
nvmf_parse_string_option(), leaving only the DH-CHAP-specific validation
in a dedicated helper.

Add nvmf_parse_dhchap_secret() to reuse nvmf_parse_string_option() for the
common allocation and ownership handling, then perform the DH-CHAP-specific
validation. If validation fails, discard the installed value with
kfree_sensitive() and clear the field so the normal options cleanup can
safely run after nvmf_parse_options() returns an error.

Both secret options share this helper because their parsing and validation
rules are identical.

Suggested-by: Christoph Hellwig <hch@xxxxxx>
Signed-off-by: Xu Rao <raoxu@xxxxxxxxxxxxx>
---
drivers/nvme/host/fabrics.c | 47 ++++++++++++++++++-------------------
1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index 24385e777307..207b05ade022 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -725,6 +725,24 @@ static int nvmf_parse_string_option(substring_t *args, char **dst)
return 0;
}

+static int nvmf_parse_dhchap_secret(substring_t *args, char **secret)
+{
+ int ret;
+
+ ret = nvmf_parse_string_option(args, secret);
+ if (ret)
+ return ret;
+
+ if (strlen(*secret) < 11 || strncmp(*secret, "DHHC-1:", 7)) {
+ pr_err("Invalid DH-CHAP secret %s\n", *secret);
+ kfree_sensitive(*secret);
+ *secret = NULL;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
const char *buf)
{
@@ -1010,34 +1028,15 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
opts->discovery_nqn = true;
break;
case NVMF_OPT_DHCHAP_SECRET:
- p = match_strdup(args);
- if (!p) {
- ret = -ENOMEM;
- goto out;
- }
- if (strlen(p) < 11 || strncmp(p, "DHHC-1:", 7)) {
- pr_err("Invalid DH-CHAP secret %s\n", p);
- kfree_sensitive(p);
- ret = -EINVAL;
+ ret = nvmf_parse_dhchap_secret(args, &opts->dhchap_secret);
+ if (ret)
goto out;
- }
- kfree(opts->dhchap_secret);
- opts->dhchap_secret = p;
break;
case NVMF_OPT_DHCHAP_CTRL_SECRET:
- p = match_strdup(args);
- if (!p) {
- ret = -ENOMEM;
- goto out;
- }
- if (strlen(p) < 11 || strncmp(p, "DHHC-1:", 7)) {
- pr_err("Invalid DH-CHAP secret %s\n", p);
- kfree_sensitive(p);
- ret = -EINVAL;
+ ret = nvmf_parse_dhchap_secret(args,
+ &opts->dhchap_ctrl_secret);
+ if (ret)
goto out;
- }
- kfree(opts->dhchap_ctrl_secret);
- opts->dhchap_ctrl_secret = p;
break;
case NVMF_OPT_TLS:
if (!IS_ENABLED(CONFIG_NVME_TCP_TLS)) {
--
2.50.1