Changeset View
Standalone View
sys/kern/uipc_socket.c
Show First 20 Lines • Show All 1,609 Lines • ▼ Show 20 Lines | |||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
struct ktls_session *tls; | struct ktls_session *tls; | ||||
int tls_enq_cnt, tls_pruflag; | int tls_enq_cnt, tls_pruflag; | ||||
uint8_t tls_rtype; | uint8_t tls_rtype; | ||||
tls = NULL; | tls = NULL; | ||||
tls_rtype = TLS_RLTYPE_APP; | tls_rtype = TLS_RLTYPE_APP; | ||||
#endif | #endif | ||||
if (uio != NULL) | if (uio != NULL) | ||||
jhb: Note that we compute `resid` here even in the case that `uio` is NULL, so it should handle… | |||||
Done Inline ActionsBut resid > 0 implies only that the whole mbuf chain has length > 0, not that each mbuf in the chain has length > 0, and ktls_frame() asserts the latter. So it seems possible in principle for kernel consumers to violate the assertion, but that should be ok. markj: But resid > 0 implies only that the whole mbuf chain has length > 0, not that each mbuf in the… | |||||
resid = uio->uio_resid; | resid = uio->uio_resid; | ||||
else if ((top->m_flags & M_PKTHDR) != 0) | else if ((top->m_flags & M_PKTHDR) != 0) | ||||
resid = top->m_pkthdr.len; | resid = top->m_pkthdr.len; | ||||
else | else | ||||
resid = m_length(top, NULL); | resid = m_length(top, NULL); | ||||
/* | /* | ||||
* In theory resid should be unsigned. However, space must be | * In theory resid should be unsigned. However, space must be | ||||
* signed, as it might be less than 0 if we over-committed, and we | * signed, as it might be less than 0 if we over-committed, and we | ||||
Show All 19 Lines | #endif | ||||
error = SOCK_IO_SEND_LOCK(so, SBLOCKWAIT(flags)); | error = SOCK_IO_SEND_LOCK(so, SBLOCKWAIT(flags)); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
tls_pruflag = 0; | tls_pruflag = 0; | ||||
tls = ktls_hold(so->so_snd.sb_tls_info); | tls = ktls_hold(so->so_snd.sb_tls_info); | ||||
if (tls != NULL) { | if (tls != NULL) { | ||||
Not Done Inline ActionsWe could check here by doing something like: if (resid == 0 && tls->params.cipher_algorithm != CRYPTO_AES_CBC) return (EINVAL); jhb: We could check here by doing something like:
```
if (resid == 0 && tls->params. | |||||
Done Inline ActionsThat's not quite as strict as what I did: sosend takes a UIO or an mbuf chain. If an mbuf chain is passed, ktls_frame() asserts that each mbuf in the chain has length > 0, whereas checking resid > 0 only verifies that the entire chain has length > 0. I guess that's fine though since the system call path always passes a UIO... markj: That's not quite as strict as what I did: sosend takes a UIO or an mbuf chain. If an mbuf chain… | |||||
if (tls->mode == TCP_TLS_MODE_SW) | if (tls->mode == TCP_TLS_MODE_SW) | ||||
tls_pruflag = PRUS_NOTREADY; | tls_pruflag = PRUS_NOTREADY; | ||||
if (control != NULL) { | if (control != NULL) { | ||||
struct cmsghdr *cm = mtod(control, struct cmsghdr *); | struct cmsghdr *cm = mtod(control, struct cmsghdr *); | ||||
if (clen >= sizeof(*cm) && | if (clen >= sizeof(*cm) && | ||||
cm->cmsg_type == TLS_SET_RECORD_TYPE) { | cm->cmsg_type == TLS_SET_RECORD_TYPE) { | ||||
tls_rtype = *((uint8_t *)CMSG_DATA(cm)); | tls_rtype = *((uint8_t *)CMSG_DATA(cm)); | ||||
clen = 0; | clen = 0; | ||||
m_freem(control); | m_freem(control); | ||||
control = NULL; | control = NULL; | ||||
atomic = 1; | atomic = 1; | ||||
} | } | ||||
} | } | ||||
if (resid == 0 && !ktls_permit_empty_frames(tls)) { | |||||
error = EINVAL; | |||||
goto release; | |||||
} | |||||
} | } | ||||
#endif | #endif | ||||
restart: | restart: | ||||
do { | do { | ||||
SOCKBUF_LOCK(&so->so_snd); | SOCKBUF_LOCK(&so->so_snd); | ||||
if (so->so_snd.sb_state & SBS_CANTSENDMORE) { | if (so->so_snd.sb_state & SBS_CANTSENDMORE) { | ||||
SOCKBUF_UNLOCK(&so->so_snd); | SOCKBUF_UNLOCK(&so->so_snd); | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | do { | ||||
do { | do { | ||||
if (uio == NULL) { | if (uio == NULL) { | ||||
resid = 0; | resid = 0; | ||||
if (flags & MSG_EOR) | if (flags & MSG_EOR) | ||||
top->m_flags |= M_EOR; | top->m_flags |= M_EOR; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
if (tls != NULL) { | if (tls != NULL) { | ||||
ktls_frame(top, tls, &tls_enq_cnt, | ktls_frame(top, tls, &tls_enq_cnt, | ||||
tls_rtype); | tls_rtype); | ||||
Not Done Inline ActionsMy only thought is if we'd like to keep the assertions in ktls_frame and instead check for empty writes in this function. The sendfile case should never fail and keeping the assertion in ktls_frame would avoid doing the checks in non-debug kernels for sendfile. jhb: My only thought is if we'd like to keep the assertions in ktls_frame and instead check for… | |||||
Not Done Inline ActionsI think that makes sense. gallatin: I think that makes sense. | |||||
tls_rtype = TLS_RLTYPE_APP; | tls_rtype = TLS_RLTYPE_APP; | ||||
} | } | ||||
#endif | #endif | ||||
} else { | } else { | ||||
/* | /* | ||||
* Copy the data from userland into a mbuf | * Copy the data from userland into a mbuf | ||||
* chain. If resid is 0, which can happen | * chain. If resid is 0, which can happen | ||||
* only if we have control to send, then | * only if we have control to send, then | ||||
▲ Show 20 Lines • Show All 2,777 Lines • Show Last 20 Lines |
Note that we compute resid here even in the case that uio is NULL, so it should handle sosend calls that only pass in an mbuf chain as well.