From nobody Mon Feb 9 11:34:54 2026 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA1D01A9FB8 for ; Fri, 17 Oct 2025 04:23:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675020; cv=none; b=jPMuUob+pnHN3T+wl0o6nwuO8CNHpsKFi0puQ7GHcZKlffDDmYxKdvrjy9wAfw6wigCo9utiKYG/SvFL+u7N8QvyJAVtZhAIfVg4x0tSyapYNZzIkUzF7gPpAY7T7W1tWsjOaKV+cnmGFUy97zpaBVJm1PaY9ZyNGRiBKZnIjX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675020; c=relaxed/simple; bh=duddJN0kQkHYKxRPfiW8CpFJ4dQVX39UNzxDdQSpByw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RLs5lN0grc+IxkDNYS+/8O6Bm9vKt6p83XFB7E3ioJyL5DFQhCUa+hZPlI6vM/3kZ7sc5No1tP+9vUTb5isBJWYXyWWHiRuZ5T5R5CgTkxn4a2z4t844d8U2WSlYN0U+sR1a8Ov4fs5U3Liho0VYn+0uf10HmcJJBQyYIVaQ+DE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BeUbD9kJ; arc=none smtp.client-ip=209.85.210.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BeUbD9kJ" Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-789fb76b466so1458328b3a.0 for ; Thu, 16 Oct 2025 21:23:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760675018; x=1761279818; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jjVILfauIufUxhc7OT1sVnMmTMxe8Z64uh1TdUKNmZM=; b=BeUbD9kJLnxKuXC5CodC5/RJB8Wn5N6uwaf23vD+xxE3p5mXTx9bMBDmzc9l/3hmmA tqB77z3a/ntjyeiiCC3HZ93Ojutn9RqJwBgsVA56qRucf072R5U0QbgwalS8RbEj0Ovh YegEaZLTpAr6iCK8Xm4C/JeCtLDmZ4NdVhuIL/vH6Y1H2adqaAKyWoMKBDtZHRgCNIdu yTqNDsc7el4Nvgx0o/2JGFBtDhHuQHrTiUxfSkHfq8FBvYZevlJSWGvndIQckALPe+sS arSGcFAner0wXyKz9q/DNeIFmWSPHPkOanIMOj86XQSQoWf5suBwPX1Xw/G9Nk1AW1j4 gQvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760675018; x=1761279818; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jjVILfauIufUxhc7OT1sVnMmTMxe8Z64uh1TdUKNmZM=; b=sEwVp0DJmYxA8VsGVehkYXE6Qd6mxsUTA4onasdmXdgz2/v9yNgcUJEKFunnQbB757 pbfuwAD1sF1R6fqY/QMFSnRNCV2acKsiLrdQyHtSPU3BLpcgmqe6UNaacP8N4kfrdoeG YfvqQ4HKxojUU5t3LRSkg2UKpse+rMQGPstvaoRNgy4fltmjxT9hsRXVWo/5gXzAim+l 7Z7hgKcKae4orTqhJlrJeecpGJkkR5fn5H89MvOjI8ppOqGLtRaL1LPJRjft+YMjX1eG w4pHi0fEnvbfVS8RByVYmEBqRrc5owXBM2S/VrEWVRNYj7wlg1IJzul3JPMJSuuZ/Q8c EbnQ== X-Forwarded-Encrypted: i=1; AJvYcCUlX1/GQSq8ZC82w4VCSF0JbY1b0VRyRvdiUpxKECTjHyI4ep6HmyaMF/z6usHBcNuxb0jrEswr2nhKcHw=@vger.kernel.org X-Gm-Message-State: AOJu0Yw9aEv/LQZxrN7JR9htnnnaoRVUMv7T+duRF47Skc4XFNUpBle/ qq8LRFmqENXMXozCs1q3ffaFwWmPd4XNrNKmuQc5ilM/zfpueffguuN6 X-Gm-Gg: ASbGnctiqSt4ccBsyYh5NMDxsWfRK889zlQe7sQplJUbMqIhaOysJjO251eShQlZjdi J0PuRs2LHkVOalzbfG76Cm9hN2NsdYXiJ2h/rfR7BP8TjuKpZzf5IPyGZF6c6bXrNHyE/VL73ew MYBhbDi894+s7SV4GDo/LqKiiPgq0/3tmHfmaCRb9hLrfF4PbKnubWhRGrxYEXWlN1PzOnoJk9D B/TXVV4W0asrR/SIzbYqhkkBom5zCIW7MIqjwC19wxlju6Zci0O1ci9Q+5Dqy7o6E3VEjeSfJ0l 6IxgnB5p4bB86TcmXZboJ4d+eCCTHRlFZOtYDKMnPvoflNUbe1kxbGqPcfVuy7L0GcrZUW2JIjF dn7YcVTa7umVBOccha+jzE6u3rwbZp5oGHHeO7d4ua7O+nZEFJznfjgJJTzJGYfAs/b9u6Zv1gR Aiy9xhdQUaFa8xvsYFu7+1oqdrucD/8dxwrloqkWvi6Ix+EQF/9XKFHSYn3ruGXAA4Zk4hTkCK4 Depi0prm/uFTziW1ysI X-Google-Smtp-Source: AGHT+IE8tGIqKknBmSR/YjZ0JxDzGHwDUZlXi4SXMFnGrMTTa5U7E8C9N7e2anx+wAKtOY9fgQgPgw== X-Received: by 2002:a05:6a20:3d84:b0:2b3:4f2a:d2e9 with SMTP id adf61e73a8af0-334a8515183mr2709377637.9.1760675018085; Thu, 16 Oct 2025 21:23:38 -0700 (PDT) Received: from toolbx.alistair23.me (2403-580b-97e8-0-82ce-f179-8a79-69f4.ip6.aussiebb.net. [2403:580b:97e8:0:82ce:f179:8a79:69f4]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-33be54cad3esm245557a91.12.2025.10.16.21.23.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Oct 2025 21:23:37 -0700 (PDT) From: alistair23@gmail.com X-Google-Original-From: alistair.francis@wdc.com To: chuck.lever@oracle.com, hare@kernel.org, kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-nvme@lists.infradead.org, linux-nfs@vger.kernel.org Cc: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me, kch@nvidia.com, hare@suse.de, alistair23@gmail.com, Alistair Francis Subject: [PATCH v4 1/7] net/handshake: Store the key serial number on completion Date: Fri, 17 Oct 2025 14:23:06 +1000 Message-ID: <20251017042312.1271322-2-alistair.francis@wdc.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251017042312.1271322-1-alistair.francis@wdc.com> References: <20251017042312.1271322-1-alistair.francis@wdc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alistair Francis Allow userspace to include a key serial number when completing a handshake with the HANDSHAKE_CMD_DONE command. We then store this serial number and will provide it back to userspace in the future. This allows userspace to save data to the keyring and then restore that data later. This will be used to support the TLS KeyUpdate operation, as now userspace can resume information about a established session. Signed-off-by: Alistair Francis Reviewed-by: Hannes Reincke --- v4: - No change v3: - No change v2: - Change "key-serial" to "session-id" Documentation/netlink/specs/handshake.yaml | 4 ++++ Documentation/networking/tls-handshake.rst | 2 ++ drivers/nvme/host/tcp.c | 3 ++- drivers/nvme/target/tcp.c | 3 ++- include/net/handshake.h | 4 +++- include/uapi/linux/handshake.h | 1 + net/handshake/genl.c | 5 +++-- net/handshake/tlshd.c | 15 +++++++++++++-- net/sunrpc/svcsock.c | 4 +++- net/sunrpc/xprtsock.c | 4 +++- 10 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Documentation/netlink/specs/handshake.yaml b/Documentation/net= link/specs/handshake.yaml index 95c3fade7a8d..a273bc74d26f 100644 --- a/Documentation/netlink/specs/handshake.yaml +++ b/Documentation/netlink/specs/handshake.yaml @@ -87,6 +87,9 @@ attribute-sets: name: remote-auth type: u32 multi-attr: true + - + name: session-id + type: u32 =20 operations: list: @@ -123,6 +126,7 @@ operations: - status - sockfd - remote-auth + - session-id =20 mcast-groups: list: diff --git a/Documentation/networking/tls-handshake.rst b/Documentation/net= working/tls-handshake.rst index 6f5ea1646a47..d7287890056a 100644 --- a/Documentation/networking/tls-handshake.rst +++ b/Documentation/networking/tls-handshake.rst @@ -60,6 +60,8 @@ fills in a structure that contains the parameters of the = request: key_serial_t ta_my_privkey; unsigned int ta_num_peerids; key_serial_t ta_my_peerids[5]; + key_serial_t user_session_id; + }; =20 The @ta_sock field references an open and connected socket. The consumer diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 2751c15beed6..611be56f8013 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -1691,7 +1691,8 @@ static void nvme_tcp_set_queue_io_cpu(struct nvme_tcp= _queue *queue) qid, queue->io_cpu); } =20 -static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid) +static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid, + key_serial_t user_session_id) { struct nvme_tcp_queue *queue =3D data; struct nvme_tcp_ctrl *ctrl =3D queue->ctrl; diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 470bf37e5a63..4ef4dd140ada 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -1780,7 +1780,8 @@ static int nvmet_tcp_tls_key_lookup(struct nvmet_tcp_= queue *queue, } =20 static void nvmet_tcp_tls_handshake_done(void *data, int status, - key_serial_t peerid) + key_serial_t peerid, + key_serial_t user_session_id) { struct nvmet_tcp_queue *queue =3D data; =20 diff --git a/include/net/handshake.h b/include/net/handshake.h index 8ebd4f9ed26e..dc2222fd6d99 100644 --- a/include/net/handshake.h +++ b/include/net/handshake.h @@ -18,7 +18,8 @@ enum { }; =20 typedef void (*tls_done_func_t)(void *data, int status, - key_serial_t peerid); + key_serial_t peerid, + key_serial_t user_session_id); =20 struct tls_handshake_args { struct socket *ta_sock; @@ -31,6 +32,7 @@ struct tls_handshake_args { key_serial_t ta_my_privkey; unsigned int ta_num_peerids; key_serial_t ta_my_peerids[5]; + key_serial_t user_session_id; }; =20 int tls_client_hello_anon(const struct tls_handshake_args *args, gfp_t fla= gs); diff --git a/include/uapi/linux/handshake.h b/include/uapi/linux/handshake.h index 662e7de46c54..b68ffbaa5f31 100644 --- a/include/uapi/linux/handshake.h +++ b/include/uapi/linux/handshake.h @@ -55,6 +55,7 @@ enum { HANDSHAKE_A_DONE_STATUS =3D 1, HANDSHAKE_A_DONE_SOCKFD, HANDSHAKE_A_DONE_REMOTE_AUTH, + HANDSHAKE_A_DONE_SESSION_ID, =20 __HANDSHAKE_A_DONE_MAX, HANDSHAKE_A_DONE_MAX =3D (__HANDSHAKE_A_DONE_MAX - 1) diff --git a/net/handshake/genl.c b/net/handshake/genl.c index f55d14d7b726..6cdce7e5dbc0 100644 --- a/net/handshake/genl.c +++ b/net/handshake/genl.c @@ -16,10 +16,11 @@ static const struct nla_policy handshake_accept_nl_poli= cy[HANDSHAKE_A_ACCEPT_HAN }; =20 /* HANDSHAKE_CMD_DONE - do */ -static const struct nla_policy handshake_done_nl_policy[HANDSHAKE_A_DONE_R= EMOTE_AUTH + 1] =3D { +static const struct nla_policy handshake_done_nl_policy[HANDSHAKE_A_DONE_S= ESSION_ID + 1] =3D { [HANDSHAKE_A_DONE_STATUS] =3D { .type =3D NLA_U32, }, [HANDSHAKE_A_DONE_SOCKFD] =3D { .type =3D NLA_S32, }, [HANDSHAKE_A_DONE_REMOTE_AUTH] =3D { .type =3D NLA_U32, }, + [HANDSHAKE_A_DONE_SESSION_ID] =3D { .type =3D NLA_U32, }, }; =20 /* Ops table for handshake */ @@ -35,7 +36,7 @@ static const struct genl_split_ops handshake_nl_ops[] =3D= { .cmd =3D HANDSHAKE_CMD_DONE, .doit =3D handshake_nl_done_doit, .policy =3D handshake_done_nl_policy, - .maxattr =3D HANDSHAKE_A_DONE_REMOTE_AUTH, + .maxattr =3D HANDSHAKE_A_DONE_SESSION_ID, .flags =3D GENL_CMD_CAP_DO, }, }; diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c index 081093dfd553..2549c5dbccd8 100644 --- a/net/handshake/tlshd.c +++ b/net/handshake/tlshd.c @@ -26,7 +26,8 @@ =20 struct tls_handshake_req { void (*th_consumer_done)(void *data, int status, - key_serial_t peerid); + key_serial_t peerid, + key_serial_t user_session_id); void *th_consumer_data; =20 int th_type; @@ -39,6 +40,8 @@ struct tls_handshake_req { =20 unsigned int th_num_peerids; key_serial_t th_peerid[5]; + + key_serial_t user_session_id; }; =20 static struct tls_handshake_req * @@ -55,6 +58,7 @@ tls_handshake_req_init(struct handshake_req *req, treq->th_num_peerids =3D 0; treq->th_certificate =3D TLS_NO_CERT; treq->th_privkey =3D TLS_NO_PRIVKEY; + treq->user_session_id =3D TLS_NO_PRIVKEY; return treq; } =20 @@ -83,6 +87,13 @@ static void tls_handshake_remote_peerids(struct tls_hand= shake_req *treq, if (i >=3D treq->th_num_peerids) break; } + + nla_for_each_attr(nla, head, len, rem) { + if (nla_type(nla) =3D=3D HANDSHAKE_A_DONE_SESSION_ID) { + treq->user_session_id =3D nla_get_u32(nla); + break; + } + } } =20 /** @@ -105,7 +116,7 @@ static void tls_handshake_done(struct handshake_req *re= q, set_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags); =20 treq->th_consumer_done(treq->th_consumer_data, -status, - treq->th_peerid[0]); + treq->th_peerid[0], treq->user_session_id); } =20 #if IS_ENABLED(CONFIG_KEYS) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 7b90abc5cf0e..bc9a713c6559 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -444,13 +444,15 @@ static void svc_tcp_kill_temp_xprt(struct svc_xprt *x= prt) * @data: address of xprt to wake * @status: status of handshake * @peerid: serial number of key containing the remote peer's identity + * @user_session_id: serial number of the userspace session ID * * If a security policy is specified as an export option, we don't * have a specific export here to check. So we set a "TLS session * is present" flag on the xprt and let an upper layer enforce local * security policy. */ -static void svc_tcp_handshake_done(void *data, int status, key_serial_t pe= erid) +static void svc_tcp_handshake_done(void *data, int status, key_serial_t pe= erid, + key_serial_t user_session_id) { struct svc_xprt *xprt =3D data; struct svc_sock *svsk =3D container_of(xprt, struct svc_sock, sk_xprt); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 3aa987e7f072..bce0f43bef65 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2589,9 +2589,11 @@ static int xs_tcp_tls_finish_connecting(struct rpc_x= prt *lower_xprt, * @data: address of xprt to wake * @status: status of handshake * @peerid: serial number of key containing the remote's identity + * @user_session_id: serial number of the userspace session ID * */ -static void xs_tls_handshake_done(void *data, int status, key_serial_t pee= rid) +static void xs_tls_handshake_done(void *data, int status, key_serial_t pee= rid, + key_serial_t user_session_id) { struct rpc_xprt *lower_xprt =3D data; struct sock_xprt *lower_transport =3D --=20 2.51.0 From nobody Mon Feb 9 11:34:54 2026 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0DF630E0E3 for ; Fri, 17 Oct 2025 04:23:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675026; cv=none; b=uR4mzWaeIcPwgLuVwGeTUlShAMIsm/CQ7m6WNip/quWNcTmul993gSsJ6WdqGBjCWT1pGUhJx1GhdaLeQRRvN8Py3CXBpNx1IVbDTT2nw0h3jZXz7yKvlOYA3u8IUPlUoIYgfVlfkjFcqLWKEtz0lKCqJGXVme8UrTKytxDLj9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675026; c=relaxed/simple; bh=37YeEv3sX+mmDjcIQ5fmoI0jB8MoKSf0MBI8d/gZIrU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LsWuZ/LJ7JJQrpncDWer6oQbS97AF5hC13Vt403QXXlUE/oEgy0+UYPxdniQpVIxmJ3mcdaZ4qKldNEOE34JdvEwV0P0JEUaQ+59LHFc/n53o6LKXdaJNgyBL4QS8bTo9hQVyCz/S+Oy5DfHzlizm02nVdpjDnNwMeMptRoeeAU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VllHUtkz; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VllHUtkz" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-269af38418aso15271055ad.1 for ; Thu, 16 Oct 2025 21:23:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760675024; x=1761279824; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZhR6OqlULE14euOr7SOeJPbIcbHzF9rdhJ80nFJJwb0=; b=VllHUtkzMpkUXDvPypYbSO7h4bOUgAdTvvSKA0faHZYqPsXz3wQX/CK2IaTCL9+7jc 3y7IrDez1pdZREPnV45jiEcl0FXjMh3E8OdTG7Gw5Iu9bAryYuxNucYUQWFpNDOATIo/ 5KVTpWnIioxUCqHO2oPvEaBixWNCGtfGrhyoa9mjqZQaOxjQybUYkzRAqeBUNkqYzcRK XiRAHrUxXPKXFE7J/OSXNDyXNn7SobMth4W5M3eGKfKTlmk8nXIsTShtpgS/wX26O5yu V/mVww6ON1msCEYb/3cODPaOOPlFJSc/QiLTiVOzeSuJxboqBXAWYIpVWgVGGJxbFmJK AV/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760675024; x=1761279824; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZhR6OqlULE14euOr7SOeJPbIcbHzF9rdhJ80nFJJwb0=; b=hUwCOWBUtpaMs78EZMsobgdJJ/HGH3ZjKjDWEieD0ydVUyciupVSdNMBzotcxqL+TA LJqj7IjfOlao0uzwqpReIkn3JkbL3wVg2E8WlIo5ORTT4+Kj1A7Z2VlaRLNbJuCclA1c 28Stam+bKadwAd1MsbUkBtNhvGDYrCjSwqxIKBvWEccR0oiq7E1NZmjK92qQ6jDbJCIi pDIk9WLT94427WF6o5Sk3FVKs8osAFhN/Y1D670IHCwBCTng73pveFm3jCfEHBYCM8NN m5i17QEBPPz8vXnCP7CQCtQohUBhiM30K1yUHHUHs8knwUJWcUW4mCNT1rk1CWDXRICL i5HQ== X-Forwarded-Encrypted: i=1; AJvYcCWj5dzOFleMycNebxl+CuRlS0b+pXItF59f6CXRNxi2fCdJDyuCv4oC3yj1KtkClt/8RLmrAFjMNw2saek=@vger.kernel.org X-Gm-Message-State: AOJu0YzgAn8d9fBm9MSlSGz8xnTrgBk8KxocKdUBITVpi/b5EYEXm5Hu NA9TdWLwYdShB0Qano36TiXKQDVaj7uXccBMClCcEsMDysxY8F7Dz+zi X-Gm-Gg: ASbGncuhiR9HRDyks8Vu+nZhzLRbFxX/g6ozQvtFqPJpqiTMJjGsvq6SL2dNZGDGO07 55VFtcNqN6FSJXc3V6GvC+oSSCg+ORvuh4kSoWWnonkGfs3an6UzBLP3798Yr8J0ZIKeO6H2Y+0 z81diIQtfUx2zvQxqrgI4m5bnIOQJYj+F1HqsNUEgEHVK1vzLavvjYK+BR0sdGxAuYQLZdro6k5 Z84NaT5ehTmktbj5Dq61KJYNZp/X0u8ch0ckyB3Wkf3GST7HwbKQWTDLLCTehygvUcYKToEi5qh ihCHsfVeWbdV6ekM/bvUfuSyi3cTK+YIViUZclqMwyVCqhQPnsk/LZnYQGKf6OHsQP+gSMgRlbz pZlMcdMFYrElSm7n0YJEtQq/DOLd4OXCslavlgtzxMR+If+95+KMjAvaZaRkYvWy71s0qpnz1pL jMDR648EMaqhAAr9Ppu4ZUMYwd5Au8tMbYagHMC2y0HgVhW4yABUTzcILNCIV6iBymW1Wcq+Aeq kdFiSNS1Sa5pjnP/39y X-Google-Smtp-Source: AGHT+IFs1j5KeQPUYHknhxmr73Cz8lIn7tiQ+fRQndA5W23hoDMgcJ9Yk8+rVDxwb74P5c6XfgnCZQ== X-Received: by 2002:a17:903:b90:b0:269:9a7a:9a43 with SMTP id d9443c01a7336-290c9c89fdfmr20658745ad.10.1760675024212; Thu, 16 Oct 2025 21:23:44 -0700 (PDT) Received: from toolbx.alistair23.me (2403-580b-97e8-0-82ce-f179-8a79-69f4.ip6.aussiebb.net. [2403:580b:97e8:0:82ce:f179:8a79:69f4]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-33be54cad3esm245557a91.12.2025.10.16.21.23.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Oct 2025 21:23:43 -0700 (PDT) From: alistair23@gmail.com X-Google-Original-From: alistair.francis@wdc.com To: chuck.lever@oracle.com, hare@kernel.org, kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-nvme@lists.infradead.org, linux-nfs@vger.kernel.org Cc: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me, kch@nvidia.com, hare@suse.de, alistair23@gmail.com, Alistair Francis Subject: [PATCH v4 2/7] net/handshake: Define handshake_sk_destruct_req Date: Fri, 17 Oct 2025 14:23:07 +1000 Message-ID: <20251017042312.1271322-3-alistair.francis@wdc.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251017042312.1271322-1-alistair.francis@wdc.com> References: <20251017042312.1271322-1-alistair.francis@wdc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alistair Francis Define a `handshake_sk_destruct_req()` function to allow the destruction of the handshake req. This is required to avoid hash conflicts when handshake_req_hash_add() is called as part of submitting the KeyUpdate request. Signed-off-by: Alistair Francis Reviewed-by: Hannes Reinecke --- v4: - No change v3: - New patch net/handshake/request.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/handshake/request.c b/net/handshake/request.c index 274d2c89b6b2..0d1c91c80478 100644 --- a/net/handshake/request.c +++ b/net/handshake/request.c @@ -98,6 +98,22 @@ static void handshake_sk_destruct(struct sock *sk) sk_destruct(sk); } =20 +/** + * handshake_sk_destruct_req - destroy an existing request + * @sk: socket on which there is an existing request + */ +static void handshake_sk_destruct_req(struct sock *sk) +{ + struct handshake_req *req; + + req =3D handshake_req_hash_lookup(sk); + if (!req) + return; + + trace_handshake_destruct(sock_net(sk), req, sk); + handshake_req_destroy(req); +} + /** * handshake_req_alloc - Allocate a handshake request * @proto: security protocol --=20 2.51.0 From nobody Mon Feb 9 11:34:54 2026 Received: from mail-pj1-f43.google.com (mail-pj1-f43.google.com [209.85.216.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FA1430F55E for ; Fri, 17 Oct 2025 04:23:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675032; cv=none; b=ghhQtRwfhTTa4WhqkC16o1zczE+Lx7lDoINeUEQbA2g7ijFSq6NbjhqDKuZdwv/I4PBKarVpv2WRs5u+lJEskz8STe5ZTSEz2LLh2HH92GnzUNcvUk8MJ8eSsrBNs6r65fkZc1T7adSgofzqs9YmWvJ+QIFk4Lre5nBh8aCt90M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675032; c=relaxed/simple; bh=qJIYSnU+HoRbvlx3ywhGBF4rw4sM63dPw5pKUX1ZIk8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EXx1yqbXzB7J9Y41VW9gfckLOqsN9xgcXcwaZKoylrNsWvmD9PAcJeugShpkg/Q+t6SNsgbi9GGyK/4zfjt2ND7NZRhoTYQnLsoCAWx42fLugiY1YKDBPpvmf9tE/prs5Ssgmhol8P5QWqg0JgQkRPWS8E50/+lZL5vVUYAUYWs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TA3KMUJZ; arc=none smtp.client-ip=209.85.216.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TA3KMUJZ" Received: by mail-pj1-f43.google.com with SMTP id 98e67ed59e1d1-330b4739538so1352143a91.3 for ; Thu, 16 Oct 2025 21:23:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760675030; x=1761279830; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kAkZgFdLzvs8Exsdja0IC6onWedwrzXxt2HCf6MfZEs=; b=TA3KMUJZ3wdXrdHBGXOHDBRRCFsBGRv825EEWg5FMuQd7150NIItSQ0LksJfiXg9Jo z6eIrJH5vbhC3GhhETfjYPPVLb4kEfQS8GgDmWRGg534bRmpCsnZqN4g/Ux/PMul3vx0 FGYHP1nfR6iMgK+IclnXv36uI6ruWqpaFHHXD2ndkI2ehG5l00snqaKwNrkRHnPhsYpl xgJdS8h+F/M5B/CXFLDZwAc+bfVHan1bWWltCsaSlC5KCgXY9XAoQ3qh7FIgRvwfiEc7 rY/8z8JRA2oPBVOv57dPYHztfpn8MNnkfBU/KL4ZLnu1u9NQ9siG/q59po+ThuoSmTEC sG4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760675030; x=1761279830; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kAkZgFdLzvs8Exsdja0IC6onWedwrzXxt2HCf6MfZEs=; b=I428hTyo6xErXZk8c8A4HA4ipUNHM8mtetYa9iDVB/kGqV0wXySuzYOfVLyLsn0D+o YU81chbBfBY5aB6TaqmW5uqc51IeVvoJAUnHoSiW1D66yz7j5hIXiQO/IezVtjBj9+Vr 4qm5Gha4UPhwB8bolwDZuWfXdY3kkDSG4fleBedoTrATTAucgktMeOTYD5RefTHGFdoM kpivDUfn4Drcecy4n7Zl/Rlc/59P4uQsSMyXbKICNyH4WJ4rlEhaA9Ubx7L3B1KH1v1x HI109yu6sc0yzRFp8SjSIyaWXVlVlyfBrhWh+OXZOxB/M1eMzHbcCqtaMvhFwj84xE13 HBCA== X-Forwarded-Encrypted: i=1; AJvYcCUF1rmdPvPibBQP8+D1erY261s4m9wDp5TUAN15LoIQUUWcRm4BUCRjfVtEM69uK2g06TZdPq6Lx+hofdY=@vger.kernel.org X-Gm-Message-State: AOJu0Ywjdu2eqyHSAZ2kbaoZ7sW62tdcCUi70HJwdOMSn/+SiwN/V78Q D34OnjP5WwGYXlhohiOSsfwuik21y+rd2cdMMs3IBXVzJDamzVqxKcre X-Gm-Gg: ASbGncu4qRGxOV4gBCYODmtzoATuC4nE5zNdFxFZqAnQjZoaduIyRYfthwGjIibjggr 8Cd374siqYglyNV6u9D6Y+MQCbSlB2flE+zN/WrA0xWVIYX/Wvr1u6E10/TE0GleUENNchReAsQ vZ5AeLK+dHKG/DyhTdmhEIln4FXrxtdUEJfNXN7LIzuE3be8g+80cQI8P/f43LacedUNi2Pz7Bq 8dkDhoDSgmOIaIOW03J8zDLhoO8+04vI3DkAy6pehxlptV4iilIQKJuuu+P1/Vr/s6zeJC6NI/P 15HZzQMzIrA9DthbrU1fZFWDLngcGXv7eBQdVqHhsqPA4VENRJWLgAT5MgU7mfVOVlZE7eYGq7z eGZxlCOzweCpp9sNcDZbiXwGkSFT+tQVzegwQ0O050Ju10xcYVR6EswEBYB/ldtABy6D98eK9PV zkNeIdgqIrkfNON9kzyxhscgS8aoR2zPDVuTqIcdJ3Z7NST39WEydyCu4IAOqvMT57CuEgiE7o2 STOwR8mrvw0NCV5tWC2 X-Google-Smtp-Source: AGHT+IFfbNX2mTod+6zKsy5GzuQyZpJ35ah75bJLjAVf3giPURvKPzSrUXNdaNKl89D52wOXFUj7ww== X-Received: by 2002:a17:90b:2ccc:b0:33b:c9b6:1cd with SMTP id 98e67ed59e1d1-33bcf8fa1fcmr2615932a91.19.1760675030324; Thu, 16 Oct 2025 21:23:50 -0700 (PDT) Received: from toolbx.alistair23.me (2403-580b-97e8-0-82ce-f179-8a79-69f4.ip6.aussiebb.net. [2403:580b:97e8:0:82ce:f179:8a79:69f4]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-33be54cad3esm245557a91.12.2025.10.16.21.23.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Oct 2025 21:23:49 -0700 (PDT) From: alistair23@gmail.com X-Google-Original-From: alistair.francis@wdc.com To: chuck.lever@oracle.com, hare@kernel.org, kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-nvme@lists.infradead.org, linux-nfs@vger.kernel.org Cc: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me, kch@nvidia.com, hare@suse.de, alistair23@gmail.com, Alistair Francis Subject: [PATCH v4 3/7] net/handshake: Ensure the request is destructed on completion Date: Fri, 17 Oct 2025 14:23:08 +1000 Message-ID: <20251017042312.1271322-4-alistair.francis@wdc.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251017042312.1271322-1-alistair.francis@wdc.com> References: <20251017042312.1271322-1-alistair.francis@wdc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alistair Francis To avoid future handshake_req_hash_add() calls failing with EEXIST when performing a KeyUpdate let's make sure the old request is destructed as part of the completion. Until now a handshake would only be destroyed on a failure or when a sock is freed (via the sk_destruct function pointer). handshake_complete() is only called on errors, not a successful handshake so it doesn't remove the request. Signed-off-by: Alistair Francis Reviewed-by: Hannes Reinecke --- v4: - Improve description in commit message v3: - New patch net/handshake/request.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/handshake/request.c b/net/handshake/request.c index 0d1c91c80478..194725a8aaca 100644 --- a/net/handshake/request.c +++ b/net/handshake/request.c @@ -311,6 +311,8 @@ void handshake_complete(struct handshake_req *req, unsi= gned int status, /* Handshake request is no longer pending */ sock_put(sk); } + + handshake_sk_destruct_req(sk); } EXPORT_SYMBOL_IF_KUNIT(handshake_complete); =20 --=20 2.51.0 From nobody Mon Feb 9 11:34:54 2026 Received: from mail-pj1-f46.google.com (mail-pj1-f46.google.com [209.85.216.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5AB1B30C61F for ; Fri, 17 Oct 2025 04:23:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675039; cv=none; b=dPFPiNHuu9jUQ+fVOp5aDh47hhFTVTCerLuRA0hb191Mbpea5OaXIK86Po1BmnL14OPynZpME2deyEsxnaDYxXhK5Fa7Aqo0gi2ZdNIqKbr8X7c4pWPN0nZzQwaAGyQ2qtq7kfsrCQ+T3FolioKM4xDsIlVOtBw/sLnNaHvxqKQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675039; c=relaxed/simple; bh=+ekasFalVsXJKFZ9kzxIalWIkPkrJVW8hYut5gHfJbs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Sfbcn448098xLGXvLs0vucx9kVPqH5ATTCMfPrKRIhId4zyTJUjKvU5gqjF/x4yocM/LBXj9ljIq4BgdSwo85JhArwFvtpEW1DrsSpbXl2kwqq5TdIJpC/ICB2PKclGeQkadjK+E/oKz5w1uxd/4WG7PRiPhk6vxn0ixZKK1jiQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Esy274jG; arc=none smtp.client-ip=209.85.216.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Esy274jG" Received: by mail-pj1-f46.google.com with SMTP id 98e67ed59e1d1-3304dd2f119so1240956a91.2 for ; Thu, 16 Oct 2025 21:23:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760675036; x=1761279836; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JU16oluyBYBU5AvUVieF6f38wb8silk8996KSyx/0bI=; b=Esy274jGHQrZ3W5XcSbw1k4h1dMVdbREWuq2I0kxsSSRGKZx30cy8NjMaxAIOJJ138 gSh+Nc2+VD6madEFbYndxt9Jwkd2CWpgfllYXeah45Pz4WUFVfVpBMwNHHefW5EsJTCy CnbbA+slk3CyapEvJRHx47cFy+SgbOsYtMk2h8bX+aR2myi1GEboHvd4jf9N5IjLxg/a HRWDpowjAlrBW4mrNhmSzmk40Ksb5mtqytHA8Ixxd/SPpw1UoTc63eZz7k7/zsCL1+rQ UY/I6ckNSXmJTfORJUf++RbcQIUnUq/yfHNn9DRLYmtx87BIDUYum3XvnXYesyKAw3n7 TYzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760675036; x=1761279836; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JU16oluyBYBU5AvUVieF6f38wb8silk8996KSyx/0bI=; b=gdM14HSJhgSNvCZYAoYASFoYAzGn7zB1dSsmvVWpfPVhdH79zGvZpblf0ahA3HkKfA A0BOWPWA6fS2o3V8T08a/+NvhC62XYzNYLX/8rJ7jRQU7g5MWIs1BSEOmqxqvchNvDAS aHIXK6XYU6X2ZI5nJZ4sdcuhK0I07u0oqMbzqHLFVrLAYNwM0+dbJzyL/jIhIQ5inSsY F3YjpRPTn0DKB1p8i4h6GREOMI43hr24QVJpHm4O6ZcdZLDaYSfw6nMBcBf5EYlT/wV2 owHfb1UAGKMnwCOQQtb/AihBPdcBNP7f5lJtcs9UHbczePhOrIEoC+m5XHF6vOHaOHg5 DCbg== X-Forwarded-Encrypted: i=1; AJvYcCXHzu0VBHaAL2IgShApq22Ut8DOpDP/C3lEHZ5X5K7Q35X8uPHg6SCATmR3Go6w/TnfM3Pb+5cNjhYndOE=@vger.kernel.org X-Gm-Message-State: AOJu0Yx1YuUjVJLChUFMMkYnRAX56Q9vzwwTS4A28SC+vncrlKCFhYQl jyjHSn2+hQTUqbGZejRKiQWja9fxBEinFHgqyNtAFtaHAEVcaWOKViAa X-Gm-Gg: ASbGncu5EOjTLYtZsmD5XtfyTVa6njB9RH9gyzma4lCqNvjxsGoXT+9fzT0wNtCGz1q T9d+Bm9OLin4nwfu5jjhloHl9hdEy/du3v6ClLCV/OiMdS7Xll+H03588GG/oqckiX0C8rDvPwp mbinpvxnBTBewSZNVQPowLFGkud3nPHglpncguqaJ5Bc4oOLJjNuSjJwYfkkX/BJMVGhZpl2E2e z6aisgmvRioFksQ+cdWmm5oF5XQdXOtvmKlYO18xK7ELCXkn7I18KLNR7QWElnPuFbPn6F1IKRJ SYk3ejeFpz5RdsGhsSHQ8itewGzQNtWjKVrSDePXkJMSl85q9X2luJhuO1xklpy/Fgv/4GZO9Kv D+izTQ5q2QUkCgefNtgUqg15QCpKIrnD7f45aEbfjVs6JM5dwqb/sa782I61s2J2pKC0O0v8S40 6207Dm6o2TuQxJ8jrs7EzDE7WMzWV28cNJk4nWo95yh4jb9Ig+HNKRFY9knK/b03ZurL4a2hRar gNie2AmQSKHXEaI6OtZ X-Google-Smtp-Source: AGHT+IGLOnUugbLEaMm8emhVTwGbBDc/InDpSx6ku4mK0z8X35Z7r6wOx9oRpJvKxnCh9rM5u21MKA== X-Received: by 2002:a17:90b:180a:b0:329:7285:6941 with SMTP id 98e67ed59e1d1-33bcf8e4e35mr2895374a91.19.1760675036441; Thu, 16 Oct 2025 21:23:56 -0700 (PDT) Received: from toolbx.alistair23.me (2403-580b-97e8-0-82ce-f179-8a79-69f4.ip6.aussiebb.net. [2403:580b:97e8:0:82ce:f179:8a79:69f4]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-33be54cad3esm245557a91.12.2025.10.16.21.23.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Oct 2025 21:23:55 -0700 (PDT) From: alistair23@gmail.com X-Google-Original-From: alistair.francis@wdc.com To: chuck.lever@oracle.com, hare@kernel.org, kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-nvme@lists.infradead.org, linux-nfs@vger.kernel.org Cc: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me, kch@nvidia.com, hare@suse.de, alistair23@gmail.com, Alistair Francis Subject: [PATCH v4 4/7] net/handshake: Support KeyUpdate message types Date: Fri, 17 Oct 2025 14:23:09 +1000 Message-ID: <20251017042312.1271322-5-alistair.francis@wdc.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251017042312.1271322-1-alistair.francis@wdc.com> References: <20251017042312.1271322-1-alistair.francis@wdc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alistair Francis When reporting the msg-type to userspace let's also support reporting KeyUpdate events. This supports reporting a client/server event and if the other side requested a KeyUpdateRequest. Link: https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.3 Signed-off-by: Alistair Francis --- v4: - Don't overload existing functions, instead create new ones v3: - Fixup yamllint and kernel-doc failures Documentation/netlink/specs/handshake.yaml | 16 ++++- drivers/nvme/host/tcp.c | 15 +++- drivers/nvme/target/tcp.c | 10 ++- include/net/handshake.h | 8 +++ include/uapi/linux/handshake.h | 13 ++++ net/handshake/tlshd.c | 83 +++++++++++++++++++++- 6 files changed, 137 insertions(+), 8 deletions(-) diff --git a/Documentation/netlink/specs/handshake.yaml b/Documentation/net= link/specs/handshake.yaml index a273bc74d26f..c72ec8fa7d7a 100644 --- a/Documentation/netlink/specs/handshake.yaml +++ b/Documentation/netlink/specs/handshake.yaml @@ -21,12 +21,18 @@ definitions: type: enum name: msg-type value-start: 0 - entries: [unspec, clienthello, serverhello] + entries: [unspec, clienthello, serverhello, clientkeyupdate, + clientkeyupdaterequest, serverkeyupdate, serverkeyupdaterequ= est] - type: enum name: auth value-start: 0 entries: [unspec, unauth, psk, x509] + - + type: enum + name: key-update-type + value-start: 0 + entries: [unspec, send, received, received_request_update] =20 attribute-sets: - @@ -74,6 +80,13 @@ attribute-sets: - name: keyring type: u32 + - + name: key-update-request + type: u32 + enum: key-update-type + - + name: key-serial + type: u32 - name: done attributes: @@ -116,6 +129,7 @@ operations: - certificate - peername - keyring + - key-serial - name: done doc: Handler reports handshake completion diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 611be56f8013..2696bf97dfac 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -20,6 +20,7 @@ #include #include #include +#include =20 #include "nvme.h" #include "fabrics.h" @@ -206,6 +207,10 @@ static struct workqueue_struct *nvme_tcp_wq; static const struct blk_mq_ops nvme_tcp_mq_ops; static const struct blk_mq_ops nvme_tcp_admin_mq_ops; static int nvme_tcp_try_send(struct nvme_tcp_queue *queue); +static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl, + struct nvme_tcp_queue *queue, + key_serial_t pskid, + handshake_key_update_type keyupdate); =20 static inline struct nvme_tcp_ctrl *to_tcp_ctrl(struct nvme_ctrl *ctrl) { @@ -1726,7 +1731,8 @@ static void nvme_tcp_tls_done(void *data, int status,= key_serial_t pskid, =20 static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl, struct nvme_tcp_queue *queue, - key_serial_t pskid) + key_serial_t pskid, + handshake_key_update_type keyupdate) { int qid =3D nvme_tcp_queue_id(queue); int ret; @@ -1748,7 +1754,10 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctr= l, args.ta_timeout_ms =3D tls_handshake_timeout * 1000; queue->tls_err =3D -EOPNOTSUPP; init_completion(&queue->tls_complete); - ret =3D tls_client_hello_psk(&args, GFP_KERNEL); + if (keyupdate =3D=3D HANDSHAKE_KEY_UPDATE_TYPE_UNSPEC) + ret =3D tls_client_hello_psk(&args, GFP_KERNEL); + else + ret =3D tls_client_keyupdate_psk(&args, GFP_KERNEL, keyupdate); if (ret) { dev_err(nctrl->device, "queue %d: failed to start TLS: %d\n", qid, ret); @@ -1898,7 +1907,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nct= rl, int qid, =20 /* If PSKs are configured try to start TLS */ if (nvme_tcp_tls_configured(nctrl) && pskid) { - ret =3D nvme_tcp_start_tls(nctrl, queue, pskid); + ret =3D nvme_tcp_start_tls(nctrl, queue, pskid, HANDSHAKE_KEY_UPDATE_TYP= E_UNSPEC); if (ret) goto err_init_connect; } diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 4ef4dd140ada..8aeec4a7f136 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -1833,7 +1833,8 @@ static void nvmet_tcp_tls_handshake_timeout(struct wo= rk_struct *w) kref_put(&queue->kref, nvmet_tcp_release_queue); } =20 -static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue) +static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue, + handshake_key_update_type keyupdate) { int ret =3D -EOPNOTSUPP; struct tls_handshake_args args; @@ -1852,7 +1853,10 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp_= queue *queue) args.ta_keyring =3D key_serial(queue->port->nport->keyring); args.ta_timeout_ms =3D tls_handshake_timeout * 1000; =20 - ret =3D tls_server_hello_psk(&args, GFP_KERNEL); + if (keyupdate =3D=3D HANDSHAKE_KEY_UPDATE_TYPE_UNSPEC) + ret =3D tls_server_hello_psk(&args, GFP_KERNEL); + else + ret =3D tls_server_keyupdate_psk(&args, GFP_KERNEL, keyupdate); if (ret) { kref_put(&queue->kref, nvmet_tcp_release_queue); pr_err("failed to start TLS, err=3D%d\n", ret); @@ -1934,7 +1938,7 @@ static void nvmet_tcp_alloc_queue(struct nvmet_tcp_po= rt *port, sk->sk_data_ready =3D port->data_ready; write_unlock_bh(&sk->sk_callback_lock); if (!nvmet_tcp_try_peek_pdu(queue)) { - if (!nvmet_tcp_tls_handshake(queue)) + if (!nvmet_tcp_tls_handshake(queue, HANDSHAKE_KEY_UPDATE_TYPE_UNSPEC)) return; /* TLS handshake failed, terminate the connection */ goto out_destroy_sq; diff --git a/include/net/handshake.h b/include/net/handshake.h index dc2222fd6d99..084c92a20b68 100644 --- a/include/net/handshake.h +++ b/include/net/handshake.h @@ -10,6 +10,10 @@ #ifndef _NET_HANDSHAKE_H #define _NET_HANDSHAKE_H =20 +#include + +#define handshake_key_update_type u32 + enum { TLS_NO_KEYRING =3D 0, TLS_NO_PEERID =3D 0, @@ -38,8 +42,12 @@ struct tls_handshake_args { int tls_client_hello_anon(const struct tls_handshake_args *args, gfp_t fla= gs); int tls_client_hello_x509(const struct tls_handshake_args *args, gfp_t fla= gs); int tls_client_hello_psk(const struct tls_handshake_args *args, gfp_t flag= s); +int tls_client_keyupdate_psk(const struct tls_handshake_args *args, gfp_t = flags, + handshake_key_update_type keyupdate); int tls_server_hello_x509(const struct tls_handshake_args *args, gfp_t fla= gs); int tls_server_hello_psk(const struct tls_handshake_args *args, gfp_t flag= s); +int tls_server_keyupdate_psk(const struct tls_handshake_args *args, gfp_t = flags, + handshake_key_update_type keyupdate); =20 bool tls_handshake_cancel(struct sock *sk); void tls_handshake_close(struct socket *sock); diff --git a/include/uapi/linux/handshake.h b/include/uapi/linux/handshake.h index b68ffbaa5f31..b691530073c6 100644 --- a/include/uapi/linux/handshake.h +++ b/include/uapi/linux/handshake.h @@ -19,6 +19,10 @@ enum handshake_msg_type { HANDSHAKE_MSG_TYPE_UNSPEC, HANDSHAKE_MSG_TYPE_CLIENTHELLO, HANDSHAKE_MSG_TYPE_SERVERHELLO, + HANDSHAKE_MSG_TYPE_CLIENTKEYUPDATE, + HANDSHAKE_MSG_TYPE_CLIENTKEYUPDATEREQUEST, + HANDSHAKE_MSG_TYPE_SERVERKEYUPDATE, + HANDSHAKE_MSG_TYPE_SERVERKEYUPDATEREQUEST, }; =20 enum handshake_auth { @@ -28,6 +32,13 @@ enum handshake_auth { HANDSHAKE_AUTH_X509, }; =20 +enum handshake_key_update_type { + HANDSHAKE_KEY_UPDATE_TYPE_UNSPEC, + HANDSHAKE_KEY_UPDATE_TYPE_SEND, + HANDSHAKE_KEY_UPDATE_TYPE_RECEIVED, + HANDSHAKE_KEY_UPDATE_TYPE_RECEIVED_REQUEST_UPDATE, +}; + enum { HANDSHAKE_A_X509_CERT =3D 1, HANDSHAKE_A_X509_PRIVKEY, @@ -46,6 +57,8 @@ enum { HANDSHAKE_A_ACCEPT_CERTIFICATE, HANDSHAKE_A_ACCEPT_PEERNAME, HANDSHAKE_A_ACCEPT_KEYRING, + HANDSHAKE_A_ACCEPT_KEY_UPDATE_REQUEST, + HANDSHAKE_A_ACCEPT_KEY_SERIAL, =20 __HANDSHAKE_A_ACCEPT_MAX, HANDSHAKE_A_ACCEPT_MAX =3D (__HANDSHAKE_A_ACCEPT_MAX - 1) diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c index 2549c5dbccd8..c40839977ab9 100644 --- a/net/handshake/tlshd.c +++ b/net/handshake/tlshd.c @@ -41,6 +41,7 @@ struct tls_handshake_req { unsigned int th_num_peerids; key_serial_t th_peerid[5]; =20 + int th_key_update_request; key_serial_t user_session_id; }; =20 @@ -58,7 +59,8 @@ tls_handshake_req_init(struct handshake_req *req, treq->th_num_peerids =3D 0; treq->th_certificate =3D TLS_NO_CERT; treq->th_privkey =3D TLS_NO_PRIVKEY; - treq->user_session_id =3D TLS_NO_PRIVKEY; + treq->user_session_id =3D args->user_session_id; + return treq; } =20 @@ -265,6 +267,16 @@ static int tls_handshake_accept(struct handshake_req *= req, break; } =20 + ret =3D nla_put_u32(msg, HANDSHAKE_A_ACCEPT_KEY_SERIAL, + treq->user_session_id); + if (ret < 0) + goto out_cancel; + + ret =3D nla_put_u32(msg, HANDSHAKE_A_ACCEPT_KEY_UPDATE_REQUEST, + treq->th_key_update_request); + if (ret < 0) + goto out_cancel; + genlmsg_end(msg, hdr); return genlmsg_reply(msg, info); =20 @@ -372,6 +384,44 @@ int tls_client_hello_psk(const struct tls_handshake_ar= gs *args, gfp_t flags) } EXPORT_SYMBOL(tls_client_hello_psk); =20 +/** + * tls_client_keyupdate_psk - request a PSK-based TLS handshake on a socket + * @args: socket and handshake parameters for this request + * @flags: memory allocation control flags + * @keyupdate: specifies the type of KeyUpdate operation + * + * Return values: + * %0: Handshake request enqueue; ->done will be called when complete + * %-EINVAL: Wrong number of local peer IDs + * %-ESRCH: No user agent is available + * %-ENOMEM: Memory allocation failed + */ +int tls_client_keyupdate_psk(const struct tls_handshake_args *args, gfp_t = flags, + handshake_key_update_type keyupdate) +{ + struct tls_handshake_req *treq; + struct handshake_req *req; + unsigned int i; + + if (!args->ta_num_peerids || + args->ta_num_peerids > ARRAY_SIZE(treq->th_peerid)) + return -EINVAL; + + req =3D handshake_req_alloc(&tls_handshake_proto, flags); + if (!req) + return -ENOMEM; + treq =3D tls_handshake_req_init(req, args); + treq->th_type =3D HANDSHAKE_MSG_TYPE_CLIENTKEYUPDATE; + treq->th_key_update_request =3D keyupdate; + treq->th_auth_mode =3D HANDSHAKE_AUTH_PSK; + treq->th_num_peerids =3D args->ta_num_peerids; + for (i =3D 0; i < args->ta_num_peerids; i++) + treq->th_peerid[i] =3D args->ta_my_peerids[i]; + + return handshake_req_submit(args->ta_sock, req, flags); +} +EXPORT_SYMBOL(tls_client_keyupdate_psk); + /** * tls_server_hello_x509 - request a server TLS handshake on a socket * @args: socket and handshake parameters for this request @@ -428,6 +478,37 @@ int tls_server_hello_psk(const struct tls_handshake_ar= gs *args, gfp_t flags) } EXPORT_SYMBOL(tls_server_hello_psk); =20 +/** + * tls_server_keyupdate_psk - request a server TLS KeyUpdate on a socket + * @args: socket and handshake parameters for this request + * @flags: memory allocation control flags + * @keyupdate: specifies the type of KeyUpdate operation + * + * Return values: + * %0: Handshake request enqueue; ->done will be called when complete + * %-ESRCH: No user agent is available + * %-ENOMEM: Memory allocation failed + */ +int tls_server_keyupdate_psk(const struct tls_handshake_args *args, gfp_t = flags, + handshake_key_update_type keyupdate) +{ + struct tls_handshake_req *treq; + struct handshake_req *req; + + req =3D handshake_req_alloc(&tls_handshake_proto, flags); + if (!req) + return -ENOMEM; + treq =3D tls_handshake_req_init(req, args); + treq->th_type =3D HANDSHAKE_MSG_TYPE_SERVERKEYUPDATE; + treq->th_key_update_request =3D keyupdate; + treq->th_auth_mode =3D HANDSHAKE_AUTH_PSK; + treq->th_num_peerids =3D 1; + treq->th_peerid[0] =3D args->ta_my_peerids[0]; + + return handshake_req_submit(args->ta_sock, req, flags); +} +EXPORT_SYMBOL(tls_server_keyupdate_psk); + /** * tls_handshake_cancel - cancel a pending handshake * @sk: socket on which there is an ongoing handshake --=20 2.51.0 From nobody Mon Feb 9 11:34:54 2026 Received: from mail-pg1-f172.google.com (mail-pg1-f172.google.com [209.85.215.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68F4430FC3D for ; Fri, 17 Oct 2025 04:24:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675045; cv=none; b=PPpwRkiBH7AoP32zQkdavDT7ljY1KAaUyadjaXBP+sD+Km5QyuqyRxtDAesQj+30akDczn6uHoIIa5H6UsxBFJO1/PlwNA8Wv42vqjh+HVk4oAkwRpXUw6CJEkcXnHUIeSpNonOgFaSujyMOMi0p2fiH2fFV4ObJ2xywKcxUgo4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675045; c=relaxed/simple; bh=egKMjdwqXFVhXo0/qrA1CwLDO+yiuNAjeyMBOfRZGcw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rr/gv3V4EmGsx7GIY2AodCv63eausO0KCRb09i1oTU8Rlfx/FJpHjtjv5fnR4rdwOmfQ7EudKg2IVptn7LCG5cR+0NWKAa99qY628dWW7kEtJojkYdYEUMLnDr6oXiudatsSrdg+4ywpj4dhX1LCVA9KkjJeeum6qkoEXF2yI3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Q9kLgCPF; arc=none smtp.client-ip=209.85.215.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Q9kLgCPF" Received: by mail-pg1-f172.google.com with SMTP id 41be03b00d2f7-b67ae7e76abso1119453a12.3 for ; Thu, 16 Oct 2025 21:24:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760675042; x=1761279842; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ynJnGU8No3Ej9J48gvJNh3pD5kzmZrz6FyAMKm2dKu0=; b=Q9kLgCPFd8C8xEHHLimehO7V7DjRAykcGUUK2NVEMMpfzhYLaPh8NMwhUVM8iKuSfe 2OX6YM6dgtPi3VbF7GZrZjm93FCDZSDjDOb28gP9Lj9O6vJaylEmcAIdiziQCwPT3Ait sbVe08KrzOfVSKsUkQFXatBTyshY+GOYmON3iKALYcWoTl/uqa/AGoznUNI3LiE2QZDB dniBY5Quj24LVGeIae5FtAO/d4ozQ0A/RkM/Wy8+uM7nW68KILthV3CsfZCjckdCmRFd KoL88Yi7q7ToRP/F6BK8dbQDBsfMz417Di+iHMcoM15ZPZeAyTfl1MZB4P+zoL0q9lMK Vpqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760675043; x=1761279843; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ynJnGU8No3Ej9J48gvJNh3pD5kzmZrz6FyAMKm2dKu0=; b=iwkmitWxeNm0cx3l9AO3WLClzJPiXhP8FZOPLqUiq6JYOJIhX6Mf0M5Jn14x0JOPmD PHLDevPwSmRHLbtd4I9wz0dqsHuDJHDTGqyUIYflErW9Yl1cVxFEQStv6MY8SWBqs3Xf QrQ9c4ZaMRHXRvZ0wmLhkPX1lrF3y24ZkKgXTyAAJiY1OeFrZRUnu+d/ZpP5iWwplioc CTjdNK/YLv3OmBvXzJTfT2oSkv5Sd0N94C0bavM4g9q6/cgVgaeFfcgGvi8Oy5F+mZE6 QCiZBN1vLLupmNnxaSxpBsnIyhUD6u50ETtlykFONm2FVkzCUljwPs5O/ChxnJrQ7Fsf PaqA== X-Forwarded-Encrypted: i=1; AJvYcCWbZ2N8IRg95BmVmwVLRMlWJ4dXg654iehjBawNlgHA3FG1hRqtwMcz/FM9LzcVzAkpyQQ1x1nj4MMQCts=@vger.kernel.org X-Gm-Message-State: AOJu0YwiLIW7s+1Ym9ln8nh+8bkddtiSOYw+bP9nk2LynDe+VfkV3unE Yg4SaUroZA/aD8pIA/7Wty2KAM7EBH97/BU73jucnG+ilfER0GImvT6bE0aD3Q== X-Gm-Gg: ASbGncvXq4THSUpzwCRzQ/z9/fduK/IgebbTzNwTg8hu46TnBGGC/QNBZbQSgLtkufy EmaqzcsLY3yZ/4257wFQkCgWpREq3N5bd2sOnY/vVkgic7pXWyeTXUQUefHCxmge7xOJ3QGTKKr K4QyLp3NJQH+g22cCjAicvOLzIFBDqS6N7pk6wwVEA7Sz1M1uhoMNdVwQPMiSYOBWtdS8EdaPJT 3M6aOGzSkRm3oMHKAW/IPgZsjVDgR0oU7bVA962T7wb1AM4P80yZE9BKY4MgyF1sQRo5rtr1qGV +kZI/yw3ZT+0+tKEz8rrB1ut3nZUf8pULT8TPLdkDGwQcbukXa6y3971q6RFgBVhUrw2Ht2/SLR o9oHKnuOtKHGjqK+0uo2ZCpEA6s5rKUHt5ngJWnxXaXXoZvpThH2osdARbm8Lzac5N2ja6PTEXH dJQ+TZw7f/SwSKX4yoS5oVZs+v6yEyT9rwBINZhB/6Iw+20VQtnvNJ/AWMFQcEUK7O1/nunu5ZH xeHk+PnwHeGL1PpxAwEXzN0tajZ7X0= X-Google-Smtp-Source: AGHT+IFcY3veIMHOTTRwopAq4s0Ev1n9UH4zUIWfhrPPA4Ws9V39ePWtGb2V3y+JvQ2CTsDbOiB+pg== X-Received: by 2002:a17:902:e88e:b0:246:e1b6:f9b0 with SMTP id d9443c01a7336-290c9ca6712mr28314355ad.18.1760675042582; Thu, 16 Oct 2025 21:24:02 -0700 (PDT) Received: from toolbx.alistair23.me (2403-580b-97e8-0-82ce-f179-8a79-69f4.ip6.aussiebb.net. [2403:580b:97e8:0:82ce:f179:8a79:69f4]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-33be54cad3esm245557a91.12.2025.10.16.21.23.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Oct 2025 21:24:02 -0700 (PDT) From: alistair23@gmail.com X-Google-Original-From: alistair.francis@wdc.com To: chuck.lever@oracle.com, hare@kernel.org, kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-nvme@lists.infradead.org, linux-nfs@vger.kernel.org Cc: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me, kch@nvidia.com, hare@suse.de, alistair23@gmail.com, Alistair Francis Subject: [PATCH v4 5/7] nvme-tcp: Support KeyUpdate Date: Fri, 17 Oct 2025 14:23:10 +1000 Message-ID: <20251017042312.1271322-6-alistair.francis@wdc.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251017042312.1271322-1-alistair.francis@wdc.com> References: <20251017042312.1271322-1-alistair.francis@wdc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alistair Francis If the nvme_tcp_try_send() or nvme_tcp_try_recv() functions return EKEYEXPIRED then the underlying TLS keys need to be updated. This occurs on an KeyUpdate event. If the NVMe Target (TLS server) initiates a KeyUpdate this patch will allow the NVMe layer to process the KeyUpdate request and forward the request to userspace. Userspace must then update the key to keep the connection alive. This patch allows us to handle the NVMe target sending a KeyUpdate request without aborting the connection. At this time we don't support initiating a KeyUpdate. Link: https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.3 Signed-off-by: Alistair Francis --- v4: - Remove all support for initiating KeyUpdate - Don't call cancel_work() when updating keys v3: - Don't cancel existing handshake requests v2: - Don't change the state - Use a helper function for KeyUpdates - Continue sending in nvme_tcp_send_all() after a KeyUpdate - Remove command message using recvmsg drivers/nvme/host/tcp.c | 60 ++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 2696bf97dfac..791e0cc91ad8 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -172,6 +172,7 @@ struct nvme_tcp_queue { bool tls_enabled; u32 rcv_crc; u32 snd_crc; + key_serial_t user_session_id; __le32 exp_ddgst; __le32 recv_ddgst; struct completion tls_complete; @@ -858,7 +859,10 @@ static void nvme_tcp_handle_c2h_term(struct nvme_tcp_q= ueue *queue, static int nvme_tcp_recvmsg_pdu(struct nvme_tcp_queue *queue) { char *pdu =3D queue->pdu; + char cbuf[CMSG_LEN(sizeof(char))] =3D {}; struct msghdr msg =3D { + .msg_control =3D cbuf, + .msg_controllen =3D sizeof(cbuf), .msg_flags =3D MSG_DONTWAIT, }; struct kvec iov =3D { @@ -873,12 +877,17 @@ static int nvme_tcp_recvmsg_pdu(struct nvme_tcp_queue= *queue) if (ret <=3D 0) return ret; =20 + hdr =3D queue->pdu; + if (hdr->type =3D=3D TLS_HANDSHAKE_KEYUPDATE) { + dev_err(queue->ctrl->ctrl.device, "KeyUpdate message\n"); + return 1; + } + queue->pdu_remaining -=3D ret; queue->pdu_offset +=3D ret; if (queue->pdu_remaining) return 0; =20 - hdr =3D queue->pdu; if (unlikely(hdr->hlen !=3D sizeof(struct nvme_tcp_rsp_pdu))) { if (!nvme_tcp_recv_pdu_supported(hdr->type)) goto unsupported_pdu; @@ -944,6 +953,7 @@ static int nvme_tcp_recvmsg_data(struct nvme_tcp_queue = *queue) struct request *rq =3D nvme_cid_to_rq(nvme_tcp_tagset(queue), pdu->command_id); struct nvme_tcp_request *req =3D blk_mq_rq_to_pdu(rq); + char cbuf[CMSG_LEN(sizeof(char))] =3D {}; =20 if (nvme_tcp_recv_state(queue) !=3D NVME_TCP_RECV_DATA) return 0; @@ -973,12 +983,14 @@ static int nvme_tcp_recvmsg_data(struct nvme_tcp_queu= e *queue) memset(&msg, 0, sizeof(msg)); msg.msg_iter =3D req->iter; msg.msg_flags =3D MSG_DONTWAIT; + msg.msg_control =3D cbuf, + msg.msg_controllen =3D sizeof(cbuf), =20 ret =3D sock_recvmsg(queue->sock, &msg, msg.msg_flags); if (ret < 0) { - dev_err(queue->ctrl->ctrl.device, - "queue %d failed to receive request %#x data", - nvme_tcp_queue_id(queue), rq->tag); + dev_dbg(queue->ctrl->ctrl.device, + "queue %d failed to receive request %#x data, %d", + nvme_tcp_queue_id(queue), rq->tag, ret); return ret; } if (queue->data_digest) @@ -1381,17 +1393,42 @@ static int nvme_tcp_try_recvmsg(struct nvme_tcp_que= ue *queue) } } while (result >=3D 0); =20 - if (result < 0 && result !=3D -EAGAIN) { + if (result =3D=3D -EKEYEXPIRED) { + return -EKEYEXPIRED; + } else if (result =3D=3D -EAGAIN) { + return -EAGAIN; + } else if (result < 0) { dev_err(queue->ctrl->ctrl.device, "receive failed: %d\n", result); queue->rd_enabled =3D false; nvme_tcp_error_recovery(&queue->ctrl->ctrl); - } else if (result =3D=3D -EAGAIN) - result =3D 0; + } =20 return result < 0 ? result : (queue->nr_cqe =3D nr_cqe); } =20 +static void update_tls_keys(struct nvme_tcp_queue *queue) +{ + int qid =3D nvme_tcp_queue_id(queue); + int ret; + + dev_dbg(queue->ctrl->ctrl.device, + "updating key for queue %d\n", qid); + + flush_work(&(queue->ctrl->ctrl).async_event_work); + + ret =3D nvme_tcp_start_tls(&(queue->ctrl->ctrl), + queue, queue->ctrl->ctrl.tls_pskid, + HANDSHAKE_KEY_UPDATE_TYPE_RECEIVED); + + if (ret < 0) { + dev_err(queue->ctrl->ctrl.device, + "failed to update the keys %d\n", ret); + nvme_tcp_fail_request(queue->request); + nvme_tcp_done_send_req(queue); + } +} + static void nvme_tcp_io_work(struct work_struct *w) { struct nvme_tcp_queue *queue =3D @@ -1414,8 +1451,11 @@ static void nvme_tcp_io_work(struct work_struct *w) result =3D nvme_tcp_try_recvmsg(queue); if (result > 0) pending =3D true; - else if (unlikely(result < 0)) - return; + else if (unlikely(result < 0)) { + if (result =3D=3D -EKEYEXPIRED) + update_tls_keys(queue); + break; + } =20 /* did we get some space after spending time in recv? */ if (nvme_tcp_queue_has_pending(queue) && @@ -1723,6 +1763,7 @@ static void nvme_tcp_tls_done(void *data, int status,= key_serial_t pskid, ctrl->ctrl.tls_pskid =3D key_serial(tls_key); key_put(tls_key); queue->tls_err =3D 0; + queue->user_session_id =3D user_session_id; } =20 out_complete: @@ -1752,6 +1793,7 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl, keyring =3D key_serial(nctrl->opts->keyring); args.ta_keyring =3D keyring; args.ta_timeout_ms =3D tls_handshake_timeout * 1000; + args.user_session_id =3D queue->user_session_id; queue->tls_err =3D -EOPNOTSUPP; init_completion(&queue->tls_complete); if (keyupdate =3D=3D HANDSHAKE_KEY_UPDATE_TYPE_UNSPEC) --=20 2.51.0 From nobody Mon Feb 9 11:34:54 2026 Received: from mail-pg1-f180.google.com (mail-pg1-f180.google.com [209.85.215.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 57599310764 for ; Fri, 17 Oct 2025 04:24:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675052; cv=none; b=BnMxDiZPsLw/dG2+wci7ze3eWHh3YuGq6WcUHvyDgCl03eyRx+rBM0K1rBpy2fwSk79RgRsv3uA0Z83C/1gwNpfodvF2rRWvfzVyBj1VMtnqBy0/UfvTfcJvlf0KOk5YEqB8gm4o6mG+U46Gp/0BrFAoR9e7Ti9Bx3xF24WJO8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675052; c=relaxed/simple; bh=5mK2M0hVJGfdiN3VSfq9BCNgQdVTn70R+CbJkNedk+k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hb0BB5g6WNT5ZQuZQMy61EUAX0yBzHMJIglOuUlRtcI8aPgZuD/blD4xQZfsTfUEAif0JkuY9vQpG2jfrKd6xM1IuR9KAD/aj1VUMMWSo/U0qFmwQzGKXsUY9FUoOfMICXAQ53ZQLjA3JPIMWuEPvbXk5e8ZGvsad8Qu4mcZDZ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WBOoQ82Q; arc=none smtp.client-ip=209.85.215.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WBOoQ82Q" Received: by mail-pg1-f180.google.com with SMTP id 41be03b00d2f7-b67ae7e76abso1119507a12.3 for ; Thu, 16 Oct 2025 21:24:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760675049; x=1761279849; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=29Lq2xnZtj+6Sy2WBmqrd6RHyzvurjh80XYGtTuJrGI=; b=WBOoQ82Q4+Y7rN+a2ZN8npcIO/l+yLJQ6aVHATOYgZu5YaeOwiL6j/PCDF7dImrvk/ Tg5mzfp4pKJHgdCC1qGeds/l87hbTpDZomv+lxCB91j50UiWagLFmrXtPhLokPiBAHG0 deTiBVSOVrJEeL+eFGMV9w6rEgAOvnDR1u+XB+54Dq7XJ5e21RybUfVgQHqZRINX6X18 56FxyIjftAjfsQulyPGrnCTdtWP1u5rCwo3dlidDUWwVDCN0FNpaDDzcN9ze5pXKuvEa s2bE07HQo+uC6rljxA/y+loGfAP9Z5/d4yd/lXTnK4RJ5FMyD6zayucReRLQwyWSq2xP X5Sw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760675049; x=1761279849; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=29Lq2xnZtj+6Sy2WBmqrd6RHyzvurjh80XYGtTuJrGI=; b=ckNHKf59yMXhz6Yl0AiD9IGaElaQnW4ujRKwKjFTHe7eI+s50t28hsTuLKZIgHzLxr ghZD8oByltT5HmmPKAGkzmNSCzc/o2QTeG4MBw3UpC4BvnnrLgPHmouXhJQmdqaInxjM 4Agek7q1OhHFo4OFjvy5QY2tO5TPFa8IUNwhs4ZkBBmnRq+hg56Q92JqCEG/L9hZINf9 zXldlJHQRocQCoFOQPDkEUTfkBLzxcnpMB9TOS2et6SrNYaanU/A1PusV6zS3Q3EDhRD 4tbriYsvumAFfnX0+CbjlKVq9KZhA1tvl0a3M6P6VWijERKXkdTQjHkrYTL/RJZGTr+x 7CPA== X-Forwarded-Encrypted: i=1; AJvYcCWcLCmte+FynDr33KOnWszZT9DsC7PWyNndzJQTV2QZidwxJcG/qVS6g4qyIYjL/Thq3L8AiqH3hMnIYPA=@vger.kernel.org X-Gm-Message-State: AOJu0YyPT1mQ6VgG5C9aZxwS27zNRtxbJhqr9VCqNMNNvIRCAwdNg1CC 1ZsDfNIHJwyRouADEnx1F27nFwBt2SRx/TQ4TU+YlJxL8sZsfStRmlxr X-Gm-Gg: ASbGncvqjDc6AZtDATKYsTdnjlxf6NsPD2z+bBCeXbugfHWVAKC3Fa+lV42JtAmVxSA yBfxk9QzcHRGYVsKugBM54dzk+CTM12R3K5AXjaoIs5pjWkMpWpGY5kgZ6W6vrE21hwV6e8gqyq WZiMtFYU4IR1soaQAfA/QHf3UMGiDrFLvrmv+q2iIAHWCkg1mw2DpMEXEQ3X7dxWdENr3K/GE2i 8X3JZsHygT6ZJDptJcCrmLBFK7dfn/7R4LwF9p/Qego30dyJ3jE+qFtmzTnTUzI1tXatHQXeeEY hjfvpvJmg/OXd7gsWumDEOVNX0ZBgWdJ76OlzbS2vJNQqUabjuMjyDVSHkPqFXN0I6Ul1+95iwn l1pad2x/G4WAGhiVqaECEXR7s7qeusmmja9sCfCGBiFJEwKJseItvXRWrHmDoro5EbSxtKD/gQO ipX6MkfejZZcfgqhVYi8DtrNxIpWTLicWz4L6N/YSa+ZoKy24lNCuL22KhhT2vGLx67UvwX7btq x08OkStgg7UqSVJ2jaM X-Google-Smtp-Source: AGHT+IE3Loe/21tReTiMC1KE1PN6nnxQShPQ2aeX3VGqy1tfwwjN0OSJDK1WmyW+Y1kgS8QPEPO/LQ== X-Received: by 2002:a17:903:1250:b0:290:dd1f:3d60 with SMTP id d9443c01a7336-290dd1f3fc8mr6269945ad.51.1760675048710; Thu, 16 Oct 2025 21:24:08 -0700 (PDT) Received: from toolbx.alistair23.me (2403-580b-97e8-0-82ce-f179-8a79-69f4.ip6.aussiebb.net. [2403:580b:97e8:0:82ce:f179:8a79:69f4]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-33be54cad3esm245557a91.12.2025.10.16.21.24.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Oct 2025 21:24:08 -0700 (PDT) From: alistair23@gmail.com X-Google-Original-From: alistair.francis@wdc.com To: chuck.lever@oracle.com, hare@kernel.org, kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-nvme@lists.infradead.org, linux-nfs@vger.kernel.org Cc: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me, kch@nvidia.com, hare@suse.de, alistair23@gmail.com, Alistair Francis Subject: [PATCH v4 6/7] nvme-tcp: Allow userspace to trigger a KeyUpdate with debugfs Date: Fri, 17 Oct 2025 14:23:11 +1000 Message-ID: <20251017042312.1271322-7-alistair.francis@wdc.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251017042312.1271322-1-alistair.francis@wdc.com> References: <20251017042312.1271322-1-alistair.francis@wdc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alistair Francis Allow userspace to trigger a KeyUpdate via debugfs. This patch exposes a key_update file that can be written to with the queue number to trigger a KeyUpdate on that queue. Signed-off-by: Alistair Francis --- v4: - No change v3: - New patch drivers/nvme/host/tcp.c | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 791e0cc91ad8..f5c7b646d002 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -1429,6 +1430,75 @@ static void update_tls_keys(struct nvme_tcp_queue *q= ueue) } } =20 +#ifdef CONFIG_NVME_TCP_TLS +#define NVME_DEBUGFS_RW_ATTR(field) \ + static int field##_open(struct inode *inode, struct file *file) \ + { return single_open(file, field##_show, inode->i_private); } \ + \ + static const struct file_operations field##_fops =3D { \ + .open =3D field##_open, \ + .read =3D seq_read, \ + .write =3D field##_write, \ + .release =3D single_release, \ + } + +static int nvme_ctrl_key_update_show(struct seq_file *m, void *p) +{ + seq_printf(m, "0\n"); + + return 0; +} + +static ssize_t nvme_ctrl_key_update_write(struct file *file, const char __= user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m =3D file->private_data; + struct nvme_ctrl *nctrl =3D m->private; + struct nvme_tcp_ctrl *ctrl =3D to_tcp_ctrl(nctrl); + char kbuf[16] =3D {0}; + int queue_nr, rc; + struct nvme_tcp_queue *queue; + + if (count > sizeof(kbuf) - 1) + return -EINVAL; + if (copy_from_user(kbuf, buf, count)) + return -EFAULT; + kbuf[count] =3D 0; + + rc =3D kstrtouint(kbuf, 10, &queue_nr); + if (rc) + return rc; + + if (queue_nr >=3D nctrl->queue_count) + return -EINVAL; + + queue =3D &ctrl->queues[queue_nr]; + + update_tls_keys(queue); + + return count; +} +NVME_DEBUGFS_RW_ATTR(nvme_ctrl_key_update); +#endif + +static void nvme_tcp_debugfs_init(struct nvme_ctrl *ctrl, + const char *dev_name) +{ + struct dentry *parent; + + /* create debugfs directory and attribute */ + parent =3D debugfs_create_dir(dev_name, NULL); + if (IS_ERR(parent)) { + pr_warn("%s: failed to create debugfs directory\n", dev_name); + return; + } + +#ifdef CONFIG_NVME_TCP_TLS + debugfs_create_file("key_update", S_IWUSR, parent, ctrl, + &nvme_ctrl_key_update_fops); +#endif +} + static void nvme_tcp_io_work(struct work_struct *w) { struct nvme_tcp_queue *queue =3D @@ -3065,6 +3135,8 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct = device *dev, list_add_tail(&ctrl->list, &nvme_tcp_ctrl_list); mutex_unlock(&nvme_tcp_ctrl_mutex); =20 + nvme_tcp_debugfs_init(&ctrl->ctrl, dev_name(dev)); + return &ctrl->ctrl; =20 out_uninit_ctrl: --=20 2.51.0 From nobody Mon Feb 9 11:34:54 2026 Received: from mail-pf1-f171.google.com (mail-pf1-f171.google.com [209.85.210.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE140310764 for ; Fri, 17 Oct 2025 04:24:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675058; cv=none; b=QoP/lJta8iQJjxNDaKp/crbM4+MJf40CdtlH7KOENyR3hivt//N8afCDFC1kGl+ZDhB1u2RbsVe/iEscpcvIxYbRtiR0kF7cbwjCJFDu/MAFgzxIJIbWHpwyqWAvDgAzskvcsVAerGoF8jpuemLPHAG0dzTGdD5EiSM0Oedj6WE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760675058; c=relaxed/simple; bh=mttQhbqh9z6Fex4BCtrcnr1DTRxAJlfyNZNJHALHqyk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P0F2EoUdTgVW/D7DlvAHCgdIPW/nIoFtMJlmYZUJEr4HFxp9Hjg33+bENb/Yob5N10WsbtCQfZ8R9qqCtD21PmUtMtry246fnYjHtkWD4r2VGE7vUw9ZB8kdTxY70/ZWg0Vm1TGbYg9XBHzOXqVEK7qEw3i8VD7NbkOPs8WmVA4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=i7c3nDdT; arc=none smtp.client-ip=209.85.210.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="i7c3nDdT" Received: by mail-pf1-f171.google.com with SMTP id d2e1a72fcca58-782bfd0a977so1200270b3a.3 for ; Thu, 16 Oct 2025 21:24:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760675055; x=1761279855; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=H/JQ/MpeHG5sNknRkM9q2VtRpwwB6bENwljP0w05Adc=; b=i7c3nDdTKDlHHj8Q0yMl5eIchL06dCa/mrMQ1ixYOS18+An9jDZoFY9wLW7KT9Qp0K 1ykwNkcNiELAWAYO21Q61B1HCnCPEDpXPNdyYeJUzpEcAQxcbEOgmixaBWDOQdNa1Jnz mTa17l7NBwQ+1b+5ARm63fUnqwIOCc5wilG16AQaT02W2DT1qqYkAzAhWUQlh1hRt+cV WTcotKBnScmaMb0EKrI2sJ0sOhzJ/Kaiz8pghCybbWFcBZEIKswHNApk8/IfK35zFdbt hs8gcgJmHBGGE0lUN4yuOvq9D/R+ejGQrPVaQ/FupRbxlpS0wb+nK1zOWmzZUflha/qW jI/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760675055; x=1761279855; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=H/JQ/MpeHG5sNknRkM9q2VtRpwwB6bENwljP0w05Adc=; b=fEHdEobXoYgcyWVwb+wKWojabAxWZ3o0CBN7ZaLYj1//27xxz20GzriYzVTAG29A8p FXdgAP/K69Y3uLKmUeBwsGaKAiUbETsduUH+KhW+5zmV2Gvw+QsawOUPnfWvY2q/xe8+ ea1XmKTxZvA14i2UI+80r7OkmliRsr/KYwlb9LKpg8BW6wmt/ulxncpEiiygWOWPQAg7 iYzz+UNefkSiLdejcln6KPT+1i8RMNX1hAiOb8/GvccBm/7DoBBeqipIZ1VZjj7gvzm/ mf260pYfzY5NtfSRcndTzYXTkfLgG01x2XbSuqXoZWx5jux0m3q+SLGY5b8mA74zdZiU zScw== X-Forwarded-Encrypted: i=1; AJvYcCWTUGzB8MH12B+3gJBd4s/xSkgqCfjoKXZf5shk3s/3ePDgJmfu8TljxfrRrFDRm9pMvDf1nMqHA8Jv6O4=@vger.kernel.org X-Gm-Message-State: AOJu0Yw0W+/9uCnZc+oBb6M3dQ8PoZx/YlfEnN0UoqUFaQesrJwKumQJ 3SMS7Nw66gFwgO6Xjtq9sHSQXGNLmuBqqZEH4sSPGwq5OurXbPjjViJ5 X-Gm-Gg: ASbGnct4KtsTqHRK9uQ1G+uOTColRgGGEOIiOSiNYI1zmPcW+3It/vqTxZSLZM/QtXj IONWQiyb2KySmMWPfnjoQBMuLX+rPWAhodKHvPYc8yvCxrhJHeu2ZHXC/sEBgtw5G9v4CPO0KKE VjOkyGxhOsEW6CyOg0zbvbqXqmII/V3lTclR/MrvOt8w1OYi2tOOo4Tql3nMoZJ4mvYnWs6YVjs lXyfxDcqwzLRZfzEPbe0YjRFxVuM+BCWmlrtD7osXTo8j1dxrtUPVraCLHwIjqVrjskO49DIgz5 R3uwP1Gi7gvr4O+10zw/GNCVE0782BU42CJK2aEJ2yDIUhnGDVyE5helSwIu/PGFMXsyQ0pTENb iWZAh7z+vjKWi3jLs79x1KtXrTKpsZep1mwZpSzM9u46TX7z0Z84lIOPXVs6QVDbaUs9AWNyLy2 4vubfkVr1e59l4z9IiBOPEtB3hPPgFWF94xPnDLsPlGcOi6NDVz+MgctDjjMOlEok91pqiYU7UZ W+dZ/cfGvAtYBvAznNw X-Google-Smtp-Source: AGHT+IHyaWxT0M6jcSDOPiAWWc/zLGVBhm66Pbmfou5gKKgW6rFVAYlwZs/wPGPlImKOfJEIkfaYVg== X-Received: by 2002:a17:90b:1d88:b0:32e:a8b7:e9c with SMTP id 98e67ed59e1d1-33bcf90c003mr2038589a91.29.1760675054825; Thu, 16 Oct 2025 21:24:14 -0700 (PDT) Received: from toolbx.alistair23.me (2403-580b-97e8-0-82ce-f179-8a79-69f4.ip6.aussiebb.net. [2403:580b:97e8:0:82ce:f179:8a79:69f4]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-33be54cad3esm245557a91.12.2025.10.16.21.24.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Oct 2025 21:24:14 -0700 (PDT) From: alistair23@gmail.com X-Google-Original-From: alistair.francis@wdc.com To: chuck.lever@oracle.com, hare@kernel.org, kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-nvme@lists.infradead.org, linux-nfs@vger.kernel.org Cc: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me, kch@nvidia.com, hare@suse.de, alistair23@gmail.com, Alistair Francis Subject: [PATCH v4 7/7] nvmet-tcp: Support KeyUpdate Date: Fri, 17 Oct 2025 14:23:12 +1000 Message-ID: <20251017042312.1271322-8-alistair.francis@wdc.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251017042312.1271322-1-alistair.francis@wdc.com> References: <20251017042312.1271322-1-alistair.francis@wdc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alistair Francis If the nvmet_tcp_try_recv() function return EKEYEXPIRED or if we receive a KeyUpdate handshake type then the underlying TLS keys need to be updated. If the NVMe Host (TLS client) initiates a KeyUpdate this patch will allow the NVMe layer to process the KeyUpdate request and forward the request to userspace. Userspace must then update the key to keep the connection alive. This patch allows us to handle the NVMe host sending a KeyUpdate request without aborting the connection. At this time we don't support initiating a KeyUpdate. Link: https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.3 Signed-off-by: Alistair Francis Reviewed-by: Hannes Reinecke --- v4: - Restructure code to avoid #ifdefs and forward declarations - Use a helper function for checking -EKEYEXPIRED - Remove all support for initiating KeyUpdate - Use helper function for restoring callbacks v3: - Use a write lock for sk_user_data - Fix build with CONFIG_NVME_TARGET_TCP_TLS disabled - Remove unused variable v2: - Use a helper function for KeyUpdates - Ensure keep alive timer is stopped - Wait for TLS KeyUpdate to complete drivers/nvme/target/tcp.c | 205 ++++++++++++++++++++++++++------------ 1 file changed, 143 insertions(+), 62 deletions(-) diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 8aeec4a7f136..4ef25df2791a 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -175,6 +175,7 @@ struct nvmet_tcp_queue { =20 /* TLS state */ key_serial_t tls_pskid; + key_serial_t user_session_id; struct delayed_work tls_handshake_tmo_work; =20 unsigned long poll_end; @@ -186,6 +187,8 @@ struct nvmet_tcp_queue { struct sockaddr_storage sockaddr_peer; struct work_struct release_work; =20 + struct completion tls_complete; + int idx; struct list_head queue_list; =20 @@ -214,6 +217,10 @@ static struct workqueue_struct *nvmet_tcp_wq; static const struct nvmet_fabrics_ops nvmet_tcp_ops; static void nvmet_tcp_free_cmd(struct nvmet_tcp_cmd *c); static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd); +#ifdef CONFIG_NVME_TARGET_TCP_TLS +static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue, + handshake_key_update_type keyupdate); +#endif =20 static inline u16 nvmet_tcp_cmd_tag(struct nvmet_tcp_queue *queue, struct nvmet_tcp_cmd *cmd) @@ -832,6 +839,23 @@ static int nvmet_tcp_try_send_one(struct nvmet_tcp_que= ue *queue, return 1; } =20 +#ifdef CONFIG_NVME_TARGET_TCP_TLS +static bool nvmet_tls_key_expired(struct nvmet_tcp_queue *queue, int ret) +{ + if (ret =3D=3D -EKEYEXPIRED && + queue->state !=3D NVMET_TCP_Q_DISCONNECTING && + queue->state !=3D NVMET_TCP_Q_TLS_HANDSHAKE) + return true; + + return false; +} +#else +static bool nvmet_tls_key_expired(struct nvmet_tcp_queue *queue, int ret) +{ + return false; +} +#endif + static int nvmet_tcp_try_send(struct nvmet_tcp_queue *queue, int budget, int *sends) { @@ -1106,6 +1130,103 @@ static inline bool nvmet_tcp_pdu_valid(u8 type) return false; } =20 +static void nvmet_tcp_release_queue(struct kref *kref) +{ + struct nvmet_tcp_queue *queue =3D + container_of(kref, struct nvmet_tcp_queue, kref); + + WARN_ON(queue->state !=3D NVMET_TCP_Q_DISCONNECTING); + queue_work(nvmet_wq, &queue->release_work); +} + +static void nvmet_tcp_schedule_release_queue(struct nvmet_tcp_queue *queue) +{ + spin_lock_bh(&queue->state_lock); + if (queue->state =3D=3D NVMET_TCP_Q_TLS_HANDSHAKE) { + /* Socket closed during handshake */ + tls_handshake_cancel(queue->sock->sk); + } + if (queue->state !=3D NVMET_TCP_Q_DISCONNECTING) { + queue->state =3D NVMET_TCP_Q_DISCONNECTING; + kref_put(&queue->kref, nvmet_tcp_release_queue); + } + spin_unlock_bh(&queue->state_lock); +} + +static void nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue *que= ue) +{ + struct socket *sock =3D queue->sock; + + if (!queue->state_change) + return; + + write_lock_bh(&sock->sk->sk_callback_lock); + sock->sk->sk_data_ready =3D queue->data_ready; + sock->sk->sk_state_change =3D queue->state_change; + sock->sk->sk_write_space =3D queue->write_space; + sock->sk->sk_user_data =3D NULL; + write_unlock_bh(&sock->sk->sk_callback_lock); +} + +#ifdef CONFIG_NVME_TARGET_TCP_TLS +static void nvmet_tcp_tls_handshake_timeout(struct work_struct *w) +{ + struct nvmet_tcp_queue *queue =3D container_of(to_delayed_work(w), + struct nvmet_tcp_queue, tls_handshake_tmo_work); + + pr_warn("queue %d: TLS handshake timeout\n", queue->idx); + /* + * If tls_handshake_cancel() fails we've lost the race with + * nvmet_tcp_tls_handshake_done() */ + if (!tls_handshake_cancel(queue->sock->sk)) + return; + spin_lock_bh(&queue->state_lock); + if (WARN_ON(queue->state !=3D NVMET_TCP_Q_TLS_HANDSHAKE)) { + spin_unlock_bh(&queue->state_lock); + return; + } + queue->state =3D NVMET_TCP_Q_FAILED; + spin_unlock_bh(&queue->state_lock); + nvmet_tcp_schedule_release_queue(queue); + kref_put(&queue->kref, nvmet_tcp_release_queue); +} + +static int update_tls_keys(struct nvmet_tcp_queue *queue) +{ + int ret; + + cancel_work(&queue->io_work); + queue->state =3D NVMET_TCP_Q_TLS_HANDSHAKE; + + nvmet_tcp_restore_socket_callbacks(queue); + + INIT_DELAYED_WORK(&queue->tls_handshake_tmo_work, + nvmet_tcp_tls_handshake_timeout); + + ret =3D nvmet_tcp_tls_handshake(queue, HANDSHAKE_KEY_UPDATE_TYPE_RECEIVED= ); + + if (ret < 0) + return ret; + + ret =3D wait_for_completion_interruptible_timeout(&queue->tls_complete, + 10 * HZ); + + if (ret <=3D 0) { + tls_handshake_cancel(queue->sock->sk); + return ret; + } + + queue->state =3D NVMET_TCP_Q_LIVE; + + return 0; +} +#else +static int update_tls_keys(struct nvmet_tcp_queue *queue) +{ + return -EPFNOSUPPORT; +} +#endif + static int nvmet_tcp_tls_record_ok(struct nvmet_tcp_queue *queue, struct msghdr *msg, char *cbuf) { @@ -1131,6 +1252,9 @@ static int nvmet_tcp_tls_record_ok(struct nvmet_tcp_q= ueue *queue, ret =3D -EAGAIN; } break; + case TLS_RECORD_TYPE_HANDSHAKE: + ret =3D -EAGAIN; + break; default: /* discard this record type */ pr_err("queue %d: TLS record %d unhandled\n", @@ -1340,6 +1464,8 @@ static int nvmet_tcp_try_recv(struct nvmet_tcp_queue = *queue, for (i =3D 0; i < budget; i++) { ret =3D nvmet_tcp_try_recv_one(queue); if (unlikely(ret < 0)) { + if (nvmet_tls_key_expired(queue, ret)) + goto done; nvmet_tcp_socket_error(queue, ret); goto done; } else if (ret =3D=3D 0) { @@ -1351,29 +1477,6 @@ static int nvmet_tcp_try_recv(struct nvmet_tcp_queue= *queue, return ret; } =20 -static void nvmet_tcp_release_queue(struct kref *kref) -{ - struct nvmet_tcp_queue *queue =3D - container_of(kref, struct nvmet_tcp_queue, kref); - - WARN_ON(queue->state !=3D NVMET_TCP_Q_DISCONNECTING); - queue_work(nvmet_wq, &queue->release_work); -} - -static void nvmet_tcp_schedule_release_queue(struct nvmet_tcp_queue *queue) -{ - spin_lock_bh(&queue->state_lock); - if (queue->state =3D=3D NVMET_TCP_Q_TLS_HANDSHAKE) { - /* Socket closed during handshake */ - tls_handshake_cancel(queue->sock->sk); - } - if (queue->state !=3D NVMET_TCP_Q_DISCONNECTING) { - queue->state =3D NVMET_TCP_Q_DISCONNECTING; - kref_put(&queue->kref, nvmet_tcp_release_queue); - } - spin_unlock_bh(&queue->state_lock); -} - static inline void nvmet_tcp_arm_queue_deadline(struct nvmet_tcp_queue *qu= eue) { queue->poll_end =3D jiffies + usecs_to_jiffies(idle_poll_period_usecs); @@ -1404,8 +1507,12 @@ static void nvmet_tcp_io_work(struct work_struct *w) ret =3D nvmet_tcp_try_recv(queue, NVMET_TCP_RECV_BUDGET, &ops); if (ret > 0) pending =3D true; - else if (ret < 0) + else if (ret < 0) { + if (ret =3D=3D -EKEYEXPIRED) + break; + return; + } =20 ret =3D nvmet_tcp_try_send(queue, NVMET_TCP_SEND_BUDGET, &ops); if (ret > 0) @@ -1415,6 +1522,11 @@ static void nvmet_tcp_io_work(struct work_struct *w) =20 } while (pending && ops < NVMET_TCP_IO_WORK_BUDGET); =20 + if (ret =3D=3D -EKEYEXPIRED) { + update_tls_keys(queue); + pending =3D true; + } + /* * Requeue the worker if idle deadline period is in progress or any * ops activity was recorded during the do-while loop above. @@ -1517,21 +1629,6 @@ static void nvmet_tcp_free_cmds(struct nvmet_tcp_que= ue *queue) kfree(cmds); } =20 -static void nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue *que= ue) -{ - struct socket *sock =3D queue->sock; - - if (!queue->state_change) - return; - - write_lock_bh(&sock->sk->sk_callback_lock); - sock->sk->sk_data_ready =3D queue->data_ready; - sock->sk->sk_state_change =3D queue->state_change; - sock->sk->sk_write_space =3D queue->write_space; - sock->sk->sk_user_data =3D NULL; - write_unlock_bh(&sock->sk->sk_callback_lock); -} - static void nvmet_tcp_uninit_data_in_cmds(struct nvmet_tcp_queue *queue) { struct nvmet_tcp_cmd *cmd =3D queue->cmds; @@ -1794,6 +1891,7 @@ static void nvmet_tcp_tls_handshake_done(void *data, = int status, } if (!status) { queue->tls_pskid =3D peerid; + queue->user_session_id =3D user_session_id; queue->state =3D NVMET_TCP_Q_CONNECTING; } else queue->state =3D NVMET_TCP_Q_FAILED; @@ -1809,32 +1907,11 @@ static void nvmet_tcp_tls_handshake_done(void *data= , int status, else nvmet_tcp_set_queue_sock(queue); kref_put(&queue->kref, nvmet_tcp_release_queue); -} - -static void nvmet_tcp_tls_handshake_timeout(struct work_struct *w) -{ - struct nvmet_tcp_queue *queue =3D container_of(to_delayed_work(w), - struct nvmet_tcp_queue, tls_handshake_tmo_work); - - pr_warn("queue %d: TLS handshake timeout\n", queue->idx); - /* - * If tls_handshake_cancel() fails we've lost the race with - * nvmet_tcp_tls_handshake_done() */ - if (!tls_handshake_cancel(queue->sock->sk)) - return; - spin_lock_bh(&queue->state_lock); - if (WARN_ON(queue->state !=3D NVMET_TCP_Q_TLS_HANDSHAKE)) { - spin_unlock_bh(&queue->state_lock); - return; - } - queue->state =3D NVMET_TCP_Q_FAILED; - spin_unlock_bh(&queue->state_lock); - nvmet_tcp_schedule_release_queue(queue); - kref_put(&queue->kref, nvmet_tcp_release_queue); + complete(&queue->tls_complete); } =20 static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue, - handshake_key_update_type keyupdate) + handshake_key_update_type keyupdate) { int ret =3D -EOPNOTSUPP; struct tls_handshake_args args; @@ -1852,11 +1929,15 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp= _queue *queue, args.ta_data =3D queue; args.ta_keyring =3D key_serial(queue->port->nport->keyring); args.ta_timeout_ms =3D tls_handshake_timeout * 1000; + args.user_session_id =3D queue->user_session_id; + + init_completion(&queue->tls_complete); =20 if (keyupdate =3D=3D HANDSHAKE_KEY_UPDATE_TYPE_UNSPEC) ret =3D tls_server_hello_psk(&args, GFP_KERNEL); else ret =3D tls_server_keyupdate_psk(&args, GFP_KERNEL, keyupdate); + if (ret) { kref_put(&queue->kref, nvmet_tcp_release_queue); pr_err("failed to start TLS, err=3D%d\n", ret); --=20 2.51.0