diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-04-13 13:09:38 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-04-13 13:09:38 +0200 |
commit | e14a27723cc3a154d67f3f26e719d08c0ba9ad25 (patch) | |
tree | c4706acf27f91784a8b592772d03e0c8da0b4731 /resolv/res_mkquery.c | |
parent | c803cb9b24c6cea15698768e4301e963b98e742c (diff) | |
download | glibc-e14a27723cc3a154d67f3f26e719d08c0ba9ad25.tar glibc-e14a27723cc3a154d67f3f26e719d08c0ba9ad25.tar.gz glibc-e14a27723cc3a154d67f3f26e719d08c0ba9ad25.tar.bz2 glibc-e14a27723cc3a154d67f3f26e719d08c0ba9ad25.zip |
resolv: Reduce EDNS payload size to 1200 bytes [BZ #21361]
This hardens the stub resolver against fragmentation-based attacks.
Diffstat (limited to 'resolv/res_mkquery.c')
-rw-r--r-- | resolv/res_mkquery.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 4532b582a2..8279d15de4 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -69,7 +69,7 @@ #include <netinet/in.h> #include <arpa/nameser.h> #include <netdb.h> -#include <resolv.h> +#include <resolv/resolv-internal.h> #include <stdio.h> #include <string.h> #include <sys/time.h> @@ -225,7 +225,30 @@ __res_nopt(res_state statp, *cp++ = 0; /* "." */ NS_PUT16(T_OPT, cp); /* TYPE */ - NS_PUT16(MIN(anslen, 0xffff), cp); /* CLASS = UDP payload size */ + + /* Lowering the advertised buffer size based on the actual + answer buffer size is desirable because the server will + minimize the reply to fit into the UDP packet (and A + non-minimal response might not fit the buffer). + + The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP + fallback and a non-minimal response which has to be + hard-truncated in the stub resolver, but this is price to + pay for avoiding fragmentation. (This issue does not + affect the nss_dns functions because they use the stub + resolver in such a way that it allocates a properly sized + response buffer.) */ + { + uint16_t buffer_size; + if (anslen < 512) + buffer_size = 512; + else if (anslen > RESOLV_EDNS_BUFFER_SIZE) + buffer_size = RESOLV_EDNS_BUFFER_SIZE; + else + buffer_size = anslen; + NS_PUT16 (buffer_size, cp); + } + *cp++ = NOERROR; /* extended RCODE */ *cp++ = 0; /* EDNS version */ @@ -243,4 +266,3 @@ __res_nopt(res_state statp, return cp - buf; } -libresolv_hidden_def (__res_nopt) |