mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-03 13:38:32 +00:00
Terminate TCP child processes that arise from UDP truncated replies.
These can't be held forever by a client that opens a connection and then sends nothing, but we can still be DoSsed by a server which accepts a connection and never replies. If the TCP process times out, it sends that information to the parent so that the UDP query can be unblocked. As the TCP timeout is 150s it's highly unlikely that any client will still be waiting, but the point is to free resources.
This commit is contained in:
4 files changed
+63
-13
No files matched your search
+16
-9
@@ -855,7 +855,7 @@ void cache_end_insert(void)
|
||||
#ifdef HAVE_DNSSEC
|
||||
void cache_update_hwm(void)
|
||||
{
|
||||
/* Sneak out possibly updated crypto HWM values. */
|
||||
/* Sneak out possibly updated crypto HWM values. */
|
||||
unsigned char op = PIPE_OP_STATS;
|
||||
|
||||
read_write(daemon->pipe_to_parent, &op, sizeof(op), RW_WRITE);
|
||||
@@ -1000,6 +1000,7 @@ int cache_recv_insert(time_t now, int fd)
|
||||
}
|
||||
|
||||
case PIPE_OP_RESULT:
|
||||
case PIPE_OP_KILLED:
|
||||
{
|
||||
/* UDP validation moved to TCP to avoid truncation.
|
||||
Restart UDP validation process with the returned result. */
|
||||
@@ -1013,11 +1014,14 @@ int cache_recv_insert(time_t now, int fd)
|
||||
!read_write(fd, (unsigned char *)&ret_len, sizeof(ret_len), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)daemon->packet, ret_len, RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&forward, sizeof(forward), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&uid, sizeof(uid), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&keycount, sizeof(keycount), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&keycountp, sizeof(keycountp), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&validatecount, sizeof(validatecount), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&validatecountp, sizeof(validatecountp), RW_READ))
|
||||
!read_write(fd, (unsigned char *)&uid, sizeof(uid), RW_READ))
|
||||
return 0;
|
||||
|
||||
if (op == PIPE_OP_RESULT &&
|
||||
(!read_write(fd, (unsigned char *)&keycount, sizeof(keycount), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&keycountp, sizeof(keycountp), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&validatecount, sizeof(validatecount), RW_READ) ||
|
||||
!read_write(fd, (unsigned char *)&validatecountp, sizeof(validatecountp), RW_READ)))
|
||||
return 0;
|
||||
|
||||
/* There's a tiny chance that the frec may have been freed
|
||||
@@ -1025,9 +1029,12 @@ int cache_recv_insert(time_t now, int fd)
|
||||
the uid field which is unique modulo 2^32 for each use. */
|
||||
if (uid == forward->uid)
|
||||
{
|
||||
/* repatriate the work counters from the child process. */
|
||||
*keycountp = keycount;
|
||||
*validatecountp = validatecount;
|
||||
if (op == PIPE_OP_RESULT)
|
||||
{
|
||||
/* repatriate the work counters from the child process. */
|
||||
*keycountp = keycount;
|
||||
*validatecountp = validatecount;
|
||||
}
|
||||
|
||||
if (!forward->dependent)
|
||||
return_reply(now, forward, (struct dns_header *)daemon->packet, ret_len, status);
|
||||
|
||||
Reference in new issue
Block a user