[PATCH 6/9] handshake: advertise the session-tag cap to user space
Chuck Lever
cel at kernel.org
Fri Jun 5 10:34:40 PDT 2026
From: Chuck Lever <chuck.lever at oracle.com>
The kernel caps the number of session tags it accepts in a DONE
downcall at HANDSHAKE_MAX_SESSIONTAGS. tlshd has no way to learn
this cap today: a daemon built against newer UAPI headers than
the running kernel silently overruns it, and the kernel truncates
the list with one pr_warn_once per boot. Truncation is
recoverable but the underlying misconfiguration is easy to miss.
Carry the cap on every ACCEPT reply as HANDSHAKE_A_ACCEPT_MAX_TAGS,
a u32 attribute populated by the kernel. User space reads the
value at ACCEPT time and can gate its DONE-side tag list against
it, turning over-cap into a user-space policy choice rather than
a silent kernel-side truncation.
Putting the cap in the ACCEPT reply keeps a single source of
truth and lets the kernel raise it in a later release without
bumping the daemon's UAPI header dependency.
Signed-off-by: Chuck Lever <chuck.lever at oracle.com>
---
Documentation/netlink/specs/handshake.yaml | 4 ++++
Documentation/networking/tls-handshake.rst | 7 +++++++
include/uapi/linux/handshake.h | 1 +
net/handshake/tlshd.c | 5 +++++
4 files changed, 17 insertions(+)
diff --git a/Documentation/netlink/specs/handshake.yaml b/Documentation/netlink/specs/handshake.yaml
index df36ff7da18f..614d31bee656 100644
--- a/Documentation/netlink/specs/handshake.yaml
+++ b/Documentation/netlink/specs/handshake.yaml
@@ -78,6 +78,9 @@ attribute-sets:
-
name: keyring
type: u32
+ -
+ name: max-tags
+ type: u32
-
name: done
attributes:
@@ -123,6 +126,7 @@ operations:
- certificate
- peername
- keyring
+ - max-tags
-
name: done
doc: Handler reports handshake completion
diff --git a/Documentation/networking/tls-handshake.rst b/Documentation/networking/tls-handshake.rst
index 352842a74e6b..ea2e090a1ed8 100644
--- a/Documentation/networking/tls-handshake.rst
+++ b/Documentation/networking/tls-handshake.rst
@@ -273,4 +273,11 @@ empty. The handshake layer always delivers a finalized tagset to
the callback, so consumers may call tagset_is_member() and
tagset_intersection() unconditionally without a separate guard.
+The tagset delivered to the consumer may contain fewer tags than
+the handshake agent assigned. The kernel caps the per-DONE tag
+count at HANDSHAKE_MAX_SESSIONTAGS, and individual tags within
+the cap may be dropped under memory pressure. The cap rides on
+every ACCEPT reply so the agent can size its DONE-side tag list
+to it; see Documentation/netlink/specs/handshake.yaml.
+
See Documentation/core-api/tagset.rst for the complete tagset API.
diff --git a/include/uapi/linux/handshake.h b/include/uapi/linux/handshake.h
index 1ed309e475b4..1445983e7369 100644
--- a/include/uapi/linux/handshake.h
+++ b/include/uapi/linux/handshake.h
@@ -49,6 +49,7 @@ enum {
HANDSHAKE_A_ACCEPT_CERTIFICATE,
HANDSHAKE_A_ACCEPT_PEERNAME,
HANDSHAKE_A_ACCEPT_KEYRING,
+ HANDSHAKE_A_ACCEPT_MAX_TAGS,
__HANDSHAKE_A_ACCEPT_MAX,
HANDSHAKE_A_ACCEPT_MAX = (__HANDSHAKE_A_ACCEPT_MAX - 1)
diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c
index 9bcaeba74f8c..eae4a4a0a9ef 100644
--- a/net/handshake/tlshd.c
+++ b/net/handshake/tlshd.c
@@ -238,6 +238,11 @@ static int tls_handshake_accept(struct handshake_req *req,
goto out_cancel;
}
+ ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MAX_TAGS,
+ HANDSHAKE_MAX_SESSIONTAGS);
+ if (ret < 0)
+ goto out_cancel;
+
ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_AUTH_MODE,
treq->th_auth_mode);
if (ret < 0)
--
2.54.0
More information about the Linux-nvme
mailing list