-
Notifications
You must be signed in to change notification settings - Fork 160
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
Fixed HBH ext parse panic when start >= end #3674
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.
Reviewed 1 of 1 files at r1.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @AlexanderKunze and @sgmonroy)
a discussion (no related file):
Btw. looking at this parseHopExtns
, I had the impression that there might be another lurking bug; I can't see a check that actually ensures that the packet data has even one more line before attempting to read next extension headers; in the following lines, access to rp.Raw
at indices > *offset
appear to be unchecked.
Lines 121 to 122 in 82be069
currExtn := common.ExtnType{Class: currHdr, Type: rp.Raw[*offset+2]} | |
hdrLen := int(rp.Raw[*offset+1]) * common.LineLen |
I think if it somehow possible to create a packet that ends on an extension saying that NextHdr
will be another hop-by-hop extension, this would also panic.
go/border/rpkt/extns.go, line 44 at r1 (raw file):
func (rp *RtrPkt) extnParseHBH(extType common.ExtnType, start, end, pos int) (rExtension, error) { if end-start <= common.LineLen {
Shouldn't this only error if the length is strictly smaller than linelen?
Looking at both callers and callees of this function, it appears that start is already offset by ExtnSubHdrLen
.
Putting this together, the check here should be: if end-start < common.LineLen - common.ExtnSubHdrLen
.
To avoid this dance with adding/subtracting the ExtnSubHdrLen, I'd propose to move the check to parseHopExtns
, as you suggested yourself.
There, you could do the check directly on the packet ExtHdrLen
field of the packet, only checking that it's > 0
.
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.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @matzf)
go/border/rpkt/extns.go, line 44 at r1 (raw file):
Previously, matzf (Matthias Frei) wrote…
Shouldn't this only error if the length is strictly smaller than linelen?
Looking at both callers and callees of this function, it appears that start is already offset byExtnSubHdrLen
.
Putting this together, the check here should be:if end-start < common.LineLen - common.ExtnSubHdrLen
.To avoid this dance with adding/subtracting the ExtnSubHdrLen, I'd propose to move the check to
parseHopExtns
, as you suggested yourself.
There, you could do the check directly on the packetExtHdrLen
field of the packet, only checking that it's> 0
.
Agreed. Even if you leave this check here for safety, although it could just be an assert as this is BR specific, there should be checks in parseHopExtns
given that you already access the packet data in that function.
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.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @matzf)
Thank you @sgmonroy and @matzf for those excellent and extensive comments. I have made changes and issued a new commit. The changes are as follows:
Please let me know any other feedback you have or if I've misunderstood something, made a mistake, or if there is something else I can do. |
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.
Reviewed 2 of 2 files at r2.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @AlexanderKunze and @matzf)
go/border/rpkt/parse.go, line 128 at r2 (raw file):
start := *offset + common.ExtnSubHdrLen end := *offset + hdrLen if start >= end {
you should also check in this function that end < len(rp.Raw)
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.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @AlexanderKunze and @sgmonroy)
go/border/rpkt/extns.go, line 44 at r1 (raw file):
Previously, sgmonroy (Sergio Gonzalez Monroy) wrote…
Agreed. Even if you leave this check here for safety, although it could just be an assert as this is BR specific, there should be checks in
parseHopExtns
given that you already access the packet data in that function.
Now the check in the assert still needs to take into account that start
is already offset by ExtnSubHdrLen
:
assert.Must(end-start + common.ExtnSubHdrLen >= common.LineLen , "Extension must be at least one line length")
Hi and thanks for the comments once again. Sorry it took so long to make these changes. I have issued the commit. Let me know if there's something else I can do. |
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.
Reviewed 2 of 2 files at r3.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @AlexanderKunze)
go/border/rpkt/parse.go, line 128 at r2 (raw file):
Previously, sgmonroy (Sergio Gonzalez Monroy) wrote…
you should also check in this function that
end < len(rp.Raw)
I saw that acceptance tests are failing. Indeed, we do support having an extension without any other layer afterwards, meaning the check should be end > len(rp.Raw)
Thanks for the correction, adjusted it accordingly. |
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.
Reviewed 1 of 2 files at r3, 1 of 1 files at r5.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @AlexanderKunze)
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.
Reviewable status: complete! all files reviewed, all discussions resolved
Squashed additional commits
The router could crash if a packet arrived with data resulting in the function
go/border/rpkt/extn_scmp.go/rSCMPExtFromRaw(...)
receiving astart >= end
, which would panic on line 38.The error is caused by
go/border/rpkt/parse.go/rp.parseHopExtns()
callingrp.extnParseHBH(...)
on line 123, which then callsrSCMPExtFromRaw(...)
with no checks forstart
orend
.I decided to add an error check in
rp.extnParseHBH(...)
instead of where the panic happens (rSCMPExtFromRaw(...)
), because a header of invalid offset or length should fail, even whenstart
orend
are not read, such as inrOneHopPathFromRaw
.The problem might also be fixed earlier, in
rp.parseHopExtns()
, where the erroneous values are actually read in. However, I was unsure if this is better and so left the error catching inrp.extnParseHBH(...)
I also chose to use as an error check that the total length of the extension must be greater than
common.LineLen
, since an extension of any less size should not be valid anyway.For reference: The packet that caused the panic was:
00c10067070405000001ff00000001110001ff000000011080007f00000b0000857b3362e3400140003f0000014152c1000000000000000000000000000000001101010000000000792c000000271f920000001b10084002110582510801027f10065002020102
This change is