From 102829aa92d42411eafde5d8d04eddc4b151706c Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Wed, 19 Aug 2020 23:42:33 +0000 Subject: [PATCH] Add the MSG_TLSAPPDATA flag to indicate "return ENXIO" for non-application TLS data records. The kernel RPC cannot process non-application data records when using TLS. It must to an upcall to a userspace daemon that will call SSL_read() to process them. This patch adds a new flag called MSG_TLSAPPDATA that the kernel RPC can use to tell sorecieve() to return ENXIO instead of a non-application data record, when that is what is at the top of the receive queue. I put the code in #ifdef KERN_TLS/#endif, although it will build without that, so that it is recognized as only useful when KERN_TLS is enabled. The alternative to doing this is to have the kernel RPC re-queue the non-application data message after receiving it, but that seems more complicated and might introduce message ordering issues when there are multiple non-application data records one after another. I do not know what, if any, changes will be required to support TLS1.3. Reviewed by: glebius Differential Revision: https://reviews.freebsd.org/D25923 --- sys/kern/uipc_socket.c | 26 ++++++++++++++++++++++++++ sys/sys/socket.h | 1 + 2 files changed, 27 insertions(+) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index ac138679c850..359546b19f65 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -2056,6 +2056,32 @@ soreceive_generic(struct socket *so, struct sockaddr **psa, struct uio *uio, if (m != NULL && m->m_type == MT_CONTROL) { struct mbuf *cm = NULL, *cmn; struct mbuf **cme = &cm; +#ifdef KERN_TLS + struct cmsghdr *cmsg; + struct tls_get_record tgr; + + /* + * For MSG_TLSAPPDATA, check for a non-application data + * record. If found, return ENXIO without removing + * it from the receive queue. This allows a subsequent + * call without MSG_TLSAPPDATA to receive it. + * Note that, for TLS, there should only be a single + * control mbuf with the TLS_GET_RECORD message in it. + */ + if (flags & MSG_TLSAPPDATA) { + cmsg = mtod(m, struct cmsghdr *); + if (cmsg->cmsg_type == TLS_GET_RECORD && + cmsg->cmsg_len == CMSG_LEN(sizeof(tgr))) { + memcpy(&tgr, CMSG_DATA(cmsg), sizeof(tgr)); + /* This will need to change for TLS 1.3. */ + if (tgr.tls_type != TLS_RLTYPE_APP) { + SOCKBUF_UNLOCK(&so->so_rcv); + error = ENXIO; + goto release; + } + } + } +#endif do { if (flags & MSG_PEEK) { diff --git a/sys/sys/socket.h b/sys/sys/socket.h index d6158acb5a32..82ec6b0cf920 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -468,6 +468,7 @@ struct msghdr { #endif #ifdef _KERNEL #define MSG_MORETOCOME 0x00100000 /* additional data pending */ +#define MSG_TLSAPPDATA 0x00200000 /* only soreceive() app. data (TLS) */ #endif /*