]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
options: fix use-after-free of DNS options on client connect master
authorAntonio Quartulli <antonio@mandelbit.com>
Mon, 22 Jun 2026 12:08:51 +0000 (14:08 +0200)
committerGert Doering <gert@greenie.muc.de>
Mon, 22 Jun 2026 13:28:19 +0000 (15:28 +0200)
struct dns_options embeds its own gc_arena. When inherit_context_child()
/inherit_context_top() copy struct options by value, the child shares the
parent's DNS arena. options_detach() detached o->gc but not
o->dns_options.gc, so pre_connect_restore()'s gc_free() (and context
teardown) freed allocations the parent still referenced.

With one or more non-pushed --dhcp-option directives that yield a DNS
entry, a connecting client triggers this and the server crashes
(use-after-free in setenv_dns_options(), reported as a double free).

Detach o->dns_options.gc as well, mirroring the existing o->gc handling.

Change-Id: I49b37b5a90554fa2d4a83c8fc5608dad2a36b835
GitHub: closes openvpn/OpenVPN#1060
Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
Acked-by: Arne Schwabe <arne-openvpn@rfc2549.org>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1715
Message-Id: <20260622120856.21586-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg37230.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
src/openvpn/options.c

index 80121923dd43be5c368a719e79ecccd6457a0d86..f4140242254cd33da405ce66b9ec606051113fad 100644 (file)
@@ -1531,7 +1531,18 @@ show_http_proxy_options(const struct http_proxy_options *o)
 void
 options_detach(struct options *o)
 {
+    /* The options struct carries two gc_arena's (one generic and one specific
+     * to the DNS settings), which the by-value options
+     * copy in inherit_context_child()/inherit_context_top() shares with the
+     * source.
+     *
+     * Detach both (i.e. re-initialize them), otherwise child's call of
+     * gc_free() (or context teardown) would free allocations the source
+     * context still references, leading to a use-after-free (and subsequent
+     * double-free).
+     */
     gc_detach(&o->gc);
+    gc_detach(&o->dns_options.gc);
     o->routes = NULL;
     o->client_nat = NULL;
     clone_push_list(o);