summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2015-07-23 13:13:43 +0200
committerTom Gundersen <teg@jklm.no>2015-07-23 18:06:50 +0200
commit89492aaf99a59b2858e71ebc30f3e123e7c6734c (patch)
treefca225fc7f596bd3ee48a95dc94d8129740b952d /src
parent549c1a2564b56f2bb38f1203d59c747ea15817f3 (diff)
resolved: rr - don't read past end of RR when parsing NSEC(3)
We can never read past the end of the packet, so this seems impossible to exploit, but let's error out early as reading past the end of the current RR is clearly an error. Found by Lennart, based on patch by Daniel.
Diffstat (limited to 'src')
-rw-r--r--src/resolve/resolved-dns-packet.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index af219ce4ff..25035ed7ee 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -1233,6 +1233,38 @@ fail:
return r;
}
+static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
+ size_t saved_rindex;
+ int r;
+
+ saved_rindex = p->rindex;
+
+ while (p->rindex < saved_rindex + size) {
+ r = dns_packet_read_type_window(p, types, NULL);
+ if (r < 0)
+ goto fail;
+
+ /* don't read past end of current RR */
+ if (p->rindex > saved_rindex + size) {
+ r = -EBADMSG;
+ goto fail;
+ }
+ }
+
+ if (p->rindex != saved_rindex + size) {
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ if (start)
+ *start = saved_rindex;
+
+ return 0;
+fail:
+ dns_packet_rewind(p, saved_rindex);
+ return r;
+}
+
int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
_cleanup_free_ char *name = NULL;
uint16_t class, type;
@@ -1634,11 +1666,12 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
if (r < 0)
goto fail;
- while (p->rindex != offset + rdlength) {
- r = dns_packet_read_type_window(p, &rr->nsec.types, NULL);
- if (r < 0)
- goto fail;
- }
+ r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
+ if (r < 0)
+ goto fail;
+
+ /* NSEC RRs with empty bitmpas makes no sense, but the RFC does not explicitly forbid them
+ so we allow it */
break;