admin: Fix crashes on invalid FieldMasks#16979
Conversation
Signed-off-by: Paul Gallagher <pgal@google.com>
|
Heh, /quitquitquit should exit cleanly and not "crash" :) Anyway I'll take a look at this. |
jmarantz
left a comment
There was a problem hiding this comment.
At a high level this looks good, with a couple of small issues and one question.
Would it make sense to do the exception trapping in config_dump_Handler.cc -- just wrap the try around addAllConfigDump? I think that might be consistent with the way we filter bad regexes in the /stats handler, but I'll leave it to you to check :)
| // trimResourceMessage will LOG(FATAL) if `field_mask` is malformed. | ||
| TRY_ASSERT_MAIN_THREAD { trimResourceMessage(field_mask, msg); } | ||
| END_TRY | ||
| catch (...) { |
There was a problem hiding this comment.
can you just catch a specific exception here? Looking at source/common/protobuf/utility.cc; I think you can use EnvoyException, which is the usual pattern.
Then you can also give the text from the exception (e.what() I think).
There was a problem hiding this comment.
Actually, it seems as though this isn't an EnvoyException but instead a std::exception, and calling e.what() just returns "std::exception", which isn't particularly helpful.
There was a problem hiding this comment.
Can you debug who is throwing this std::exception?
In theory no one in Envoy should be throwing an exception that is not derived from EnvoyException. However, if this comes from the STL then that won't be true.
There was a problem hiding this comment.
Can we see what's going on up stack and make it not call LOG(FATAL)?
There was a problem hiding this comment.
Can you use this utility inside trimResourceMessage after the unpack?
There was a problem hiding this comment.
I meant protobuf. Thanks.
There was a problem hiding this comment.
Unfortunately I don't think so; all messages are dynamically constructed from DynamicMessageFactory inside trimResourceMessage, and IsValidFieldMask is templated and requires compile-time knowledge of the proto type, e.g. IsValidFieldMask<Cluster>(mask).
There was a problem hiding this comment.
Is there anything we can do to pre-validate the field_mask to avoid crashing in protobuf? Catching the throw that emanates from a LOG(FATAL) seems non-robust.
There was a problem hiding this comment.
I added a method which essentially does the same thing as IsValidFieldMask but doesn't require compile-time knowledge of types. LMK if this works for you!
| ProtobufUtil::FieldMaskUtil::TrimMessage(field_mask, message.get()); | ||
| } | ||
| END_TRY | ||
| catch (...) { |
| header_map, response)); | ||
| EXPECT_EQ("FieldMask paths: \"cluster.transport_socket_matches.name\"\n could not be " | ||
| "successfully used.", | ||
| response.toString()); |
There was a problem hiding this comment.
can you also make sure that headerMap.ContentTtype == "text/plain" here? If that was somehow 'text/html' then the error message could contain an XSS.
I think there's a ContentTypeValues.XXX value for that.
| getCallback("/config_dump?mask=bootstrap.node.extensions.name", header_map, response)); | ||
| EXPECT_EQ("FieldMask paths: \"bootstrap.node.extensions.name\"\n could not be " | ||
| "successfully used.", | ||
| response.toString()); |
There was a problem hiding this comment.
ditto: check for content-type: text/plain
Signed-off-by: Paul Gallagher <pgal@google.com>
Signed-off-by: Paul Gallagher <pgal@google.com>
| addAllConfigToDump(dump, mask, include_eds); | ||
| auto err = addAllConfigToDump(dump, mask, include_eds); | ||
| if (err.has_value()) { | ||
| response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Text); |
There was a problem hiding this comment.
sorry can you also add
response_headers.addReference(
Http::Headers::get().XContentTypeOptions,
Http::Headers::get().XContentTypeOptionValues.Nosniff);
Just a little paranoia to make sure browsers don't flip into HTML mode if some text looks like HTML. Just a bit of paranoia based on past browser behavior :)
Signed-off-by: Paul Gallagher <pgal@google.com>
jmarantz
left a comment
There was a problem hiding this comment.
basically LGTM with a few minor nits you can take care of, but I'll turn it over to senior maintainers. Thanks for doing this!
/assign-from @envoyproxy/senior-maintainers
|
@envoyproxy/senior-maintainers assignee is @zuercher |
Signed-off-by: Paul Gallagher <pgal@google.com>
zuercher
left a comment
There was a problem hiding this comment.
I think this looks good, modulo one nit and the clang-tidy errors. Those are
CheckFieldMaskAndTrimMessagevscheckFieldMaskAndTrimMessage- requiring braces around all control statements bodies (the if at line config_dump_handler.cc:110)
| // below. | ||
| // | ||
| // | ||
| // |
There was a problem hiding this comment.
nit: rm extra blank comment lines
Signed-off-by: Paul Gallagher <pgal@google.com>
When a field mask is invalid, TrimMessage will LOG(FATAL). Since explicitly checking validity of a field mask via FieldMaskUtil::IsValidFieldMask for a message requires compile-time knowledge of the message type, the best we can do is catch the exception thrown by TrimMessage and return an error. Risk Level: Low Testing: Unit tests. Docs Changes: None, this aligns actual behavior with documented behavior. Release Notes: n/a Signed-off-by: Paul Gallagher <pgal@google.com> Signed-off-by: chris.xin <xinchuantao@qq.com>
When a field mask is invalid, TrimMessage will LOG(FATAL). Since explicitly checking validity of a field mask via FieldMaskUtil::IsValidFieldMask for a message requires compile-time knowledge of the message type, the best we can do is catch the exception thrown by TrimMessage and return an error. Risk Level: Low Testing: Unit tests. Docs Changes: None, this aligns actual behavior with documented behavior. Release Notes: n/a Signed-off-by: Paul Gallagher <pgal@google.com>
Signed-off-by: Paul Gallagher pgal@google.com
Note: Though this is an unexpected crash, this change does not require the security process, as the admin interface already has documented methods of triggering a crash (
/quitquitquit), and should always be protected anyway.Commit Message: admin: Fix crashes on invalid FieldMasks
Additional Description: When a field mask is invalid, TrimMessage will LOG(FATAL). Since explicitly checking validity of a field mask via FieldMaskUtil::IsValidFieldMask for a message requires compile-time knowledge of the message type, the best we can do is catch the exception thrown by TrimMessage and return an error.
Risk Level: Low
Testing: Unit tests.
Docs Changes: None, this aligns actual behavior with documented behavior.