mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
In TLS DNS, it was possible for an 'isc__nm_uvreq_t' object to be used twice when it was not implied, leading to use after free errors, leading to abort()'s and/or crashes. In particular, in the older version of the code, the following was happening: * 'tlsdns_send_direct()' is eventually called from 'isc__nm_async_tlsdnssend()' when sending data; * 'tlsdns_send_direct()' could fail. If it happens early closer to the beginning of the function, then the 'isc__nm_uvreq_t' object is passed to 'isc__nm_failed_send_cb()' and eventually gets destroyed normally without any negative consequences; * However, if 'tlsdns_send_direct()' fails due to the call to 'tls_cycle()', then the send request object is re-queued to be processed asynchronously later by a call to 'tlsdns_send_enqueue()'. * The error processing code in 'tlsdns_send_direct()' is written without an assumption that the send request object could be re-queued in 'tlsdns_send_direct()' and, thus, it was passed to 'isc__nm_failed_send_cb()' for asynchronous error processing. * As a result of asynchronous processing initiated by `tlsdns_send_enqueue()` the 'isc__nm_uvreq_t' send request object gets properly destroyed eventually. * Then, as a result of asynchronous error processing initiated by the 'isc__nm_failed_send_cb()' call, the send request object is used a second time. However, it was destroyed at the previous step. So we have a (relatively) obvious logical mistake here. Why 'tls_cycle()' was failing is of no particular importance, as I can see many ways for it to fail both on TLS and networking levels. In particular, during testing with 'dnsperf', I have encountered the following two cases: 1. 'result == ISC_R_TLSERROR' - the remote side was wrapping up, causing errors on TLS level (e.g. handshake has not been completed yet); 2. 'result == ISC_R_CONNECTIONRESET' - the remote side closed the connection after we have initiated the asynchronous send request operation and reached the point when its processing started. One could ask: why haven't we encountered the error before? That happened because 'send()' is, in general, a faster operation than 'read()' so we were lucky enough not to encounter this, as it took dnsperf to make our code fail in a particular way to trigger the problematic code path. It requires closing the connection shortly after we have made an asynchronous 'send()' attempt and passed the data for processing by the libuv code (or, to be precise, down our technologies stack). |
||
|---|---|---|
| .. | ||
| bind9 | ||
| dns | ||
| irs | ||
| isc | ||
| isccc | ||
| isccfg | ||
| ns | ||
| .gitignore | ||
| Makefile.am | ||