[PATCH 11/18] nvme-tcp: control message handling for recvmsg()

Hannes Reinecke
2023-03-29T14:00:01Z

kTLS is sending TLS ALERT messages as control messages for recvmsg().
As we can't do anything sensible with it just abort the connection
and let the userspace agent to a re-negotiation.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/nvme/host/tcp.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 54d27873227a..2e15fa83b725 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -1377,6 +1377,11 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
{
struct nvme_tcp_icreq_pdu *icreq;
struct nvme_tcp_icresp_pdu *icresp;
+#ifdef CONFIG_NVME_TLS
+ char cbuf[CMSG_LEN(sizeof(char))] = {};
+ struct cmsghdr *cmsg;
+ unsigned char ctype;
+#endif
struct msghdr msg = {};
struct kvec iov;
bool ctrl_hdgst, ctrl_ddgst;
@@ -1414,11 +1419,27 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
memset(&msg, 0, sizeof(msg));
iov.iov_base = icresp;
iov.iov_len = sizeof(*icresp);
+#ifdef CONFIG_NVME_TLS
+ msg.msg_control = cbuf;
+ msg.msg_controllen = sizeof(cbuf);
+#endif
ret = kernel_recvmsg(queue->sock, &msg, &iov, 1,
iov.iov_len, msg.msg_flags);
if (ret < 0)
goto free_icresp;
-
+#ifdef CONFIG_NVME_TLS
+ cmsg = (struct cmsghdr *)cbuf;
+ if (CMSG_OK(&msg, cmsg) &&
+ cmsg->cmsg_level == SOL_TLS &&
+ cmsg->cmsg_type == TLS_GET_RECORD_TYPE) {
+ ctype = *((unsigned char *)CMSG_DATA(cmsg));
+ if (ctype != TLS_RECORD_TYPE_DATA) {
+ pr_err("queue %d: unhandled TLS record %d\n",
+ nvme_tcp_queue_id(queue), ctype);
+ return -ENOTCONN;
+ }
+ }
+#endif
ret = -EINVAL;
if (icresp->hdr.type != nvme_tcp_icresp) {
pr_err("queue %d: bad type returned %d\n",
--
2.35.3