Commit 7378b003 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge tag 'nvme-6.18-2025-09-23' of git://git.infradead.org/nvme into for-6.18/block

Pull NVMe updates from Keith:

" - FC target fixes (Daniel)
  - Authentication fixes and updates (Martin, Chris)
  - Admin controller handling (Kamaljit)
  - Target lockdep assertions (Max)
  - Keep-alive updates for discovery (Alastair)
  - Suspend quirk (Georg)"

* tag 'nvme-6.18-2025-09-23' of git://git.infradead.org/nvme:
  nvme: Use non zero KATO for persistent discovery connections
  nvmet: add safety check for subsys lock
  nvme-core: use nvme_is_io_ctrl() for I/O controller check
  nvme-core: do ioccsz/iorcsz validation only for I/O controllers
  nvme-core: add method to check for an I/O controller
  nvme-pci: Add TUXEDO IBS Gen8 to Samsung sleep quirk
  nvme-auth: use hkdf_expand_label()
  nvme-auth: add hkdf_expand_label()
  nvme-tcp: send only permitted commands for secure concat
  nvme-fc: use lock accessing port_state and rport state
  nvmet-fcloop: call done callback even when remote port is gone
  nvmet-fc: avoid scheduling association deletion twice
  nvmet-fc: move lsop put work to nvmet_fc_ls_req_op
  nvme-auth: update bi_directional flag
parents 5d726c4d 2e482655
Loading
Loading
Loading
Loading
+66 −20
Original line number Diff line number Diff line
@@ -683,6 +683,59 @@ int nvme_auth_generate_digest(u8 hmac_id, u8 *psk, size_t psk_len,
}
EXPORT_SYMBOL_GPL(nvme_auth_generate_digest);

/**
 * hkdf_expand_label - HKDF-Expand-Label (RFC 8846 section 7.1)
 * @hmac_tfm: hash context keyed with pseudorandom key
 * @label: ASCII label without "tls13 " prefix
 * @labellen: length of @label
 * @context: context bytes
 * @contextlen: length of @context
 * @okm: output keying material
 * @okmlen: length of @okm
 *
 * Build the TLS 1.3 HkdfLabel structure and invoke hkdf_expand().
 *
 * Returns 0 on success with output keying material stored in @okm,
 * or a negative errno value otherwise.
 */
