git: 7b8ddbd4a07d - stable/15 - sendfile: Fix bug when using headers with SW KTLS offload
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 30 Oct 2026 17:40:27 UTC
The branch stable/15 has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=7b8ddbd4a07de27c12319aad36750f4946ff12be
commit 7b8ddbd4a07de27c12319aad36750f4946ff12be
Author: Andrew Gallatin <gallatin@FreeBSD.org>
AuthorDate: 2026-05-22 17:57:54 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-10-30 17:39:48 +0000
sendfile: Fix bug when using headers with SW KTLS offload
When using SW KTLS, we must account for the headers in sf_iodone()
in terms of either freeing or enqueuing them for TLS work.
Not doing so can lead to a situation where we enqueue only
the payload, and not the header, for encryption. Rather than
leaking the header, the socket is left "hung" with the header marked
M_NOTREADY.
Sponsored by: Netflix
Reviewed by: glebius, kib
Differential Revision: https://reviews.freebsd.org/D57134
(cherry picked from commit fd9af1e7084c550358d9598407f9ee7583e6a53f)
---
sys/kern/kern_sendfile.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
index a64024cdafe3..c14f784f26cd 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -96,6 +96,8 @@ struct sf_io {
vm_pindex_t pindex0;
#ifdef KERN_TLS
struct ktls_session *tls;
+ struct mbuf *tls_m;
+ int tls_enq_cnt;
#endif
vm_page_t pa[];
};
@@ -386,7 +388,12 @@ sendfile_iodone(void *arg, vm_page_t *pa, int count, int error)
so->so_proto->pr_abort(so);
so->so_error = EIO;
- mb_free_notready(sfio->m, sfio->npages);
+#ifdef KERN_TLS
+ if (sfio->tls_m != NULL)
+ mb_free_notready(sfio->tls_m, sfio->tls_enq_cnt);
+ else
+#endif
+ mb_free_notready(sfio->m, sfio->npages);
#ifdef KERN_TLS
} else if (sfio->tls != NULL && sfio->tls->mode == TCP_TLS_MODE_SW) {
/*
@@ -398,7 +405,10 @@ sendfile_iodone(void *arg, vm_page_t *pa, int count, int error)
* Donate the socket reference from sfio to rather
* than explicitly invoking soref().
*/
- ktls_enqueue(sfio->m, so, sfio->npages);
+ if (sfio->tls_m != NULL)
+ ktls_enqueue(sfio->tls_m, so, sfio->tls_enq_cnt);
+ else
+ ktls_enqueue(sfio->m, so, sfio->npages);
goto out_with_ref;
#endif
} else
@@ -958,6 +968,8 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
* for all of sfio's lifetime.
*/
sfio->tls = tls;
+ sfio->tls_m = NULL;
+ sfio->tls_enq_cnt = 0;
#endif
vm_object_pip_add(obj, 1);
error = sendfile_swapin(obj, sfio, &nios, off, space, rhpages,
@@ -1201,6 +1213,13 @@ prepend_header:
} else {
sfio->so = so;
sfio->m = m0;
+#ifdef KERN_TLS
+ if (hdrlen != 0 && tls != NULL &&
+ tls->mode == TCP_TLS_MODE_SW) {
+ sfio->tls_m = m;
+ sfio->tls_enq_cnt = tls_enq_cnt;
+ }
+#endif
soref(so);
error = pr->pr_send(so, PRUS_NOTREADY, m, NULL, NULL,
td);