aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_sendfile.c
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-05-21 21:44:46 +0000
committerMark Johnston <markj@FreeBSD.org>2021-05-21 21:45:19 +0000
commit916c61a5ed37da8ecdedd3c5512813d8dcec9a24 (patch)
treea8f0763aee2168fc0a94f7ae346b7d916c1b35d1 /sys/kern/kern_sendfile.c
parent7d2608a5d24ec3534dad7f24191f12a8181ea206 (diff)
downloadsrc-916c61a5ed37da8ecdedd3c5512813d8dcec9a24.tar.gz
src-916c61a5ed37da8ecdedd3c5512813d8dcec9a24.zip
Fix handling of errors from pru_send(PRUS_NOTREADY)
PRUS_NOTREADY indicates that the caller has not yet populated the chain with data, and so it is not ready for transmission. This is used by sendfile (for async I/O) and KTLS (for encryption). In particular, if pru_send returns an error, the caller is responsible for freeing the chain since other implicit references to the data buffers exist. For async sendfile, it happens that an error will only be returned if the connection was dropped, in which case tcp_usr_ready() will handle freeing the chain. But since KTLS can be used in conjunction with the regular socket I/O system calls, many more error cases - which do not result in the connection being dropped - are reachable. In these cases, KTLS was effectively assuming success. So: - Change sosend_generic() to free the mbuf chain if pru_send(PRUS_NOTREADY) fails. Nothing else owns a reference to the chain at that point. - Similarly, in vn_sendfile() change the !async I/O && KTLS case to free the chain. - If async I/O is still outstanding when pru_send fails in vn_sendfile(), set an error in the sfio structure so that the connection is aborted and the mbuf chain is freed. Reviewed by: gallatin, tuexen Discussed with: jhb MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D30349
Diffstat (limited to 'sys/kern/kern_sendfile.c')
-rw-r--r--sys/kern/kern_sendfile.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
index 520b7c9c62d0..ac1072ca2406 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -1175,8 +1175,12 @@ prepend_header:
if (tls != NULL && tls->mode == TCP_TLS_MODE_SW) {
error = (*so->so_proto->pr_usrreqs->pru_send)
(so, PRUS_NOTREADY, m, NULL, NULL, td);
- soref(so);
- ktls_enqueue(m, so, tls_enq_cnt);
+ if (error != 0) {
+ m_freem(m);
+ } else {
+ soref(so);
+ ktls_enqueue(m, so, tls_enq_cnt);
+ }
} else
#endif
error = (*so->so_proto->pr_usrreqs->pru_send)
@@ -1187,11 +1191,11 @@ prepend_header:
soref(so);
error = (*so->so_proto->pr_usrreqs->pru_send)
(so, PRUS_NOTREADY, m, NULL, NULL, td);
- sendfile_iodone(sfio, NULL, 0, 0);
+ sendfile_iodone(sfio, NULL, 0, error);
}
CURVNET_RESTORE();
- m = NULL; /* pru_send always consumes */
+ m = NULL;
if (error)
goto done;
sbytes += space + hdrlen;