From: Jakub Kicinski <kuba@kernel.org>
To: rjethwani@purestorage.com
Cc: Jakub Kicinski <kuba@kernel.org>,
netdev@vger.kernel.org, saeedm@nvidia.com, tariqt@nvidia.com,
mbloch@nvidia.com, borisp@nvidia.com, john.fastabend@gmail.com,
sd@queasysnail.net, davem@davemloft.net, pabeni@redhat.com,
edumazet@google.com, leon@kernel.org,
andrew.gospodarek@broadcom.com
Subject: Re: [PATCH v16 04/10] tls: add TLS 1.3 hardware offload support
Date: Mon, 17 Aug 2026 15:11:28 -0700 [thread overview]
Message-ID: <20260817221128.3666336-1-kuba@kernel.org> (raw)
In-Reply-To: <20260807183853.2288959-5-rjethwani@purestorage.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
tls: add TLS 1.3 hardware offload support
This drops the TLS_1_2_VERSION gates in tls_set_device_offload() and
tls_set_device_offload_rx(), teaches tls_device_record_close() to append
the TLS 1.3 content_type byte along with the tag, and switches the
device fallback encryption path to prot->prepend_size / prot->aad_size
so the 1.3 layouts work. tls_device_init() also pre-populates
dummy_page with an identity byte map.
A few questions below.
> diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
> index 37bb06a8e8f5..bbb1aa733500 100644
> --- a/net/tls/tls_device.c
> +++ b/net/tls/tls_device.c
> @@ -317,25 +317,34 @@ static void tls_device_record_close(struct sock *sk,
> unsigned char record_type)
> {
> struct tls_prot_info *prot = &ctx->prot_info;
> - struct page_frag dummy_tag_frag;
> -
> - /* append tag
> - * device will fill in the tag, we just need to append a placeholder
> - * use socket memory to improve coalescing (re-using a single buffer
> - * increases frag count)
> - * if we can't allocate memory now use the dummy page
> + int tail = prot->tag_size + prot->tail_size;
> +
> + /* Append tail: tag for TLS 1.2, content_type + tag for TLS 1.3.
> + * Device fills in the tag, we just need to append a placeholder.
> + * Use socket memory to improve coalescing (re-using a single buffer
> + * increases frag count); if allocation fails use dummy_page
> + * (offset = record_type gives correct content_type byte via
> + * identity mapping)
> */
> - if (unlikely(pfrag->size - pfrag->offset < prot->tag_size) &&
> - !skb_page_frag_refill(prot->tag_size, pfrag, sk->sk_allocation)) {
> - dummy_tag_frag.page = dummy_page;
> - dummy_tag_frag.offset = 0;
> - pfrag = &dummy_tag_frag;
> + if (unlikely(pfrag->size - pfrag->offset < tail) &&
> + !skb_page_frag_refill(tail, pfrag, sk->sk_allocation)) {
> + struct page_frag dummy_pfrag = {
> + .page = dummy_page,
> + .offset = record_type,
> + };
> + tls_append_frag(record, &dummy_pfrag, tail);
[Severity: Medium]
Here record_type is used directly as an offset into the shared global
dummy_page, and tail = prot->tag_size + prot->tail_size bytes are appended
starting from that offset. tls_device_init() only writes the first 256
bytes of the page, and the page comes from a plain alloc_page(GFP_KERNEL),
so the rest is not zeroed.
With AES-GCM (tag_size 16) and TLS 1.3 (tail_size 1), a record_type of 240
or above makes the appended frag cover dummy_page bytes
[256, record_type + 17), which are never initialized.
record_type is taken verbatim from the user cmsg; tls_process_cmsg() in
tls_main.c checks only cmsg_len and MSG_MORE:
case TLS_SET_RECORD_TYPE:
if (cmsg->cmsg_len < CMSG_LEN(sizeof(*record_type)))
return -EINVAL;
if (msg->msg_flags & MSG_MORE)
return -EINVAL;
...
*record_type = *(unsigned char *)CMSG_DATA(cmsg);
so all 256 offsets are reachable from an unprivileged process. Can this
put uninitialized page contents into the tag placeholder area of the
record? Would zeroing the page (__GFP_ZERO), initializing
256 + max tag bytes, or bounding the offset be preferable?
Related to this, the comment added in tls_device_init() says "By populating
all 256 values, we avoid needing to validate record_type at runtime", but
the identity map only covers the content_type byte, not the tag portion of
the tail that follows it.
> + } else {
> + if (prot->tail_size) {
> + char *content_type_addr = page_address(pfrag->page) +
> + pfrag->offset;
> + *content_type_addr = record_type;
> + }
> + tls_append_frag(record, pfrag, tail);
> }
> - tls_append_frag(record, pfrag, prot->tag_size);
[Severity: High]
This isn't a bug introduced by this patch, but the else branch now
dereferences pfrag->page one step earlier than before, and pfrag->page is
never checked for NULL.
Consider the state skb_page_frag_refill() leaves behind on failure in
net/core/sock.c:
pfrag->offset = 0;
...
pfrag->page = alloc_page(gfp);
if (likely(pfrag->page)) {
pfrag->size = PAGE_SIZE;
return true;
}
return false;
offset is zeroed and page is NULL, but size keeps its previous non-zero
value, so pfrag->size - pfrag->offset is at least PAGE_SIZE and the
"< tail" guard here is false. The dummy_page fallback is skipped and the
else branch runs.
Can tls_device_record_close() then be reached with that pfrag? In
tls_push_data(), with an already-open record (record->len >
prot->prepend_size, e.g. after a previous MSG_MORE sendmsg),
tls_do_allocation() takes the sk_page_frag_refill(sk, pfrag) path; on
allocation failure it returns -ENOMEM, sk_stream_wait_memory() returns
non-zero (immediately -EAGAIN for MSG_DONTWAIT), and control does:
} else if (record->len > prot->prepend_size) {
goto last_record;
}
which sets done = true and calls tls_device_record_close(sk, tls_ctx,
record, pfrag, record_type).
For TLS 1.3 (prot->tail_size == 1) that computes page_address(NULL) + 0 and
stores record_type through it, then tls_append_frag() does get_page(NULL).
The pre-patch code took the same false branch and crashed in
tls_append_frag(), so the NULL deref itself is older, but should this test
pfrag->page (or reset pfrag->size on refill failure) so the dummy_page
fallback that exists for exactly this situation is actually used?
>
> /* fill prepend */
> tls_fill_prepend(ctx, skb_frag_address(&record->frags[0]),
> - record->len - prot->overhead_size,
> + record->len - prot->overhead_size + prot->tail_size,
> record_type);
> }
>
[ ... ]
> @@ -1091,11 +1100,6 @@ int tls_set_device_offload(struct sock *sk)
> }
>
> crypto_info = &ctx->crypto_send.info;
> - if (crypto_info->version != TLS_1_2_VERSION) {
> - rc = -EOPNOTSUPP;
> - goto release_netdev;
> - }
> -
> cipher_desc = get_cipher_desc(crypto_info->cipher_type);
> if (!cipher_desc || !cipher_desc->offloadable) {
> rc = -EINVAL;
[Severity: Low]
Should Documentation/networking/tls-offload.rst be updated along with this?
Its Rekey section still says:
Offload does not currently support TLS 1.3, therefore key rotation
is not a concern for offloaded connections at this point.
Removing the version gates here and in tls_set_device_offload_rx() makes
the first half untrue, and the later patches in the series ("tls: device:
add TX KeyUpdate support", "tls: device: add RX KeyUpdate support") make
the second half untrue. No patch in the series touches that file, so the
sentence is still there at the end of the series.
>
> @@ -1410,12 +1411,22 @@ static struct notifier_block tls_dev_notifier = {
>
> int __init tls_device_init(void)
> {
> - int err;
> + unsigned char *page_addr;
> + int err, i;
>
> dummy_page = alloc_page(GFP_KERNEL);
> if (!dummy_page)
> return -ENOMEM;
>
> + /* Pre-populate dummy_page with identity mapping for all byte values.
> + * This is used as fallback for TLS 1.3 content type when memory
> + * allocation fails. By populating all 256 values, we avoid needing
> + * to validate record_type at runtime.
> + */
> + page_addr = page_address(dummy_page);
> + for (i = 0; i < 256; i++)
> + page_addr[i] = (unsigned char)i;
> +
> destruct_wq = alloc_workqueue("ktls_device_destruct", WQ_PERCPU, 0);
> if (!destruct_wq) {
> err = -ENOMEM;
--
pw-bot: cr
next prev parent reply other threads:[~2026-08-17 22:11 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-07 18:38 [PATCH net-next v16 00/10] tls: Add TLS 1.3 hardware offload support Rishikesh Jethwani
2026-08-07 18:38 ` [PATCH v16 01/10] net: tls: reject TLS 1.3 offload in chcr_ktls and nfp drivers Rishikesh Jethwani
2026-08-07 18:38 ` [PATCH v16 02/10] net/mlx5e: add TLS 1.3 hardware offload support Rishikesh Jethwani
2026-08-07 18:38 ` [PATCH v16 03/10] tls: reject rekey attempts on an existing HW-offloaded connection Rishikesh Jethwani
2026-08-07 18:38 ` [PATCH v16 04/10] tls: add TLS 1.3 hardware offload support Rishikesh Jethwani
2026-08-17 22:11 ` Jakub Kicinski [this message]
2026-08-07 18:38 ` [PATCH v16 05/10] tls: split tls_set_sw_offload into init and finalize stages Rishikesh Jethwani
2026-08-17 22:11 ` Jakub Kicinski
2026-08-07 18:38 ` [PATCH v16 06/10] tls: prep helpers and refactors for HW offload KeyUpdate Rishikesh Jethwani
2026-08-17 22:11 ` Jakub Kicinski
2026-08-07 18:38 ` [PATCH v16 07/10] tls: device: add TX KeyUpdate support Rishikesh Jethwani
2026-08-17 22:11 ` Jakub Kicinski
2026-08-07 18:38 ` [PATCH v16 08/10] tls: device: add RX " Rishikesh Jethwani
2026-08-17 22:11 ` Jakub Kicinski
2026-08-07 18:38 ` [PATCH v16 09/10] tls: device: add tracepoints for the KeyUpdate path Rishikesh Jethwani
2026-08-17 22:11 ` Jakub Kicinski
2026-08-07 18:38 ` [PATCH v16 10/10] selftests: net: add TLS hardware offload test Rishikesh Jethwani
2026-08-17 22:10 ` Jakub Kicinski
2026-08-17 22:11 ` Jakub Kicinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260817221128.3666336-1-kuba@kernel.org \
--to=kuba@kernel.org \
--cc=andrew.gospodarek@broadcom.com \
--cc=borisp@nvidia.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=john.fastabend@gmail.com \
--cc=leon@kernel.org \
--cc=mbloch@nvidia.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rjethwani@purestorage.com \
--cc=saeedm@nvidia.com \
--cc=sd@queasysnail.net \
--cc=tariqt@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox