pmproxy: release the X509 reference in the CERT_REQD check - #2698
Conversation
SSL_get_peer_certificate() returns a certificate whose reference count has been incremented, so the caller owns that reference and must release it with X509_free(). On OpenSSL 3.x the name is a compatibility macro for SSL_get1_peer_certificate(), which has the same owning semantics. 81a9efe called it inline in the NULL test and discarded the result. Because of the short-circuit order the reference is taken only when the connection is TLS and an SSL object exists, and it is leaked precisely when a certificate is present - that is, on the path where the request is allowed through. on_headers_complete() runs once per request, so a pmproxy started with -Q accumulates one X509 per authenticated REST request for the lifetime of the daemon. Capture the reference and free it, leaving the accept/reject logic unchanged. SSL_get0_peer_certificate() would avoid the reference entirely but is not available on the older OpenSSL versions pcp still supports. Reported and fixed while backporting 81a9efe to pcp 6.3.7 and 6.0.1. Fixes performancecopilot#2693.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughSummary by CodeRabbit
WalkthroughThe ChangesCertificate Reference Cleanup
Suggested reviewers: Poem
Merge Risk: ⚪ Minimal · up to This localized change releases the certificate reference taken during CERT_REQD checks, preventing a per-request memory leak for affected TLS clients. No actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@wtatarski thanks! |
SSL_get_peer_certificate()returns a certificate whose reference count has beenincremented, so the caller owns that reference and must release it with
X509_free().On OpenSSL 3.x the name is a compatibility macro for
SSL_get1_peer_certificate(),which has the same owning semantics.
81a9efe ("pmproxy: enforce -Q (CERT_REQD) for REST API connections") called it
inline in the NULL test and discarded the result:
Because of the short-circuit order the reference is only taken when the connection is
TLS and an SSL object exists, and it is leaked precisely when a certificate is
present — that is, on the path where the request is allowed through. The rejection paths
do not leak.
on_headers_complete()runs once per request, so apmproxystarted with-Qaccumulates oneX509per authenticated REST request for the lifetime of thedaemon.
This only affects deployments that have opted into client-certificate enforcement;
-Qis not enabled by the shipped
pmproxy.conf. It is a reliability defect rather than asecurity issue, since reaching it requires a client certificate that already passed
validation.
The fix captures the reference and frees it, leaving the accept/reject logic unchanged.
SSL_get0_peer_certificate()would avoid taking a reference at all, but it is notavailable on the older OpenSSL versions pcp still supports, so
X509_free()is theportable form.
Found while backporting 81a9efe to pcp 6.3.7 and 6.0.1 (OpenSSL 3.2.2). Verified
against current
main(55365f2): the block is unchanged there, this commit introducesthe only call to
SSL_get_peer_certificate()undersrc/, and there is no otherX509_free()in the tree — so nothing else was releasing it.Related Issues
Fixes #2693