mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-08 23:42:06 -04:00
Preserve the request buffer across async SIG(0) processing
For SIG(0)-signed requests, view matching is offloaded and the request is finished asynchronously from ns_client_request_continue(), which passes client->inner.buffer to dns_dt_send(). That buffer aliases the network manager's receive buffer, only valid during the read callback, so it may already be freed and reused, producing garbage dnstap frames (e.g. the "upforwd" sig0-over-DoT test fails with UQ=0). When the request is offloaded (ns_client_setup_view() returns DNS_R_WAIT) and dnstap is enabled, copy the request buffer and point client->inner.buffer at the copy so it survives the asynchronous hop; free it in ns__client_reset_cb(). When dnstap is disabled there is no async consumer of the buffer, so detach it from the receive buffer instead. Assisted-by: Claude:claude-opus-4-8
This commit is contained in:
parent
c8e9823121
commit
ddfe8a1bdc
2 changed files with 44 additions and 9 deletions
|
|
@ -1722,6 +1722,16 @@ ns__client_reset_cb(void *client0) {
|
|||
client_put_tcp_buffer(client);
|
||||
}
|
||||
|
||||
if (client->inner.reqbuf != NULL) {
|
||||
isc_mem_put(client->manager->mctx, client->inner.reqbuf,
|
||||
client->inner.reqbuf_size);
|
||||
client->inner.reqbuf_size = 0;
|
||||
}
|
||||
|
||||
if (client->inner.buffer != NULL) {
|
||||
isc_buffer_initnull(client->inner.buffer);
|
||||
}
|
||||
|
||||
if (client->inner.keytag != NULL) {
|
||||
isc_mem_put(client->manager->mctx, client->inner.keytag,
|
||||
client->inner.keytag_len);
|
||||
|
|
@ -2162,6 +2172,29 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
|
||||
result = ns_client_setup_view(client, &netaddr);
|
||||
if (result == DNS_R_WAIT) {
|
||||
#ifdef HAVE_DNSTAP
|
||||
/*
|
||||
* The request is finished asynchronously, but the receive
|
||||
* buffer is only valid during this callback; copy it so it
|
||||
* survives the asynchronous hop for dnstap logging.
|
||||
*/
|
||||
isc_region_t r;
|
||||
INSIST(client->inner.reqbuf == NULL);
|
||||
isc_buffer_usedregion(client->inner.buffer, &r);
|
||||
if (r.length != 0) {
|
||||
client->inner.reqbuf =
|
||||
isc_mem_get(client->manager->mctx, r.length);
|
||||
client->inner.reqbuf_size = r.length;
|
||||
memmove(client->inner.reqbuf, r.base, r.length);
|
||||
isc_buffer_init(&client->inner.tbuffer,
|
||||
client->inner.reqbuf, r.length);
|
||||
isc_buffer_add(&client->inner.tbuffer, r.length);
|
||||
client->inner.buffer = &client->inner.tbuffer;
|
||||
}
|
||||
#else
|
||||
isc_buffer_initnull(client->inner.buffer);
|
||||
#endif /* #ifdef HAVE_DNSTAP */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -184,15 +184,17 @@ struct ns_client {
|
|||
int16_t ednsversion; /* -1 noedns */
|
||||
uint16_t additionaldepth;
|
||||
void (*cleanup)(ns_client_t *);
|
||||
isc_time_t requesttime;
|
||||
isc_stdtime_t now;
|
||||
isc_time_t tnow;
|
||||
dns_name_t signername; /*%< [T]SIG key name */
|
||||
dns_name_t *signer; /*%< NULL if not valid sig */
|
||||
isc_result_t sigresult;
|
||||
isc_result_t viewmatchresult;
|
||||
isc_buffer_t *buffer;
|
||||
isc_buffer_t tbuffer;
|
||||
isc_time_t requesttime;
|
||||
isc_stdtime_t now;
|
||||
isc_time_t tnow;
|
||||
dns_name_t signername; /*%< [T]SIG key name */
|
||||
dns_name_t *signer; /*%< NULL if not valid sig */
|
||||
isc_result_t sigresult;
|
||||
isc_result_t viewmatchresult;
|
||||
isc_buffer_t *buffer;
|
||||
isc_buffer_t tbuffer;
|
||||
unsigned char *reqbuf; /*%< request copy for async path */
|
||||
size_t reqbuf_size;
|
||||
|
||||
dns_name_t rad; /* Zone rad domain */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue