Skip to content

mbedtls: client: fix ALPN stack-use-after-scope - #3658

Open
saghul wants to merge 1 commit into
warmcat:mainfrom
saghul:fix-mbedtls-client-alpn-uaf
Open

mbedtls: client: fix ALPN stack-use-after-scope#3658
saghul wants to merge 1 commit into
warmcat:mainfrom
saghul:fix-mbedtls-client-alpn-uaf

Conversation

@saghul

@saghul saghul commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

In lws_ssl_client_bio_create() (mbedtls backend), the final else branch copies the ALPN from the ah into a temp_alpn[128] buffer scoped to that block and points alpn_comma at it:

} else {
    char temp_alpn[128];
    if (lws_hdr_copy(wsi, temp_alpn, sizeof(temp_alpn),
            _WSI_TOKEN_CLIENT_ALPN) > 0)
        alpn_comma = temp_alpn;
}   /* temp_alpn goes out of scope here */

if (alpn_comma) {
    ...
    lws_mbedtls_set_alpn(conn->ctx, alpn_comma);  /* reads out-of-scope stack */
}

lws_mbedtls_set_alpn() runs after the block closes and lws_strncpy()s alpn_comma into ctx->alpn_strings, so it reads out-of-scope stack.

This branch is taken for a client wsi that has no stash and carries its ALPN in the ah header — e.g. the QUIC→TCP fallback reset path (lws_client_h3_grace_cblws_client_reset), where an Alt-Svc-learned h3 origin whose QUIC path doesn't answer is retried over TCP. It happens to work in practice because the stack slot is usually not reused before the copy, but it is undefined behaviour.

ASAN reports it as stack-use-after-scope in lws_mbedtls_set_alpn (via lws_strncpy), reached from lws_ssl_client_bio_create.

Fix: hoist temp_alpn to function scope so it outlives the assignment. One-line move; no behaviour change on any path.

Verified downstream (txiki.js, mbedtls + native h3 Alt-Svc upgrade/fallback): the fallback test went from a reproducible stack-use-after-scope under ASAN to clean with this change.

In lws_ssl_client_bio_create() the final else branch copies the ALPN from
the ah into a temp_alpn[] buffer scoped to that block and points alpn_comma
at it, but lws_mbedtls_set_alpn(conn->ctx, alpn_comma) runs after the block
has closed, so it reads (and lws_strncpy()s) out-of-scope stack.

This path is taken for a client wsi with no stash that carries its ALPN in
the ah header, e.g. the QUIC->TCP fallback reset (lws_client_h3_grace_cb ->
lws_client_reset). It happens to work because the stack slot is usually not
yet reused, but it is undefined behaviour; ASAN reports stack-use-after-scope
at lws_mbedtls_set_alpn().

Hoist temp_alpn to function scope so it outlives the assignment.
@sonarqubecloud

Copy link
Copy Markdown

saghul added a commit to saghul/txiki.js that referenced this pull request Aug 21, 2026
Adds patches/lws-mbedtls-client-alpn-uaf.patch (upstreamed as
warmcat/libwebsockets#3658) and the CMake infrastructure to apply
libwebsockets patches to the submodule work tree at configure time,
mirroring the existing mbedTLS QUIC patch scheme (idempotent
forward/reverse apply --check).

This makes the HTTP/3 native-upgrade PR ASAN-green as a whole without
waiting on the upstream merge: the fallback path triggers a
stack-use-after-scope in lws_ssl_client_bio_create() that the patch
fixes. Drop the patch and this block once the lws submodule is bumped
past the merge.
saghul added a commit to saghul/txiki.js that referenced this pull request Aug 21, 2026
Adds patches/lws-mbedtls-client-alpn-uaf.patch (upstreamed as
warmcat/libwebsockets#3658) and the CMake infrastructure to apply
libwebsockets patches to the submodule work tree at configure time,
mirroring the existing mbedTLS QUIC patch scheme (idempotent
forward/reverse apply --check).

This makes the HTTP/3 native-upgrade PR ASAN-green as a whole without
waiting on the upstream merge: the fallback path triggers a
stack-use-after-scope in lws_ssl_client_bio_create() that the patch
fixes. Drop the patch and this block once the lws submodule is bumped
past the merge.
saghul added a commit to saghul/txiki.js that referenced this pull request Aug 21, 2026
Adds patches/lws-mbedtls-client-alpn-uaf.patch (upstreamed as
warmcat/libwebsockets#3658) and the CMake infrastructure to apply
libwebsockets patches to the submodule work tree at configure time,
mirroring the existing mbedTLS QUIC patch scheme (idempotent
forward/reverse apply --check).

This makes the HTTP/3 native-upgrade PR ASAN-green as a whole without
waiting on the upstream merge: the fallback path triggers a
stack-use-after-scope in lws_ssl_client_bio_create() that the patch
fixes. Drop the patch and this block once the lws submodule is bumped
past the merge.
@lws-team
lws-team force-pushed the main branch 10 times, most recently from 591ce34 to bc69b6b Compare August 31, 2026 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant