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
http2_client: fix reader segfault on PROTOCOL_ERRORs #3926
Conversation
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the patch! One minor comment.
msg := "" | ||
if errorDetail != nil { | ||
msg = errorDetail.Error() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some text to msg
when errorDetail
is nil
.
} else {
msg = "unknown framer error" // ??
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was unsure what comment is appropriate when errorDetail is unavailable...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds fine to me.
http2.Framer ErrorDetail() might return nil even in case of http2.StreamError, as documented.
275719c
to
c8eec21
Compare
msg := "" | ||
if errorDetail != nil { | ||
msg = errorDetail.Error() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds fine to me.
Thanks again! |
http2.Framer ErrorDetail() might return nil even in case of http2.StreamError, as documented.
(Note: This problem was initially reported to grpc-security@ just in case, but they assessed this segfault isn't a security issue.)
What did you do?
Wrote a gRPC server may send an invalid HEADERS frame to a gRPC client process written with grpc-go. The frame is set length to 0. https://img.sorah.jp/x/20200917_185642_kdwgHWb8KG.png
(a server is written using our original protocol implementation, which is I'm maintaining and sending an invalid HEADERS frame is a different bug. Found during investigation of server process crash)
What did you expect to see?
HTTP/2 session would properly shut down with PROTOCOL_ERROR.
What did you see instead?
a client process would crash with SEGV (segmentation fault).
This happens because http2.Framer#ErrorDetail() returned nil (it may return, as documented):
grpc-go/internal/transport/http2_client.go
Line 1309 in 4270c3c
It might return nil even in case of StreamError.
For instance, when a server sent an invalid HEADERS frame where a length is zero, http2.Framer#ReadFrame returns an StreamError
without setting http2.Framer#lastError (which is a struct field back of ErrorDetail).
https://github.com/golang/net/blob/62affa334b73ec65ed44a326519ac12c421905e3/http2/frame.go#L1022
Due to this crash existing in http2Client Reader goroutine, this is unavoidable and a process would result in a segmentation fault.
This bug seems to be introduced at commit 40a879c which changed to call Error() of a return value of ErrorDetail().