static int hkdf_expand_label(struct crypto_shash *hmac_tfm,
		const u8 *label, unsigned int labellen,
		const u8 *context, unsigned int contextlen,
		u8 *okm, unsigned int okmlen)
{
	int err;
	u8 *info;
	unsigned int infolen;
	const char *tls13_prefix = "tls13 ";
	unsigned int prefixlen = strlen(tls13_prefix);

	if (WARN_ON(labellen > (255 - prefixlen)))
		return -EINVAL;
	if (WARN_ON(contextlen > 255))
		return -EINVAL;

	infolen = 2 + (1 + prefixlen + labellen) + (1 + contextlen);
	info = kzalloc(infolen, GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	/* HkdfLabel.Length */
	put_unaligned_be16(okmlen, info);

	/* HkdfLabel.Label */
	info[2] = prefixlen + labellen;
	memcpy(info + 3, tls13_prefix, prefixlen);
	memcpy(info + 3 + prefixlen, label, labellen);

	/* HkdfLabel.Context */
	info[3 + prefixlen + labellen] = contextlen;
	memcpy(info + 4 + prefixlen + labellen, context, contextlen);

	err = hkdf_expand(hmac_tfm, info, infolen, okm, okmlen);
	kfree_sensitive(info);
	return err;
}

/**
 * nvme_auth_derive_tls_psk - Derive TLS PSK
 * @hmac_id: Hash function identifier
@@ -715,10 +768,10 @@ int nvme_auth_derive_tls_psk(int hmac_id, u8 *psk, size_t psk_len,
{
	struct crypto_shash *hmac_tfm;
	const char *hmac_name;
	const char *psk_prefix = "tls13 nvme-tls-psk";
	const char *label = "nvme-tls-psk";
	static const char default_salt[HKDF_MAX_HASHLEN];
	size_t info_len, prk_len;
	char *info;
	size_t prk_len;
	const char *ctx;
	unsigned char *prk, *tls_key;
	int ret;

@@ -758,36 +811,29 @@ int nvme_auth_derive_tls_psk(int hmac_id, u8 *psk, size_t psk_len,
	if (ret)
		goto out_free_prk;

	/*
	 * 2 additional bytes for the length field from HDKF-Expand-Label,
	 * 2 additional bytes for the HMAC ID, and one byte for the space
	 * separator.
	 */
	info_len = strlen(psk_digest) + strlen(psk_prefix) + 5;
	info = kzalloc(info_len + 1, GFP_KERNEL);
	if (!info) {
	ctx = kasprintf(GFP_KERNEL, "%02d %s", hmac_id, psk_digest);
	if (!ctx) {
		ret = -ENOMEM;
		goto out_free_prk;
	}

	put_unaligned_be16(psk_len, info);
	memcpy(info + 2, psk_prefix, strlen(psk_prefix));
	sprintf(info + 2 + strlen(psk_prefix), "%02d %s", hmac_id, psk_digest);

	tls_key = kzalloc(psk_len, GFP_KERNEL);
	if (!tls_key) {
		ret = -ENOMEM;
		goto out_free_info;
		goto out_free_ctx;
	}
	ret = hkdf_expand(hmac_tfm, info, info_len, tls_key, psk_len);
	ret = hkdf_expand_label(hmac_tfm,
				label, strlen(label),
				ctx, strlen(ctx),
				tls_key, psk_len);
	if (ret) {
		kfree(tls_key);
		goto out_free_info;
		goto out_free_ctx;
	}
	*ret_psk = tls_key;

out_free_info:
	kfree(info);
out_free_ctx:
	kfree(ctx);
out_free_prk:
	kfree(prk);
out_free_shash:
+3 −2
Original line number Diff line number Diff line
@@ -331,9 +331,10 @@ static int nvme_auth_set_dhchap_reply_data(struct nvme_ctrl *ctrl,
	} else {
		memset(chap->c2, 0, chap->hash_len);
	}
	if (ctrl->opts->concat)
	if (ctrl->opts->concat) {
		chap->s2 = 0;
	else
		chap->bi_directional = false;
	} else
		chap->s2 = nvme_auth_get_seqnum();
	data->seqnum = cpu_to_le32(chap->s2);
	if (chap->host_key_len) {
+15 −4
Original line number Diff line number Diff line
@@ -3163,6 +3163,11 @@ static inline bool nvme_admin_ctrl(struct nvme_ctrl *ctrl)
	return ctrl->cntrltype == NVME_CTRL_ADMIN;
}

static inline bool nvme_is_io_ctrl(struct nvme_ctrl *ctrl)
{
	return !nvme_discovery_ctrl(ctrl) && !nvme_admin_ctrl(ctrl);
}

static bool nvme_validate_cntlid(struct nvme_subsystem *subsys,
		struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
{
@@ -3365,7 +3370,7 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl)
	else
		ctrl->max_zeroes_sectors = 0;

	if (ctrl->subsys->subtype != NVME_NQN_NVME ||
	if (!nvme_is_io_ctrl(ctrl) ||
	    !nvme_id_cns_ok(ctrl, NVME_ID_CNS_CS_CTRL) ||
	    test_bit(NVME_CTRL_SKIP_ID_CNS_CS, &ctrl->flags))
		return 0;
@@ -3487,14 +3492,14 @@ static int nvme_check_ctrl_fabric_info(struct nvme_ctrl *ctrl, struct nvme_id_ct
		return -EINVAL;
	}

	if (!nvme_discovery_ctrl(ctrl) && ctrl->ioccsz < 4) {
	if (nvme_is_io_ctrl(ctrl) && ctrl->ioccsz < 4) {
		dev_err(ctrl->device,
			"I/O queue command capsule supported size %d < 4\n",
			ctrl->ioccsz);
		return -EINVAL;
	}

	if (!nvme_discovery_ctrl(ctrl) && ctrl->iorcsz < 1) {
	if (nvme_is_io_ctrl(ctrl) && ctrl->iorcsz < 1) {
		dev_err(ctrl->device,
			"I/O queue response capsule supported size %d < 1\n",
			ctrl->iorcsz);
@@ -4986,8 +4991,14 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
	 * checking that they started once before, hence are reconnecting back.
	 */
	if (test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags) &&
	    nvme_discovery_ctrl(ctrl))
	    nvme_discovery_ctrl(ctrl)) {
		if (!ctrl->kato) {
			nvme_stop_keep_alive(ctrl);
			ctrl->kato = NVME_DEFAULT_KATO;
			nvme_start_keep_alive(ctrl);
		}
		nvme_change_uevent(ctrl, "NVME_EVENT=rediscover");
	}

	if (ctrl->queue_count > 1) {
		nvme_queue_scan(ctrl);
+8 −2
Original line number Diff line number Diff line
@@ -3032,11 +3032,17 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)

	++ctrl->ctrl.nr_reconnects;

	if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE)
	spin_lock_irqsave(&ctrl->rport->lock, flags);
	if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE) {
		spin_unlock_irqrestore(&ctrl->rport->lock, flags);
		return -ENODEV;
	}

	if (nvme_fc_ctlr_active_on_rport(ctrl))
	if (nvme_fc_ctlr_active_on_rport(ctrl)) {
		spin_unlock_irqrestore(&ctrl->rport->lock, flags);
		return -ENOTUNIQ;
	}
	spin_unlock_irqrestore(&ctrl->rport->lock, flags);

	dev_info(ctrl->ctrl.device,
		"NVME-FC{%d}: create association : host wwpn 0x%016llx "
+2 −0
Original line number Diff line number Diff line
@@ -3330,10 +3330,12 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
		 * Exclude Samsung 990 Evo from NVME_QUIRK_SIMPLE_SUSPEND
		 * because of high power consumption (> 2 Watt) in s2idle
		 * sleep. Only some boards with Intel CPU are affected.
		 * (Note for testing: Samsung 990 Evo Plus has same PCI ID)
		 */
		if (dmi_match(DMI_BOARD_NAME, "DN50Z-140HC-YD") ||
		    dmi_match(DMI_BOARD_NAME, "GMxPXxx") ||
		    dmi_match(DMI_BOARD_NAME, "GXxMRXx") ||
		    dmi_match(DMI_BOARD_NAME, "NS5X_NS7XAU") ||
		    dmi_match(DMI_BOARD_NAME, "PH4PG31") ||
		    dmi_match(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1") ||
		    dmi_match(DMI_BOARD_NAME, "PH6PG01_PH6PG71"))
Loading