From: Vladimír Čunát Date: Wed, 26 Jul 2017 16:21:01 +0000 (+0200) Subject: rrcache: fix prefetching of expiring insecure RRs X-Git-Tag: v1.3.2~1^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=35a281d1a86d296a818449c9963be233db8bba27;p=thirdparty%2Fknot-resolver.git rrcache: fix prefetching of expiring insecure RRs Our security policy prevented those from reaching cache, crippling the feature. --- diff --git a/daemon/bindings.c b/daemon/bindings.c index cd7affafb..853deb867 100644 --- a/daemon/bindings.c +++ b/daemon/bindings.c @@ -1188,7 +1188,10 @@ static int wrk_resolve(lua_State *L) lua_error(L); } uint8_t dname[KNOT_DNAME_MAXLEN]; - knot_dname_from_str(dname, lua_tostring(L, 1), sizeof(dname)); + if (!knot_dname_from_str(dname, lua_tostring(L, 1), sizeof(dname))) { + lua_pushstring(L, "invalid qname"); + lua_error(L); + }; /* Check class and type */ uint16_t rrtype = lua_tointeger(L, 2); if (!lua_isnumber(L, 2)) { diff --git a/lib/layer/rrcache.c b/lib/layer/rrcache.c index d5a5d2bd4..2a25c1af2 100644 --- a/lib/layer/rrcache.c +++ b/lib/layer/rrcache.c @@ -88,7 +88,6 @@ static int loot_rr(struct kr_cache *cache, knot_pkt_t *pkt, const knot_dname_t * return kr_error(ENOENT); } - /* Mark as expiring if it has less than 1% TTL (or less than 5s) */ if (is_expiring(&cache_rr, drift)) { qry->flags |= QUERY_EXPIRING; } @@ -301,7 +300,19 @@ static int commit_rr(const char *key, void *val, void *data) * This way they would have to hit the first answer (whenever TTL expires). */ if (cached_rank >= 0) { VERBOSE_MSG(baton->qry, "=> orig. rank: 0%0.2o\n", cached_rank); - if (cached_rank >= rank) { + bool accept = rank > cached_rank; + /* Additionally accept equal rank if the cached RR is expiring. + * This is primarily for prefetching from predict module. */ + if (rank == cached_rank) { + uint32_t drift = baton->timestamp; + knot_rrset_t cache_rr; + knot_rrset_init(&cache_rr, rr->owner, rr->type, rr->rclass); + int ret = kr_cache_peek_rr(baton->cache, &cache_rr, NULL, NULL, &drift); + if (ret != kr_ok() || is_expiring(&cache_rr, drift)) { + accept = true; + } + } + if (!accept) { return kr_ok(); } } diff --git a/modules/predict/predict.lua b/modules/predict/predict.lua index 153d534c0..4bc1acf3f 100644 --- a/modules/predict/predict.lua +++ b/modules/predict/predict.lua @@ -31,7 +31,7 @@ function predict.drain(ev) local deleted = 0 for key, val in pairs(predict.queue) do local qtype, qname = key:match('(%S*)%s(.*)') - worker.resolve(qname, kres.type[qtype], 1, kres.query.NO_CACHE) + worker.resolve(qname, kres.type[qtype], kres.class.IN, kres.query.NO_CACHE) predict.queue[key] = nil deleted = deleted + 1 if deleted >= predict.batch then