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 /*