]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
rrcache: don't clobber pkt if failing the second step
authorVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 18 Apr 2017 10:24:04 +0000 (12:24 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 18 Apr 2017 14:05:12 +0000 (16:05 +0200)
I hope fixing this bug should diminish the recent experiences of Google
domains failing to resolve on Turris Omnia.

lib/layer/rrcache.c

index e7f3a0f853d9c12f55d7c5518ec725e5a5ddbf43..d5d908a3b1fd14146213d84c0494859ce43f7419 100644 (file)
@@ -117,6 +117,21 @@ static int loot_rrcache(struct kr_cache *cache, knot_pkt_t *pkt,
        } else if (ret == 0 && dobit) {
                ret = loot_rr(cache, pkt, qry->sname, qry->sclass, rrtype, qry,
                              &rank, &flags, true, lowest_rank);
+               if (ret) {
+                       VERBOSE_MSG(qry, "=> RRSIG(s) expected but not found, skipping");
+                       /* In some cases, e.g. due to bugs, this may fail.
+                        * A possible good example is that a cache backend
+                        * (such as redis) chose to evict RRSIG but not RRset.
+                        * Let's return cache failure, but the packet has been
+                        * updated already by the RRs!  Let's try to clear it.
+                        * The following command might theoretically fail again
+                        * while parsing question, but let's just log that
+                        * condition in non-debug mode (it might be non-fatal). */
+                       if (kr_pkt_clear_payload(pkt)) {
+                               kr_log_error("[ rc ] => ERROR: work-around failed\n");
+                               assert(false);
+                       }
+               }
        }
        return ret;
 }
@@ -411,7 +426,7 @@ static int rrcache_stash(kr_layer_t *ctx, knot_pkt_t *pkt)
                if (ret == kr_error(ENOSPC)) {
                        ret = kr_cache_clear(cache);
                        if (ret != 0 && ret != kr_error(EEXIST)) {
-                               kr_log_error("[cache] failed to clear cache: %s\n", kr_strerror(ret));
+                               kr_log_error("[ rc ] failed to clear cache: %s\n", kr_strerror(ret));
                        }
                }
                kr_cache_sync(cache);