fix(storage): narrow the pinned-connection discard escape - #952
Conversation
The exported rebindConn.Raw handed callers the underlying driver connection, an open-ended binder bypass. Replace it with an unexported discardBadConn that can only retire the session, and rename raw() to lockerConn() so the one sanctioned bypass is explicit. Follow-up to review feedback on #950.
There was a problem hiding this comment.
Pull request overview
This PR tightens the rebindConn wrapper API in pkg/storage/internal/sqlstore to remove the exported driver-connection escape hatch, while preserving the one explicit binder bypass needed for advisory-locking on a pinned session. It reduces the surface area for bypassing placeholder rebinding and makes “retire this session” impossible to misuse for executing SQL outside the binder boundary.
Changes:
- Replace exported
rebindConn.Raw(...)with an internaldiscardBadConn()that retires the pinned session viadriver.ErrBadConnwithout exposing the underlying driver connection. - Rename the advisory-lock escape from
raw()tolockerConn()to make the binder-bypass intent explicit and narrowly scoped. - Update lock-connection cleanup to treat
sql.ErrConnDoneas a successful close after a discard, and add/extend unit tests around discard behavior and Tx isolation propagation.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/storage/internal/sqlstore/db.go | Removes exported driver-conn access; adds discardBadConn() and renames the lock-only binder bypass to lockerConn(). |
| pkg/storage/internal/sqlstore/db_test.go | Adds coverage ensuring discard retires sessions without SQL/binder access and verifies Tx isolation options reach the driver through wrappers. |
| pkg/storage/internal/sqlstore/apply_operations.go | Switches advisory-lock calls from raw() to lockerConn() for the named-lock boundary. |
| pkg/storage/internal/sqlstore/apply_operations_test.go | Updates tests to use lockerConn() for named-lock Acquire/Release. |
| pkg/storage/internal/sqlstore/applies.go | Routes discard through discardBadConn(), switches named-lock usage to lockerConn(), and treats sql.ErrConnDone as a successful close after discard. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
🤖 Adversarial correctness review, requested by Armand and performed by his agent. Reviewed at head Verdict: correct, and exactly the right shape for this wrapper — no findings. The escape surface now says what it means: FindingsNone. Verified (tried to break, couldn't)
This review was generated by Claude Code (claude-fable-5). |
aparajon
left a comment
There was a problem hiding this comment.
🤖 Approving on Armand's behalf after the adversarial correctness review above (no findings). This stamp was left by Claude Code (claude-fable-5).
Summary
Follow-up to #950 review feedback. The exported
rebindConn.Raw(func(driverConn any) error)gave any caller open-ended access to the underlying driver connection — an unnecessary binder-bypass surface on a wrapper whose whole job is to guarantee every statement rebinds exactly once. This narrows the wrapper so lifecycle control cannot execute SQL.What
rebindConn.Rawwith unexporteddiscardBadConn(): it injectsdriver.ErrBadConninternally so the pool destroys the session, swallows the sentinel as the success signal, and exposes no driver connection to callers.raw()tolockerConn()so the sole sanctioned binder bypass reads as what it is: the advisory-lock boundary that must run engine-native placeholders on the pinned session.closeApplyTargetLockConntreatssql.ErrConnDoneas success, since a preceding discard retires the session immediately.discardBadConndestroys the driver connection, executes no SQL, never touches the binder, and a laterClosereportssql.ErrConnDone; transaction isolation levels (RepeatableRead / ReadCommitted) survive the wrapper types to the driver while still rebinding exactly once.Why
After this change the wrapper's surface tells the full story:
lockerConn()is the only way SQL can bypass the binder, and it exists solely for the advisory locker. Discarding a suspect session is deliberately incapable of running statements, so no future caller can quietly route store SQL around the rebind guarantee.Before / after