git: fc1a02c93ba4 - stable/14 - ktls: Fix an off-by-one bug in tls13_find_record_type()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 28 Sep 2026 16:20:36 UTC
The branch stable/14 has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=fc1a02c93ba4c9a98e329a4166618bbaf17d584b
commit fc1a02c93ba4c9a98e329a4166618bbaf17d584b
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-09-23 16:53:17 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-09-28 13:57:00 +0000
ktls: Fix an off-by-one bug in tls13_find_record_type()
If the entire plaintext is zero-filled, the backwards walk in
tls13_find_record_type() would return the offset of the last byte of the
TLS header. This causes an underflow when decrypting, resulting in a
null pointer dereference.
Fix the bug and add a regression test.
Reviewed by: gallatin, jhb
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D59767
(cherry picked from commit 7c5e457d3afdc7742ee24f0b5ee6e5e7aa00a6bd)
---
sys/kern/uipc_ktls.c | 4 +--
tests/sys/kern/ktls_test.c | 71 ++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 68 insertions(+), 7 deletions(-)
diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c
index 0273a82dd9fc..2efb1c4cfe0d 100644
--- a/sys/kern/uipc_ktls.c
+++ b/sys/kern/uipc_ktls.c
@@ -2327,14 +2327,14 @@ tls13_find_record_type(struct ktls_session *tls, struct mbuf *m, int tls_len,
m_len--;
if (m_len > 0) {
record_type = cp[m_len - 1];
- last_offset = offset + m_len;
+ last_offset = offset + m_len - 1;
}
}
if (last_offset < tls->params.tls_hlen)
return (EBADMSG);
*record_typep = record_type;
- *trailer_len = tls_len - last_offset + 1;
+ *trailer_len = tls_len - last_offset;
return (0);
}
diff --git a/tests/sys/kern/ktls_test.c b/tests/sys/kern/ktls_test.c
index d3a79aeb1470..7e9334c10144 100644
--- a/tests/sys/kern/ktls_test.c
+++ b/tests/sys/kern/ktls_test.c
@@ -2756,6 +2756,62 @@ ATF_TC_BODY(ktls_receive_##cipher_name##_bad_type, tc) \
auth_alg, minor) \
ATF_TP_ADD_TC(tp, ktls_receive_##cipher_name##_bad_type);
+static void
+test_ktls13_receive_no_content_type(const atf_tc_t *tc, struct tls_enable *en,
+ uint64_t seqno)
+{
+ char *outbuf;
+ size_t outbuf_cap, outbuf_len;
+ ssize_t rv;
+ int sockets[2];
+
+ ATF_REQUIRE_INTEQ(TLS_MINOR_VER_THREE, en->tls_vminor);
+
+ outbuf_cap = tls_header_len(en) + tls_trailer_len(en);
+ outbuf = malloc(outbuf_cap);
+
+ ATF_REQUIRE_MSG(open_sockets(tc, sockets), "failed to create sockets");
+
+ ATF_REQUIRE(setsockopt(sockets[0], IPPROTO_TCP, TCP_RXTLS_ENABLE, en,
+ sizeof(*en)) == 0);
+ check_tls_mode(tc, sockets[0], TCP_RXTLS_MODE);
+
+ fd_set_blocking(sockets[0]);
+ fd_set_blocking(sockets[1]);
+
+ outbuf_len = encrypt_tls_record(tc, en, 0 /* invalid content type */,
+ seqno, NULL, 0, outbuf, outbuf_cap, 0);
+
+ rv = write(sockets[1], outbuf, outbuf_len);
+ ATF_REQUIRE_INTEQ((ssize_t)outbuf_len, rv);
+
+ ktls_receive_tls_error(sockets[0], EBADMSG);
+
+ free(outbuf);
+
+ close_sockets_ignore_errors(sockets);
+}
+
+#define GEN_RECEIVE_NO_CONTENT_TYPE_TEST(cipher_name, cipher_alg, \
+ key_size, auth_alg, minor) \
+ATF_TC_WITHOUT_HEAD(ktls_receive_##cipher_name##_no_content_type); \
+ATF_TC_BODY(ktls_receive_##cipher_name##_no_content_type, tc) \
+{ \
+ struct tls_enable en; \
+ uint64_t seqno; \
+ \
+ ATF_REQUIRE_KTLS_RX(); \
+ seqno = random(); \
+ build_tls_enable(tc, cipher_alg, key_size, auth_alg, minor, \
+ seqno, &en); \
+ test_ktls13_receive_no_content_type(tc, &en, seqno); \
+ free_tls_enable(&en); \
+}
+
+#define ADD_RECEIVE_NO_CONTENT_TYPE_TEST(cipher_name, cipher_alg, \
+ key_size, auth_alg, minor) \
+ ATF_TP_ADD_TC(tp, ktls_receive_##cipher_name##_no_content_type);
+
#define GEN_RECEIVE_TLS13_TESTS(cipher_name, cipher_alg, key_size, \
auth_alg, minor) \
GEN_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
@@ -2763,7 +2819,9 @@ ATF_TC_BODY(ktls_receive_##cipher_name##_bad_type, tc) \
GEN_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
auth_alg, minor, long_padded, 64 * 1024, 15) \
GEN_RECEIVE_BAD_TYPE_TEST(cipher_name, cipher_alg, key_size, \
- auth_alg, minor, 64)
+ auth_alg, minor, 64) \
+ GEN_RECEIVE_NO_CONTENT_TYPE_TEST(cipher_name, cipher_alg, \
+ key_size, auth_alg, minor)
#define ADD_RECEIVE_TLS13_TESTS(cipher_name, cipher_alg, key_size, \
auth_alg, minor) \
@@ -2772,12 +2830,15 @@ ATF_TC_BODY(ktls_receive_##cipher_name##_bad_type, tc) \
ADD_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
auth_alg, minor, long_padded) \
ADD_RECEIVE_BAD_TYPE_TEST(cipher_name, cipher_alg, key_size, \
- auth_alg, minor)
+ auth_alg, minor) \
+ ADD_RECEIVE_NO_CONTENT_TYPE_TEST(cipher_name, cipher_alg, \
+ key_size, auth_alg, minor)
/*
- * For TLS 1.3 cipher suites, run two additional receive tests which
- * use add padding to each record. Also run a test that uses an
- * invalid "outer" record type.
+ * For TLS 1.3 cipher suites, run two additional receive tests: two which add
+ * padding to each record, a test that uses an invalid "outer" record type, and
+ * a test that exercises handling of a payload with an invalid inner content
+ * type.
*/
TLS_13_TESTS(GEN_RECEIVE_TLS13_TESTS);