[PATCH 6/9] handshake: advertise the session-tag cap to user space

Chuck Lever <[email protected]>
Newsgroups gmane.linux.nfs,gmane.linux.network
Message-ID <[email protected]>
From: Chuck Lever <[email protected]>

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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.