Date: Fri, 4 Jun 2021 01:09:33 GMT From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 75683ed20b70 - stable/13 - Fix handling of errors from pru_send(PRUS_NOTREADY) Message-ID: <202106040109.15419XwY047792@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=75683ed20b70da2b813e5a9da220cfee94c0b307 commit 75683ed20b70da2b813e5a9da220cfee94c0b307 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2021-05-21 21:44:46 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2021-06-04 01:02:02 +0000 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 Sponsored by: The FreeBSD Foundation (cherry picked from commit 916c61a5ed37da8ecdedd3c5512813d8dcec9a24) --- sys/kern/kern_sendfile.c | 12 ++++++++---- sys/kern/uipc_socket.c | 19 +++++++------------ 2 files changed, 15 insertions(+), 16 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; diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 77ce876fd20f..852132e45e58 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1763,18 +1763,13 @@ restart: #ifdef KERN_TLS if (tls != NULL && tls->mode == TCP_TLS_MODE_SW) { - /* - * Note that error is intentionally - * ignored. - * - * Like sendfile(), we rely on the - * completion routine (pru_ready()) - * to free the mbufs in the event that - * pru_send() encountered an error and - * did not append them to the sockbuf. - */ - soref(so); - ktls_enqueue(top, so, tls_enq_cnt); + if (error != 0) { + m_freem(top); + top = NULL; + } else { + soref(so); + ktls_enqueue(top, so, tls_enq_cnt); + } } #endif clen = 0;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202106040109.15419XwY047792>