5.3.0 regression: SSL_set_cert_cb(..., NULL, ...) stores a null function pointer instead of clearing, crashing the next handshake
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- Nửa ngày
- Mức phù hợp với người mới
- 62/100
Hướng nghiên cứu
Start in ssl/ssl_cert.cc at ssl_cert_set_cert_cb (both overloads), where a null callback is stored as an OldCallback instead of resetting to std::monostate, and check CertCb::operator bool() in ssl/internal.h. Then trace do_cert_callback in ssl/handshake_server.cc. A regression test should call SSL_set_cert_cb(ssl, NULL, NULL) and complete a server handshake without invoking a callback. Done when clearing with NULL leaves the callback absent and that test passes, with any boring-sys/patches/ entry kept consistent with the upstream fix.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
In boring / boring-sys 5.3.0 (BoringSSL revision 427ec40c), clearing a certificate callback by passing NULL no longer resets it to the empty state. The null pointer is stored as an OldCallback alternative inside CertCb::cb, so CertCb::operator bool() reports the callback as present, and do_cert_callback then invokes a null function pointer. On our machines this crashes the server process during the resumed TLS handshake and currently keeps us from upgrading to 5.3.0.
Root cause
Introduced by google/boringssl commit 902518a787 ("ssl: Allow certificate selection callback to pick fatal alert"), which turned CERT::cert_cb into struct CertCb { std::variant<std::monostate, OldCallback, NewCallback> }:
// ssl/ssl_cert.cc, ssl_cert_set_cert_cb (both overloads)
- cert->cert_cb = cb;
+ cert->cert_cb.cb = cb;
Assigning a null function pointer selects the OldCallback alternative by exact type match rather than monostate, so the "cleared" representation is no longer reachable through this setter. CertCb::operator bool() (ssl/internal.h) only excludes monostate, and do_cert_callback (ssl/handshake_server.cc) calls the callback whenever that conversion is true.
Reproduction (real world)
Pingora's resumable TLS accept uses exactly this pattern: it arms a blocking cert_cb (suspend_when_need_ssl_cert), pauses the handshake, installs the certificate, then clears the callback with SSL_set_cert_cb(ssl, NULL, NULL) before resuming (unblock_ssl_cert in pingora-boringssl). With 5.3.0 every resumed handshake crashes:
bssl::CertCb::operator()(ssl_st*, void*, unsigned char*) const
bssl::do_cert_callback(bssl::SSL_HANDSHAKE*)
bssl::ssl_server_handshake(bssl::SSL_HANDSHAKE*)
...
SSL_do_handshake
SSL_accept
(excerpt from the macOS crash report: EXC_BAD_ACCESS, invalid address 0x0)
Bisecting boring/boring-sys back to 5.2.0 makes all of this disappear: 33 failing integration tests go back to green. SSL_CTX_set_cert_cb(ctx, NULL, arg) alone should be enough to hit the same path on the next server handshake.
Suggested fix
Normalize a null callback to the empty state in ssl_cert_set_cert_cb, restoring the previous "NULL clears" behavior:
if (cb == nullptr) {
cert->cert_cb.cb = std::monostate();
} else {
cert->cert_cb.cb = cb;
}
(same for the _ex overload.)
Notes
- The same code is present on google/boringssl
mainas of 2026-10-15. - Reproduced on macOS 27.0.1 (26A434) aarch64, rustc 1.99.0; the defect in the C++ itself is platform-independent.
- Happy to send a PR that carries the change as a
boring-sys/patches/entry with a regression test, if that is the preferred route — or to help get it into BoringSSL if you would rather pick it up with the next revision bump.
- Ngôn ngữ chính
- Rust
- Star
- 526
- Fork
- 178
- Merge trung bình
- 15 giờ 34 phút
- Pull request đã merge (30 ngày)
- 9
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của cloudflare/boring
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
cloudflare/boring#527 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
cloudflare/boring#526 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
SLH-DSA supportCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
cloudflare/boring#522 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Build failure on 32 bit freebsdĐang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
cloudflare/boring#517 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
cloudflare/boring#500 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của cloudflare/boring
Issue tương tự
-
area/infra good first issue type/bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 60/100
cristim/AztecCraft#92 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
charles-hood/DiagramCraft#51 ·
-
S: Untriaged T: Bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
libnyanpasu/clash-nyanpasu#5788 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
area:cli bug good first issue priority:medium
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
rtk-ai/rtk#4589 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày