mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
opencrypto: Handle end-of-cursor conditions in crypto_cursor_segment()
Some consumers, e.g., swcr_encdec(), may call crypto_cursor_segment() after having advanced the cursor to the end of the buffer. In this case I believe the right behaviour is to return NULL and a length of 0. When this occurs with a CRYPTO_BUF_VMPAGE buffer, the cc_vmpage pointer will point past the end of the page pointer array, so crypto_cursor_segment() ends up dereferencing a random pointer before the function returns a length of 0. The uio-backed cursor has a similar problem. Address this by keeping track of the residual buffer length and returning immediately once the length is zero. PR: 271766 Reported by: Andrew "RhodiumToad" Gierth <andrew@tao11.riddles.org.uk> Reviewed by: jhb MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D40428
This commit is contained in:
parent
e74dd9577f
commit
718d4a1d56
1 changed files with 27 additions and 7 deletions
|
|
@ -321,6 +321,7 @@ crypto_cursor_init(struct crypto_buffer_cursor *cc,
|
|||
break;
|
||||
case CRYPTO_BUF_UIO:
|
||||
cc->cc_iov = cb->cb_uio->uio_iov;
|
||||
cc->cc_buf_len = cb->cb_uio->uio_resid;
|
||||
break;
|
||||
default:
|
||||
#ifdef INVARIANTS
|
||||
|
|
@ -386,6 +387,7 @@ crypto_cursor_advance(struct crypto_buffer_cursor *cc, size_t amount)
|
|||
cc->cc_offset += amount;
|
||||
break;
|
||||
}
|
||||
cc->cc_buf_len -= remain;
|
||||
amount -= remain;
|
||||
cc->cc_iov++;
|
||||
cc->cc_offset = 0;
|
||||
|
|
@ -406,14 +408,34 @@ crypto_cursor_segment(struct crypto_buffer_cursor *cc, size_t *len)
|
|||
{
|
||||
switch (cc->cc_type) {
|
||||
case CRYPTO_BUF_CONTIG:
|
||||
*len = cc->cc_buf_len;
|
||||
return (cc->cc_buf);
|
||||
case CRYPTO_BUF_UIO:
|
||||
case CRYPTO_BUF_VMPAGE:
|
||||
if (cc->cc_buf_len == 0) {
|
||||
*len = 0;
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
case CRYPTO_BUF_MBUF:
|
||||
case CRYPTO_BUF_SINGLE_MBUF:
|
||||
if (cc->cc_mbuf == NULL) {
|
||||
*len = 0;
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
#ifdef INVARIANTS
|
||||
panic("%s: invalid buffer type %d", __func__, cc->cc_type);
|
||||
#endif
|
||||
*len = 0;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
switch (cc->cc_type) {
|
||||
case CRYPTO_BUF_CONTIG:
|
||||
*len = cc->cc_buf_len;
|
||||
return (cc->cc_buf);
|
||||
case CRYPTO_BUF_MBUF:
|
||||
case CRYPTO_BUF_SINGLE_MBUF:
|
||||
if (cc->cc_mbuf->m_flags & M_EXTPG)
|
||||
return (m_epg_segment(cc->cc_mbuf, cc->cc_offset, len));
|
||||
*len = cc->cc_mbuf->m_len - cc->cc_offset;
|
||||
|
|
@ -426,11 +448,7 @@ crypto_cursor_segment(struct crypto_buffer_cursor *cc, size_t *len)
|
|||
*len = cc->cc_iov->iov_len - cc->cc_offset;
|
||||
return ((char *)cc->cc_iov->iov_base + cc->cc_offset);
|
||||
default:
|
||||
#ifdef INVARIANTS
|
||||
panic("%s: invalid buffer type %d", __func__, cc->cc_type);
|
||||
#endif
|
||||
*len = 0;
|
||||
return (NULL);
|
||||
__assert_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -504,6 +522,7 @@ crypto_cursor_copyback(struct crypto_buffer_cursor *cc, int size,
|
|||
todo = MIN(remain, size);
|
||||
memcpy(dst, src, todo);
|
||||
src += todo;
|
||||
cc->cc_buf_len -= todo;
|
||||
if (todo < remain) {
|
||||
cc->cc_offset += todo;
|
||||
break;
|
||||
|
|
@ -593,6 +612,7 @@ crypto_cursor_copydata(struct crypto_buffer_cursor *cc, int size, void *vdst)
|
|||
todo = MIN(remain, size);
|
||||
memcpy(dst, src, todo);
|
||||
dst += todo;
|
||||
cc->cc_buf_len -= todo;
|
||||
if (todo < remain) {
|
||||
cc->cc_offset += todo;
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue