Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

postgres: validate message syntax before parsing #16575

Merged
merged 15 commits into from
Jun 18, 2021

Conversation

cpakulski
Copy link
Contributor

Commit Message:
Validate postgres messages before parsing.

Additional Description:
Introduced InSync and OutOfSync states in decoder. When decoder detects a wrongly formatted message, it stops parsing and moves to OutOfSync state. Continuing parsing after encountering message with wrong syntax may lead to interpreting random bytes as length of the message and possibly causing OOM.

Risk Level: Low
Testing: Added unit tests and run full regression tests.
Docs Changes: No.
Release Notes: No.
Platform Specific Features:
Fixes #12340

Signed-off-by: Christoph Pakulski <[email protected]>
@cpakulski cpakulski requested review from lizan and dio May 19, 2021 19:14
@cpakulski cpakulski marked this pull request as ready for review May 19, 2021 19:15
std::string message_;
uint32_t message_len_{};

static const std::string FRONTEND;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static const string (non-POD) is source of flaky test, use singleton (CONSTRUCT_ON_FIRST_USE) or constexpr string_view.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converted to constexpr string_view. Thanks!

…inmutable strings

used for logging.

Signed-off-by: Christoph Pakulski <[email protected]>
@cpakulski
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #16575 (comment) was created by @cpakulski.

see: more, trace.

@zuercher
Copy link
Member

zuercher commented Jun 7, 2021

cc @fabriziomello could have a look as an extension owner?

message_len_ = data.peekBEInt<uint32_t>(0);
// MAX_STARTUP_PACKET_LENGTH is defined in Postgres source code
// as maximum size of initial packet.
#define MAX_STARTUP_PACKET_LENGTH 10000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps move it to postgres_decoder.h and add the following link to comments: https://github.com/postgres/postgres/search?q=MAX_STARTUP_PACKET_LENGTH&type=code


// The minimum size of the message sufficient for parsing is 5 bytes.
if (data.length() < 5) {
if (data.length() < 4) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about create something like #define MIN_MESSAGE_LENGTH 4 ? And seems the comment above is not in sync what code does...

encrypted_ = true;
// Handler for SSLRequest (Int32(80877103) = 0x04d2162f)
// See details in https://www.postgresql.org/docs/current/protocol-message-formats.html.
if (code == 0x04d2162f) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both lines 249 and 253 use SSLRequest codes... for code legibility what about add some macros?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO macro will make it more difficult to read and will not add any value. The meaning of this value is documented pretty clearly here.

data.drain(data.length());
return encrypted_ ? Decoder::ReadyForNext : Decoder::Stopped;
Decoder::Result result = Decoder::Result::ReadyForNext;
uint32_t code = data.peekBEInt<uint32_t>(4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename code to startup_packet just to use the Postgres vocabulary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but this is not really a packet itself, but just 4-bytes code which can be either a version or encryption type.

@fabriziomello
Copy link
Contributor

cc @fabriziomello could have a look as an extension owner?

Thanks for remember me ... did some minor comments. Me and @cpakulski already discussed a bit about this in PVT before he send the PR. Mostly about MAX_STARTUP_PACKET_LENGTH because we decided implement it the same way Postgres does.

Signed-off-by: Christoph Pakulski <[email protected]>
@fabriziomello
Copy link
Contributor

@cpakulski the Postgres Regression using your last commit 60b5585 worked but seems our current pipeline doesn't like it so much.

@cpakulski
Copy link
Contributor Author

@fabriziomello Would you mind running Postgres Regression test on the latest commit? Thanks.

@fabriziomello
Copy link
Contributor

@fabriziomello Would you mind running Postgres Regression test on the latest commit? Thanks.

I did it when I saw your new commit and it ran without any issue: https://github.com/fabriziomello/envoy-postgres-regression/actions/runs/940000625

@fabriziomello
Copy link
Contributor

/LGTM

@cpakulski
Copy link
Contributor Author

@lizan How can we move this PR forward? All regression tests have passed.
If there are no style comments, it is ready for merge. Thanks!

@lizan lizan merged commit 4533ea1 into envoyproxy:main Jun 18, 2021
leyao-daily pushed a commit to leyao-daily/envoy that referenced this pull request Sep 30, 2021
Commit Message:
Validate postgres messages before parsing.

Additional Description:
Introduced InSync and OutOfSync states in decoder. When decoder detects a wrongly formatted message, it stops parsing and moves to OutOfSync state. Continuing parsing after encountering message with wrong syntax may lead to interpreting random bytes as length of the message and possibly causing OOM.

Risk Level: Low
Testing: Added unit tests and run full regression tests.
Docs Changes: No.
Release Notes: No.
Platform Specific Features:
Fixes envoyproxy#12340 

Signed-off-by: Christoph Pakulski <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[postgres_proxy] assert failure with untrusted buffer when onData()
5 participants