You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@serf.apache.org by Alexandr Miloslavskiy <al...@syntevo.com> on 2021/10/08 01:08:37 UTC
[BUG] Segfault when connection failed
I'm trying serf from branch 1.4.x.
I couldn't use 1.3.9 because I also need to use OpenSSL 1.1.
I have encountered a segfault and debugged. To my understanding, the
crashing code comes from this commit:
r1712776 by Bert Huijben, 2015-11-05 17:05:02
Hard to say if the commit introduced the problem or merely shuffled the
code around. At any rate, the crash is not reproducible with serf 1.3.9.
I have debugged, see analysis below. However, without knowledge of serf,
I can't quickly figure how to fix.
Hopefully Bert could do that?
Analysis:
---------
1) I'm trying to connect SVN to an HTTPS server using a client cert.
2) I'm using a wrong password for the certificate.
3) In `ssl_decrypt()`
It detects error in `SSL_read()` and propagates error.
Stack:
libsvn_ra_1!ssl_decrypt
libsvn_ra_1!common_databuf_prep
libsvn_ra_1!serf_databuf_peek
libsvn_ra_1!read_from_connection
libsvn_ra_1!process_connection
libsvn_ra_1!serf__process_connection
libsvn_ra_1!serf_context_run
libsvn_ra_1!svn_ra_serf__context_run_wait
libsvn_ra_1!svn_ra_serf__exchange_capabilities
libsvn_ra_1!svn_ra_serf__open
libsvn_ra_1!svn_ra_open5
libsvn_client_1!svn_client__open_ra_session_internal
libsvn_client_1!svn_client__ra_session_from_path2
libsvn_client_1!svn_client_info4
4) In `svn_ra_open5()`
calls `svn_pool_destroy(sesspool)`
5) In `svn_pool_destroy()`
calls the registered `clean_resp()`
6) In `clean_resp()`
Sets `request->respool` to NULL.
(request->writing == SERF_WRITING_STARTED)
calls `serf__connection_pre_cleanup()`
7) In `serf__connection_pre_cleanup()`
It has loop for `conn->done_reqs`.
loop handles exactly one request, the one already in `clean_resp()`
loop sets `rq->writing` to `SERF_WRITING_FINISHED`
loop calls `serf__destroy_request()`
8) In `serf__destroy_request()`
`rq->writing` is already `SERF_WRITING_FINISHED` (see #7)
Therefore, it's time to clean things.
`request->respool` is null (see #6).
`request` is freed via `serf_bucket_mem_free()`.
9) Back to `clean_resp()`
Segfaults on `if (request->resp_bkt)`.
Re: [BUG] Segfault when connection failed
Posted by Alexandr Miloslavskiy <al...@syntevo.com>.
CC += Bert Huijben, probably he knows the area best
On 08.10.2021 4:08, Alexandr Miloslavskiy wrote:
> I'm trying serf from branch 1.4.x.
> I couldn't use 1.3.9 because I also need to use OpenSSL 1.1.
>
> I have encountered a segfault and debugged. To my understanding, the
> crashing code comes from this commit:
> r1712776 by Bert Huijben, 2015-11-05 17:05:02
>
> Hard to say if the commit introduced the problem or merely shuffled the
> code around. At any rate, the crash is not reproducible with serf 1.3.9.
>
> I have debugged, see analysis below. However, without knowledge of serf,
> I can't quickly figure how to fix.
>
> Hopefully Bert could do that?
>
> Analysis:
> ---------
> 1) I'm trying to connect SVN to an HTTPS server using a client cert.
>
> 2) I'm using a wrong password for the certificate.
>
> 3) In `ssl_decrypt()`
> It detects error in `SSL_read()` and propagates error.
> Stack:
> libsvn_ra_1!ssl_decrypt
> libsvn_ra_1!common_databuf_prep
> libsvn_ra_1!serf_databuf_peek
> libsvn_ra_1!read_from_connection
> libsvn_ra_1!process_connection
> libsvn_ra_1!serf__process_connection
> libsvn_ra_1!serf_context_run
> libsvn_ra_1!svn_ra_serf__context_run_wait
> libsvn_ra_1!svn_ra_serf__exchange_capabilities
> libsvn_ra_1!svn_ra_serf__open
> libsvn_ra_1!svn_ra_open5
> libsvn_client_1!svn_client__open_ra_session_internal
> libsvn_client_1!svn_client__ra_session_from_path2
> libsvn_client_1!svn_client_info4
>
> 4) In `svn_ra_open5()`
> calls `svn_pool_destroy(sesspool)`
>
> 5) In `svn_pool_destroy()`
> calls the registered `clean_resp()`
>
> 6) In `clean_resp()`
> Sets `request->respool` to NULL.
> (request->writing == SERF_WRITING_STARTED)
> calls `serf__connection_pre_cleanup()`
>
> 7) In `serf__connection_pre_cleanup()`
> It has loop for `conn->done_reqs`.
> loop handles exactly one request, the one already in `clean_resp()`
> loop sets `rq->writing` to `SERF_WRITING_FINISHED`
> loop calls `serf__destroy_request()`
>
> 8) In `serf__destroy_request()`
> `rq->writing` is already `SERF_WRITING_FINISHED` (see #7)
> Therefore, it's time to clean things.
> `request->respool` is null (see #6).
> `request` is freed via `serf_bucket_mem_free()`.
>
> 9) Back to `clean_resp()`
> Segfaults on `if (request->resp_bkt)`.
>