]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: resolvers: switch to a better PRNG for query IDs
authorWilly Tarreau <w@1wt.eu>
Tue, 26 May 2026 07:30:12 +0000 (09:30 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 26 May 2026 11:13:24 +0000 (13:13 +0200)
The PRNG used by the DNS currently is easily predictable once an
observer can collect a few consecutive IDs from the same thread, since
it's a 32-bit xorshift reduced to 16 bits output. Let's switch it to
ha_random32() instead.

This should be backported, however on older releases the ha_random32()
cost is higher due to the lock involved.

src/resolvers.c

index 1bcbdb857e7926f513aacfbaecd0fd5e9631961c..ffdc3163c4e00acdba83271494957bbfd1981107 100644 (file)
@@ -63,7 +63,6 @@ struct list resolv_srvrq_list = LIST_HEAD_INIT(resolv_srvrq_list);
 
 static THREAD_LOCAL struct list death_row; /* list of deferred resolutions to kill, local validity only */
 static THREAD_LOCAL unsigned int recurse = 0; /* counter to track calls to public functions */
-static THREAD_LOCAL uint64_t resolv_query_id_seed = 0; /* random seed */
 struct resolvers *curr_resolvers = NULL;
 
 DECLARE_STATIC_TYPED_POOL(resolv_answer_item_pool, "resolv_answer_item", struct resolv_answer_item);
@@ -365,18 +364,6 @@ struct resolv_answer_item *find_srvrq_answer_record(const struct resolv_requeste
        return NULL;
 }
 
-/* 2 bytes random generator to generate DNS query ID */
-static inline uint16_t resolv_rnd16(void)
-{
-       if (!resolv_query_id_seed)
-               resolv_query_id_seed = now_ms;
-       resolv_query_id_seed ^= resolv_query_id_seed << 13;
-       resolv_query_id_seed ^= resolv_query_id_seed >> 7;
-       resolv_query_id_seed ^= resolv_query_id_seed << 17;
-       return resolv_query_id_seed;
-}
-
-
 static inline int resolv_resolution_timeout(struct resolv_resolution *res)
 {
        return (!LIST_ISEMPTY(&res->requesters) ? res->resolvers->timeout.resolve : res->resolvers->hold.valid);
@@ -516,7 +503,7 @@ resolv_run_resolution(struct resolv_resolution *resolution)
        /* Generates a new query id. We try at most 100 times to find a free
         * query id */
        for (i = 0; i < 100; ++i) {
-               query_id = resolv_rnd16();
+               query_id = (uint16_t)ha_random32();
                if (!eb32_lookup(&resolvers->query_ids, query_id))
                        break;
                query_id = -1;