Date: Fri, 21 May 2021 21:45:31 GMT From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 916c61a5ed37 - main - Fix handling of errors from pru_send(PRUS_NOTREADY) Message-ID: <202105212145.14LLjVq5055475@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=916c61a5ed37da8ecdedd3c5512813d8dcec9a24 commit 916c61a5ed37da8ecdedd3c5512813d8dcec9a24 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2021-05-21 21:44:46 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2021-05-21 21:45:19 +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 MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D30349 --- 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 2a167eb68a22..0ca87bfc522a 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1767,18 +1767,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?202105212145.14LLjVq5055475>