From 295a3079783f6f5fd44562f2a6e57ba0a43e0d05 Mon Sep 17 00:00:00 2001 From: William Yang Date: Fri, 12 Jan 2024 12:00:42 +0100 Subject: [PATCH 1/2] fix(UAF): swap old/new l->config_ctx only when start success --- c_src/quicer_listener.c | 2 +- test/quicer_listener_SUITE.erl | 83 +++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/c_src/quicer_listener.c b/c_src/quicer_listener.c index 402cac7b..4a077fff 100644 --- a/c_src/quicer_listener.c +++ b/c_src/quicer_listener.c @@ -623,7 +623,6 @@ start_listener3(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) } QuicerConfigCTX *old_config_ctx = l_ctx->config_resource; - l_ctx->config_resource = new_config_ctx; #if defined(QUICER_USE_TRUSTED_STORE) X509_STORE_free(l_ctx->trusted_store); @@ -651,6 +650,7 @@ start_listener3(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) } l_ctx->is_stopped = FALSE; + l_ctx->config_resource = new_config_ctx; // the ongoing handshake will be completed with the old config enif_release_resource(old_config_ctx); diff --git a/test/quicer_listener_SUITE.erl b/test/quicer_listener_SUITE.erl index 6a0d71be..caa70aab 100644 --- a/test/quicer_listener_SUITE.erl +++ b/test/quicer_listener_SUITE.erl @@ -557,7 +557,6 @@ tc_listener_conf_reload(Config) -> tc_listener_conf_reload_listen_on(Config) -> process_flag(trap_exit, true), - DataDir = ?config(data_dir, Config), ServerConnCallback = example_server_connection, ServerStreamCallback = example_server_stream, Port = select_port(), @@ -637,6 +636,88 @@ tc_listener_conf_reload_listen_on(Config) -> gen_server:stop(ClientConnPid), quicer_listener:stop_listener(QuicApp). +tc_listener_conf_reload_listen_on_neg(Config) -> + process_flag(trap_exit, true), + ServerConnCallback = example_server_connection, + ServerStreamCallback = example_server_stream, + Port = select_port(), + application:ensure_all_started(quicer), + ListenerOpts = [ + {conn_acceptors, 32}, + {peer_bidi_stream_count, 0}, + {peer_unidi_stream_count, 1} + | default_listen_opts(Config) + ], + ConnectionOpts = [ + {conn_callback, ServerConnCallback}, + {stream_acceptors, 2} + | default_conn_opts() + ], + StreamOpts = [ + {stream_callback, ServerStreamCallback} + | default_stream_opts() + ], + Options = {ListenerOpts, ConnectionOpts, StreamOpts}, + + %% Given a QUIC connection between example client and example server + {ok, QuicApp} = quicer:spawn_listener(sample, Port, Options), + ClientConnOpts = default_conn_opts_verify(Config, ca), + {ok, ClientConnPid} = example_client_connection:start_link( + "localhost", + Port, + {ClientConnOpts, default_stream_opts()} + ), + + ct:pal("C1 status : ~p", [sys:get_status(ClientConnPid)]), + {ok, LHandle} = quicer_listener:get_handle(QuicApp, 5000), + + %% WHEN: the listener is reloaded with ListenOn (new bind address) + NewPort = 1, + %% THEN: We get error + {error, _, _} = quicer_listener:reload(QuicApp, NewPort, ListenerOpts), + %% THEN: the listener handle is unchanged + ?assertEqual({ok, LHandle}, quicer_listener:get_handle(QuicApp, 5000)), + + %% WHEN: we unlock it and start new connection + ok = quicer_listener:unlock(QuicApp, 3000), + + %% THEN: the new connection shall be established with some reties + %% and traffic can be sent and received + {ok, Conn2} = + snabbkaffe:retry( + 300, + 10, + fun() -> + {ok, _} = quicer:connect( + "localhost", + Port, + default_conn_opts_verify(Config, 'ca'), + 5000 + ) + end + ), + + {ok, Stream2} = quicer:start_stream( + Conn2, + #{open_flag => ?QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL} + ), + {ok, _} = quicer:send(Stream2, <<"ping_from_conn_2">>), + + receive + {quic, new_stream, Stream2Remote, #{is_orphan := true}} -> + quicer:setopt(Stream2Remote, active, true), + ok + end, + + receive + {quic, <<"ping_from_conn_2">>, Stream2Remote, _} -> ok + after 2000 -> + ct:fail("nothing from conn 2"), + quicer_test_lib:report_unhandled_messages() + end, + + quicer_listener:stop_listener(QuicApp). + tc_stop_close_listener(Config) -> Port = select_port(), {ok, L} = quicer:listen(Port, default_listen_opts(Config)), From 248bb65d8ab710c7d47e54814b661efd12ee897a Mon Sep 17 00:00:00 2001 From: William Yang Date: Fri, 12 Jan 2024 13:33:23 +0100 Subject: [PATCH 2/2] test: adapt to macOS --- test/quicer_listener_SUITE.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/quicer_listener_SUITE.erl b/test/quicer_listener_SUITE.erl index caa70aab..2cb2c483 100644 --- a/test/quicer_listener_SUITE.erl +++ b/test/quicer_listener_SUITE.erl @@ -99,6 +99,8 @@ end_per_group(_GroupName, _Config) -> %% Reason = term() %% @end %%-------------------------------------------------------------------- +init_per_testcase(tc_listener_conf_reload_listen_on_neg, Config) -> + {skip, "MacOs is able to listen on port 1"}; init_per_testcase(_TestCase, Config) -> application:ensure_all_started(quicer), quicer_test_lib:cleanup_msquic(), @@ -671,7 +673,7 @@ tc_listener_conf_reload_listen_on_neg(Config) -> ct:pal("C1 status : ~p", [sys:get_status(ClientConnPid)]), {ok, LHandle} = quicer_listener:get_handle(QuicApp, 5000), - %% WHEN: the listener is reloaded with ListenOn (new bind address) + %% WHEN: the listener is reloaded with ListenOn (new invalid bind address) NewPort = 1, %% THEN: We get error {error, _, _} = quicer_listener:reload(QuicApp, NewPort, ListenerOpts),