Skip to content

Commit 96ffcb5

Browse files
unsafesql: avoid panicking during query formatting
Part of the effort to guard access to the crdb_internal and system namespaces includes auditing override access (and denied access) to these unsafe internals. Included in this audit is the offending query which attempted to pry into these namespaces. In multiple locations however, this auditing caused the system to panic, for different reasons. In one case, an incorrect number of annotations on the query caused a panic. Another included a plan builder which had no associated statement. We see the process of going from plan -> query as a difficult one, and thus guard this attempt to audit these accesses in a blanket panic catcher, as it's not common that this will happen, and when it does we don't want the system to wholesale fail the query. Fixes: #153590 Epic: CRDB-24527 Release note: none
1 parent 1c18131 commit 96ffcb5

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

pkg/sql/unsafesql/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ go_library(
1414
"//pkg/util/log/eventpb",
1515
"//pkg/util/log/severity",
1616
"//pkg/util/timeutil",
17+
"@com_github_cockroachdb_redact//:redact",
1718
],
1819
)
1920

@@ -26,7 +27,9 @@ go_test(
2627
"//pkg/security/securityassets",
2728
"//pkg/security/securitytest",
2829
"//pkg/server",
30+
"//pkg/settings",
2931
"//pkg/sql/isql",
32+
"//pkg/sql/sem/tree",
3033
"//pkg/sql/sqlerrors",
3134
"//pkg/testutils/serverutils",
3235
"//pkg/testutils/sqlutils",

pkg/sql/unsafesql/unsafesql.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/cockroachdb/cockroach/pkg/util/log/eventpb"
1818
"github.com/cockroachdb/cockroach/pkg/util/log/severity"
1919
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
20+
"github.com/cockroachdb/redact"
2021
)
2122

2223
// The accessedLogLimiter is used to limit the rate of logging unsafe internal access
@@ -53,7 +54,7 @@ func CheckInternalsAccess(
5354
return nil
5455
}
5556

56-
q := tree.FormatAstAsRedactableString(stmt, ann, sv)
57+
q := SafeFormatQuery(stmt, ann, sv)
5758
// If an override is set, allow access to this virtual table.
5859
if sd.AllowUnsafeInternals {
5960
// Log this access to the SENSITIVE_ACCESS channel since the override condition bypassed normal access controls.
@@ -69,3 +70,20 @@ func CheckInternalsAccess(
6970
}
7071
return sqlerrors.ErrUnsafeTableAccess
7172
}
73+
74+
// SafeFormatQuery attempts to format the query for logging, but recovers from
75+
// any panics that may occur during formatting.
76+
func SafeFormatQuery(
77+
stmt tree.Statement, ann *tree.Annotations, sv *settings.Values,
78+
) (s redact.RedactableString) {
79+
if stmt == nil {
80+
return "<nil statement>"
81+
}
82+
defer func() {
83+
if r := recover(); r != nil {
84+
log.Dev.Errorf(context.TODO(), "panic in SafeFormatQuery: %v", r)
85+
s = "<panicked query format>"
86+
}
87+
}()
88+
return tree.FormatAstAsRedactableString(stmt, ann, sv)
89+
}

pkg/sql/unsafesql/unsafesql_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import (
1616
"github.com/cockroachdb/cockroach/pkg/security/securityassets"
1717
"github.com/cockroachdb/cockroach/pkg/security/securitytest"
1818
"github.com/cockroachdb/cockroach/pkg/server"
19+
"github.com/cockroachdb/cockroach/pkg/settings"
1920
"github.com/cockroachdb/cockroach/pkg/sql/isql"
21+
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
2022
"github.com/cockroachdb/cockroach/pkg/sql/sqlerrors"
2123
"github.com/cockroachdb/cockroach/pkg/sql/unsafesql"
2224
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
@@ -255,3 +257,35 @@ func TestAccessCheckServer(t *testing.T) {
255257
})
256258
}
257259
}
260+
261+
// panickingStatement is a mock Statement that panics during formatting
262+
type panickingStatement struct{}
263+
264+
func (ps panickingStatement) String() string {
265+
return "panicking statement"
266+
}
267+
268+
func (ps panickingStatement) Format(ctx *tree.FmtCtx) {
269+
panic("deliberate panic for testing")
270+
}
271+
272+
func (ps panickingStatement) StatementReturnType() tree.StatementReturnType {
273+
return tree.Unknown
274+
}
275+
276+
func (ps panickingStatement) StatementType() tree.StatementType {
277+
return tree.TypeDML
278+
}
279+
280+
func (ps panickingStatement) StatementTag() string {
281+
return "TEST"
282+
}
283+
284+
func TestPanickingSQLFormat(t *testing.T) {
285+
result := unsafesql.SafeFormatQuery(panickingStatement{}, nil, &settings.Values{})
286+
require.Equal(
287+
t,
288+
"<panicked query format>",
289+
string(result),
290+
)
291+
}

0 commit comments

Comments
 (0)