Fix read out of buffer bounds when dealing with BIO_ADDR

This issue was discoevered while I was testing SSL_new_from_listener()
using a newly created unit test. It has turned out the QUIC stack
at few places contain pattern as follows:
	foo(QUIC_WHATEVER *q, BIO_ADDR *a)
	{
	   q->a = *a;
	}

The problem is that derefencning a that way is risky. If the address `a`
comes from BIO_lookup_ex() it may actually be shorter than sizeof(BIO_ADDR).
Using BIO_ADDR_copy() is the right thing to do here.

Fixes #26241

Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26252)

(cherry picked from commit 395a83a617)
This commit is contained in:
Alexandr Nedvedicky 2024-12-23 17:03:32 +01:00 committed by Tomas Mraz
parent 52efaa7909
commit a04a5fe8a1
4 changed files with 22 additions and 13 deletions

View file

@ -104,6 +104,7 @@ void BIO_ADDR_clear(BIO_ADDR *ap)
*/
int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
{
memset(ap, 0, sizeof(BIO_ADDR));
if (sa->sa_family == AF_INET) {
memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in));
return 1;

View file

@ -474,8 +474,7 @@ int ossl_quic_channel_get_peer_addr(QUIC_CHANNEL *ch, BIO_ADDR *peer_addr)
if (!ch->addressed_mode)
return 0;
*peer_addr = ch->cur_peer_addr;
return 1;
return BIO_ADDR_copy(peer_addr, &ch->cur_peer_addr);
}
int ossl_quic_channel_set_peer_addr(QUIC_CHANNEL *ch, const BIO_ADDR *peer_addr)
@ -489,8 +488,12 @@ int ossl_quic_channel_set_peer_addr(QUIC_CHANNEL *ch, const BIO_ADDR *peer_addr)
return 1;
}
ch->cur_peer_addr = *peer_addr;
ch->addressed_mode = 1;
if (!BIO_ADDR_copy(&ch->cur_peer_addr, peer_addr)) {
ch->addressed_mode = 0;
return 0;
}
ch->addressed_mode = 1;
return 1;
}
@ -3344,7 +3347,9 @@ int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer,
return 0;
/* Note our newly learnt peer address and CIDs. */
ch->cur_peer_addr = *peer;
if (!BIO_ADDR_copy(&ch->cur_peer_addr, peer))
return 0;
ch->init_dcid = *peer_dcid;
ch->cur_remote_dcid = *peer_scid;

View file

@ -842,15 +842,19 @@ int ossl_qtx_write_pkt(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt)
if (!was_coalescing) {
/* Set addresses in TXE. */
if (pkt->peer != NULL)
txe->peer = *pkt->peer;
else
if (pkt->peer != NULL) {
if (!BIO_ADDR_copy(&txe->peer, pkt->peer))
return 0;
} else {
BIO_ADDR_clear(&txe->peer);
}
if (pkt->local != NULL)
txe->local = *pkt->local;
else
if (pkt->local != NULL) {
if (!BIO_ADDR_copy(&txe->local, pkt->local))
return 0;
} else {
BIO_ADDR_clear(&txe->local);
}
}
ret = qtx_mutate_write(qtx, pkt, txe, enc_level);

View file

@ -613,8 +613,7 @@ int ossl_quic_tx_packetiser_set_peer(OSSL_QUIC_TX_PACKETISER *txp,
return 1;
}
txp->args.peer = *peer;
return 1;
return BIO_ADDR_copy(&txp->args.peer, peer);
}
void ossl_quic_tx_packetiser_set_ack_tx_cb(OSSL_QUIC_TX_PACKETISER *txp,