nvme fixes for 6.7

- nvme keyring config compile fixes (Hannes and Arnd)
  - fabrics keep alive fixes (Hannes)
  - tcp authentication fixes (Mark)
  - io_uring_cmd error handling fix (Anuj)
  - stale firmware attribute fix (Daniel)
  - tcp memory leak (Christophe)
  - cytpo library usage simplification (Eric)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE3Fbyvv+648XNRdHTPe3zGtjzRgkFAmVLsqUACgkQPe3zGtjz
 Rgn2GhAAs+2tP+Y2GjnzxxDrFllwH595sMCaqtQmGO/nu3kcxBAwipUuibwWxNxb
 4D3m4WGt4YzqmwDEQo4aY3ylhzWWkkanWvG0eyQfwSI3TOppZGAnXrdCh3HdHFNu
 IgPHpDWbNIUcf//mb7KJd1IMRG52ZIiMZJym7yyziUktaqQ0dnpviJS6kNLfzcME
 psBZcx+6Ns4+ixTkrnsyS/RkPE1CrgpjzCd7WcyZbTfwbhsk4obvxNFce6gFZQG6
 nQcKpTDTR+r17dKI/UdJbAnQsw5+Cdr7NokCwch4YfKOcvxTJ5H4gQnOF4tg1UzZ
 LUMRD/QeVepqojXeIIgWe5YrdoWbPxHemuo6BcCgEbs8Qx9Lz5iC29JS6599/xv8
 yK4dUhl8bNyh8gA7KVx5n3rde3fyktcrnYoVF0/6u4+jRRxsdjohiDs9+Uy/eHay
 6IwJc4gZV9Dohm1FL8WX/KEI4Sn3u6Ca4asi8kDQ1TNBw0EI1XMMuvjDb6hGr9WX
 jFhnFewggxrk7xiJBuUlVyPS5076xlAyfYtaJ5hMqYXmLRx2FBvDbcQGFSwaERjx
 NeKPbRjJ4ttfnNAsgsSnMtmWDhC8nZsSBkHJ/e2pU19en7v6BbjggiaJ5ZG4aYpT
 S2UExU+qCPEimMo6N2W/ql6bCCMLV7ly6dAgyU7VR4/nS6shp7w=
 =R803
 -----END PGP SIGNATURE-----

Merge tag 'nvme-6.7-2023-11-8' of git://git.infradead.org/nvme into block-6.7

Pull NVMe fixes from Keith:

"nvme fixes for 6.7

 - nvme keyring config compile fixes (Hannes and Arnd)
 - fabrics keep alive fixes (Hannes)
 - tcp authentication fixes (Mark)
 - io_uring_cmd error handling fix (Anuj)
 - stale firmware attribute fix (Daniel)
 - tcp memory leak (Christophe)
 - cytpo library usage simplification (Eric)"

* tag 'nvme-6.7-2023-11-8' of git://git.infradead.org/nvme:
  nvme: keyring: fix conditional compilation
  nvme: common: make keyring and auth separate modules
  nvme: start keep-alive after admin queue setup
  nvme-loop: always quiesce and cancel commands before destroying admin q
  nvme-tcp: avoid open-coding nvme_tcp_teardown_admin_queue()
  nvme-auth: always set valid seq_num in dhchap reply
  nvme-auth: add flag for bi-directional auth
  nvme-auth: auth success1 msg always includes resp
  nvme: fix error-handling for io_uring nvme-passthrough
  nvme: update firmware version after commit
  nvme-tcp: Fix a memory leak
  nvme-auth: use crypto_shash_tfm_digest()
This commit is contained in:
Jens Axboe 2023-11-08 09:19:16 -07:00
commit 37d9486874
16 changed files with 61 additions and 76 deletions

View file

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_NVME_COMMON) += common/
obj-y += common/
obj-y += host/
obj-y += target/

View file

@ -1,14 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
config NVME_COMMON
tristate
config NVME_KEYRING
bool
tristate
select KEYS
config NVME_AUTH
bool
tristate
select CRYPTO
select CRYPTO_HMAC
select CRYPTO_SHA256

View file

@ -2,7 +2,8 @@
ccflags-y += -I$(src)
obj-$(CONFIG_NVME_COMMON) += nvme-common.o
obj-$(CONFIG_NVME_AUTH) += nvme-auth.o
obj-$(CONFIG_NVME_KEYRING) += nvme-keyring.o
nvme-common-$(CONFIG_NVME_AUTH) += auth.o
nvme-common-$(CONFIG_NVME_KEYRING) += keyring.o
nvme-auth-y += auth.o
nvme-keyring-y += keyring.o

View file

@ -341,7 +341,6 @@ int nvme_auth_augmented_challenge(u8 hmac_id, u8 *skey, size_t skey_len,
u8 *challenge, u8 *aug, size_t hlen)
{
struct crypto_shash *tfm;
struct shash_desc *desc;
u8 *hashed_key;
const char *hmac_name;
int ret;
@ -369,29 +368,11 @@ int nvme_auth_augmented_challenge(u8 hmac_id, u8 *skey, size_t skey_len,
goto out_free_key;
}
desc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
GFP_KERNEL);
if (!desc) {
ret = -ENOMEM;
goto out_free_hash;
}
desc->tfm = tfm;
ret = crypto_shash_setkey(tfm, hashed_key, hlen);
if (ret)
goto out_free_desc;
goto out_free_hash;
ret = crypto_shash_init(desc);
if (ret)
goto out_free_desc;
ret = crypto_shash_update(desc, challenge, hlen);
if (ret)
goto out_free_desc;
ret = crypto_shash_final(desc, aug);
out_free_desc:
kfree_sensitive(desc);
ret = crypto_shash_tfm_digest(tfm, challenge, hlen, aug);
out_free_hash:
crypto_free_shash(tfm);
out_free_key:

View file

@ -151,7 +151,7 @@ key_serial_t nvme_tls_psk_default(struct key *keyring,
}
EXPORT_SYMBOL_GPL(nvme_tls_psk_default);
int nvme_keyring_init(void)
static int __init nvme_keyring_init(void)
{
int err;
@ -171,12 +171,15 @@ int nvme_keyring_init(void)
}
return 0;
}
EXPORT_SYMBOL_GPL(nvme_keyring_init);
void nvme_keyring_exit(void)
static void __exit nvme_keyring_exit(void)
{
unregister_key_type(&nvme_tls_psk_key_type);
key_revoke(nvme_keyring);
key_put(nvme_keyring);
}
EXPORT_SYMBOL_GPL(nvme_keyring_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
module_init(nvme_keyring_init);
module_exit(nvme_keyring_exit);

View file

@ -95,7 +95,6 @@ config NVME_TCP
config NVME_TCP_TLS
bool "NVMe over Fabrics TCP TLS encryption support"
depends on NVME_TCP
select NVME_COMMON
select NVME_KEYRING
select NET_HANDSHAKE
select KEYS
@ -110,7 +109,6 @@ config NVME_TCP_TLS
config NVME_HOST_AUTH
bool "NVM Express over Fabrics In-Band Authentication"
depends on NVME_CORE
select NVME_COMMON
select NVME_AUTH
help
This provides support for NVMe over Fabrics In-Band Authentication.

View file

@ -29,6 +29,7 @@ struct nvme_dhchap_queue_context {
int error;
u32 s1;
u32 s2;
bool bi_directional;
u16 transaction;
u8 status;
u8 dhgroup_id;
@ -312,17 +313,17 @@ static int nvme_auth_set_dhchap_reply_data(struct nvme_ctrl *ctrl,
data->dhvlen = cpu_to_le16(chap->host_key_len);
memcpy(data->rval, chap->response, chap->hash_len);
if (ctrl->ctrl_key) {
chap->bi_directional = true;
get_random_bytes(chap->c2, chap->hash_len);
data->cvalid = 1;
chap->s2 = nvme_auth_get_seqnum();
memcpy(data->rval + chap->hash_len, chap->c2,
chap->hash_len);
dev_dbg(ctrl->device, "%s: qid %d ctrl challenge %*ph\n",
__func__, chap->qid, (int)chap->hash_len, chap->c2);
} else {
memset(chap->c2, 0, chap->hash_len);
chap->s2 = 0;
}
chap->s2 = nvme_auth_get_seqnum();
data->seqnum = cpu_to_le32(chap->s2);
if (chap->host_key_len) {
dev_dbg(ctrl->device, "%s: qid %d host public key %*ph\n",
@ -339,10 +340,7 @@ static int nvme_auth_process_dhchap_success1(struct nvme_ctrl *ctrl,
struct nvme_dhchap_queue_context *chap)
{
struct nvmf_auth_dhchap_success1_data *data = chap->buf;
size_t size = sizeof(*data);
if (chap->s2)
size += chap->hash_len;
size_t size = sizeof(*data) + chap->hash_len;
if (size > CHAP_BUF_SIZE) {
chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
@ -663,6 +661,7 @@ static void nvme_auth_reset_dhchap(struct nvme_dhchap_queue_context *chap)
chap->error = 0;
chap->s1 = 0;
chap->s2 = 0;
chap->bi_directional = false;
chap->transaction = 0;
memset(chap->c1, 0, sizeof(chap->c1));
memset(chap->c2, 0, sizeof(chap->c2));
@ -825,7 +824,7 @@ static void nvme_queue_auth_work(struct work_struct *work)
goto fail2;
}
if (chap->s2) {
if (chap->bi_directional) {
/* DH-HMAC-CHAP Step 5: send success2 */
dev_dbg(ctrl->device, "%s: qid %d send success2\n",
__func__, chap->qid);

View file

@ -25,7 +25,6 @@
#include "nvme.h"
#include "fabrics.h"
#include <linux/nvme-auth.h>
#include <linux/nvme-keyring.h>
#define CREATE_TRACE_POINTS
#include "trace.h"
@ -483,6 +482,7 @@ EXPORT_SYMBOL_GPL(nvme_cancel_tagset);
void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl)
{
nvme_stop_keep_alive(ctrl);
if (ctrl->admin_tagset) {
blk_mq_tagset_busy_iter(ctrl->admin_tagset,
nvme_cancel_request, ctrl);
@ -3200,6 +3200,8 @@ int nvme_init_ctrl_finish(struct nvme_ctrl *ctrl, bool was_suspended)
clear_bit(NVME_CTRL_DIRTY_CAPABILITY, &ctrl->flags);
ctrl->identified = true;
nvme_start_keep_alive(ctrl);
return 0;
}
EXPORT_SYMBOL_GPL(nvme_init_ctrl_finish);
@ -4074,8 +4076,21 @@ static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl)
return;
if (nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_FW_SLOT, 0, NVME_CSI_NVM,
log, sizeof(*log), 0))
log, sizeof(*log), 0)) {
dev_warn(ctrl->device, "Get FW SLOT INFO log error\n");
goto out_free_log;
}
if (log->afi & 0x70 || !(log->afi & 0x7)) {
dev_info(ctrl->device,
"Firmware is activated after next Controller Level Reset\n");
goto out_free_log;
}
memcpy(ctrl->subsys->firmware_rev, &log->frs[(log->afi & 0x7) - 1],
sizeof(ctrl->subsys->firmware_rev));
out_free_log:
kfree(log);
}
@ -4333,7 +4348,6 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
{
nvme_mpath_stop(ctrl);
nvme_auth_stop(ctrl);
nvme_stop_keep_alive(ctrl);
nvme_stop_failfast_work(ctrl);
flush_work(&ctrl->async_event_work);
cancel_work_sync(&ctrl->fw_act_work);
@ -4344,8 +4358,6 @@ EXPORT_SYMBOL_GPL(nvme_stop_ctrl);
void nvme_start_ctrl(struct nvme_ctrl *ctrl)
{
nvme_start_keep_alive(ctrl);
nvme_enable_aen(ctrl);
/*
@ -4724,16 +4736,11 @@ static int __init nvme_core_init(void)
result = PTR_ERR(nvme_ns_chr_class);
goto unregister_generic_ns;
}
result = nvme_keyring_init();
if (result)
goto destroy_ns_chr;
result = nvme_init_auth();
if (result)
goto keyring_exit;
goto destroy_ns_chr;
return 0;
keyring_exit:
nvme_keyring_exit();
destroy_ns_chr:
class_destroy(nvme_ns_chr_class);
unregister_generic_ns:
@ -4757,7 +4764,6 @@ static int __init nvme_core_init(void)
static void __exit nvme_core_exit(void)
{
nvme_exit_auth();
nvme_keyring_exit();
class_destroy(nvme_ns_chr_class);
class_destroy(nvme_subsys_class);
class_destroy(nvme_class);

View file

@ -2530,6 +2530,12 @@ __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)
* clean up the admin queue. Same thing as above.
*/
nvme_quiesce_admin_queue(&ctrl->ctrl);
/*
* Open-coding nvme_cancel_admin_tagset() as fc
* is not using nvme_cancel_request().
*/
nvme_stop_keep_alive(&ctrl->ctrl);
blk_sync_queue(ctrl->ctrl.admin_q);
blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
nvme_fc_terminate_exchange, &ctrl->ctrl);

View file

@ -510,10 +510,13 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
req->bio = pdu->bio;
if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
if (nvme_req(req)->flags & NVME_REQ_CANCELLED) {
pdu->nvme_status = -EINTR;
else
} else {
pdu->nvme_status = nvme_req(req)->status;
if (!pdu->nvme_status)
pdu->nvme_status = blk_status_to_errno(err);
}
pdu->u.result = le64_to_cpu(nvme_req(req)->result.u64);
/*

View file

@ -1423,13 +1423,14 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
nvme_tcp_queue_id(queue), ret);
goto free_icresp;
}
ret = -ENOTCONN;
if (queue->ctrl->ctrl.opts->tls) {
ctype = tls_get_record_type(queue->sock->sk,
(struct cmsghdr *)cbuf);
if (ctype != TLS_RECORD_TYPE_DATA) {
pr_err("queue %d: unhandled TLS record %d\n",
nvme_tcp_queue_id(queue), ctype);
return -ENOTCONN;
goto free_icresp;
}
}
ret = -EINVAL;
@ -2236,11 +2237,7 @@ static int nvme_tcp_setup_ctrl(struct nvme_ctrl *ctrl, bool new)
nvme_tcp_destroy_io_queues(ctrl, new);
}
destroy_admin:
nvme_quiesce_admin_queue(ctrl);
blk_sync_queue(ctrl->admin_q);
nvme_tcp_stop_queue(ctrl, 0);
nvme_cancel_admin_tagset(ctrl);
nvme_tcp_destroy_admin_queue(ctrl, new);
nvme_tcp_teardown_admin_queue(ctrl, false);
return ret;
}

View file

@ -87,7 +87,6 @@ config NVME_TARGET_TCP
config NVME_TARGET_TCP_TLS
bool "NVMe over Fabrics TCP target TLS encryption support"
depends on NVME_TARGET_TCP
select NVME_COMMON
select NVME_KEYRING
select NET_HANDSHAKE
select KEYS
@ -102,7 +101,6 @@ config NVME_TARGET_TCP_TLS
config NVME_TARGET_AUTH
bool "NVMe over Fabrics In-band Authentication support"
depends on NVME_TARGET
select NVME_COMMON
select NVME_AUTH
help
This enables support for NVMe over Fabrics In-band Authentication

View file

@ -163,11 +163,11 @@ static u16 nvmet_auth_reply(struct nvmet_req *req, void *d)
pr_debug("%s: ctrl %d qid %d challenge %*ph\n",
__func__, ctrl->cntlid, req->sq->qid, data->hl,
req->sq->dhchap_c2);
req->sq->dhchap_s2 = le32_to_cpu(data->seqnum);
} else {
req->sq->authenticated = true;
req->sq->dhchap_c2 = NULL;
}
req->sq->dhchap_s2 = le32_to_cpu(data->seqnum);
return 0;
}

View file

@ -466,6 +466,8 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work)
out_destroy_io:
nvme_loop_destroy_io_queues(ctrl);
out_destroy_admin:
nvme_quiesce_admin_queue(&ctrl->ctrl);
nvme_cancel_admin_tagset(&ctrl->ctrl);
nvme_loop_destroy_admin_queue(ctrl);
out_disable:
dev_warn(ctrl->ctrl.device, "Removing after reset failure\n");
@ -600,6 +602,8 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
return &ctrl->ctrl;
out_remove_admin_queue:
nvme_quiesce_admin_queue(&ctrl->ctrl);
nvme_cancel_admin_tagset(&ctrl->ctrl);
nvme_loop_destroy_admin_queue(ctrl);
out_free_queues:
kfree(ctrl->queues);

View file

@ -6,14 +6,12 @@
#ifndef _NVME_KEYRING_H
#define _NVME_KEYRING_H
#ifdef CONFIG_NVME_KEYRING
#if IS_ENABLED(CONFIG_NVME_KEYRING)
key_serial_t nvme_tls_psk_default(struct key *keyring,
const char *hostnqn, const char *subnqn);
key_serial_t nvme_keyring_id(void);
int nvme_keyring_init(void);
void nvme_keyring_exit(void);
#else
@ -26,11 +24,5 @@ static inline key_serial_t nvme_keyring_id(void)
{
return 0;
}
static inline int nvme_keyring_init(void)
{
return 0;
}
static inline void nvme_keyring_exit(void) {}
#endif /* !CONFIG_NVME_KEYRING */
#endif /* _NVME_KEYRING_H */

View file

@ -1732,7 +1732,7 @@ struct nvmf_auth_dhchap_success1_data {
__u8 rsvd2;
__u8 rvalid;
__u8 rsvd3[7];
/* 'hl' bytes of response value if 'rvalid' is set */
/* 'hl' bytes of response value */
__u8 rval[];
};