Follow-up from the round-2 security review of #4051 (finding L-1): #4051 (comment)
Problem
A failed login can plant one invalid byte in the PostgreSQL server log (#4046). The three log readers (pg_log_events, pg_deadlocks, pg_plan_capture) read the log with pg_read_file, which returns text. On some database encodings, one planted byte fails the whole 4 MB tail read until the line leaves the window.
#4051 adds a byte route: with EXECUTE on pg_read_binary_file, the readers read the log as bytea and decode it as UTF-8. That route serves UTF8 and SQL_ASCII databases only. Decoding as UTF-8 is wrong for other encodings, because it turns the database's own non-ASCII text into U+FFFD.
The text route is still blindable on some of those other encodings:
- EUC encodings (for example
EUC_JP): PostgreSQL checks the text against the database encoding on read. An invalid multibyte sequence fails the read with SQLSTATE 22021.
WIN1252: the bytes 0x81, 0x8D, 0x8F, 0x90 and 0x9D have no UTF-8 equivalent, so the conversion to the client's UTF8 fails with SQLSTATE 22P05.
Single-byte encodings that map every byte, such as LATIN1, are not affected. Every byte except NUL is valid text there, and every byte converts to UTF-8.
Proposed fix
Let the byte route serve every server encoding. Decode the bytea in the connected database's own encoding (the value of server_encoding) instead of always as UTF-8. Map each PostgreSQL encoding name to a .NET Encoding, with a replacement fallback, so an invalid byte shows as U+FFFD instead of failing the read. Then remove the encoding gate from PgReadBinaryFileCapability.ProbeSql.
Until then
#4051 tells the operator the truth on these encodings. Take a 22021 or a 22P05 on a log-tail read. The fault message says that granting pg_read_binary_file does not help on this database encoding, and it points here. The runbook and Darling/README.md say the same.
Follow-up from the round-2 security review of #4051 (finding L-1): #4051 (comment)
Problem
A failed login can plant one invalid byte in the PostgreSQL server log (#4046). The three log readers (
pg_log_events,pg_deadlocks,pg_plan_capture) read the log withpg_read_file, which returns text. On some database encodings, one planted byte fails the whole 4 MB tail read until the line leaves the window.#4051 adds a byte route: with
EXECUTEonpg_read_binary_file, the readers read the log as bytea and decode it as UTF-8. That route serves UTF8 and SQL_ASCII databases only. Decoding as UTF-8 is wrong for other encodings, because it turns the database's own non-ASCII text into U+FFFD.The text route is still blindable on some of those other encodings:
EUC_JP): PostgreSQL checks the text against the database encoding on read. An invalid multibyte sequence fails the read with SQLSTATE 22021.WIN1252: the bytes 0x81, 0x8D, 0x8F, 0x90 and 0x9D have no UTF-8 equivalent, so the conversion to the client's UTF8 fails with SQLSTATE 22P05.Single-byte encodings that map every byte, such as
LATIN1, are not affected. Every byte except NUL is valid text there, and every byte converts to UTF-8.Proposed fix
Let the byte route serve every server encoding. Decode the bytea in the connected database's own encoding (the value of
server_encoding) instead of always as UTF-8. Map each PostgreSQL encoding name to a .NETEncoding, with a replacement fallback, so an invalid byte shows as U+FFFD instead of failing the read. Then remove the encoding gate fromPgReadBinaryFileCapability.ProbeSql.Until then
#4051 tells the operator the truth on these encodings. Take a 22021 or a 22P05 on a log-tail read. The fault message says that granting
pg_read_binary_filedoes not help on this database encoding, and it points here. The runbook andDarling/README.mdsay the same.