From: Shuji Furukawa Date: Mon, 18 Nov 2024 14:20:20 +0000 (+0900) Subject: Improve shuffling algorithm of connection list X-Git-Tag: v2.7_alpha1~132 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9502e5257c59bfd23b9afcdb28f7994470591430;p=thirdparty%2Fopenvpn.git Improve shuffling algorithm of connection list This patch implements the Fisher-Yates shuffle algorithm to ensure that all permutations of the connection target list are generated with equal probability, eliminating biases present in the previous shuffling method. In the Fisher-Yates algorithm, there's only one way to obtain each permutation through a series of element swaps, so all permutations occur with equal probability in theory. Signed-off-by: Shuji Furukawa Acked-by: Antonio Quartulli Message-Id: <20241118142019.31045-1-shujifurukawa1213@gmail.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg29837.html Signed-off-by: Gert Doering --- diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 7145495ce..a23cb2477 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -467,7 +467,15 @@ ce_management_query_remote(struct context *c) #endif /* ENABLE_MANAGEMENT */ /* - * Initialize and possibly randomize connection list. + * Initialize and possibly randomize the connection list. + * + * Applies the Fisher-Yates shuffle algorithm to ensure all permutations + * are equally probable, thereby eliminating shuffling bias. + * + * The algorithm randomly selects an element from the unshuffled portion + * and places it at position i. There's only one way to obtain each + * permutation through these swaps. This guarantees that each permutation + * occurs with equal probability in theory. */ static void init_connection_list(struct context *c) @@ -478,9 +486,9 @@ init_connection_list(struct context *c) if (c->options.remote_random) { int i; - for (i = 0; i < l->len; ++i) + for (i = l->len - 1; i > 0; --i) { - const int j = get_random() % l->len; + const int j = get_random() % (i + 1); if (i != j) { struct connection_entry *tmp;