-
Notifications
You must be signed in to change notification settings - Fork 2k
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
nanocoap: fix server-side option_count overflow #10754
Conversation
Just took a first look. The fix looks appropriate. Need to do a little more testing. In the unit test, how do I know that the printed pointer values indicate a good test? Just that they are close to each other? Is it possible to be more specific? It's odd to print values as part of a unit test. I would think it makes more sense to compare the values within the test, and fail the test if the difference is outside of some range. |
When I wrote the test, I wasn't sure that it would (without the fix) crash. Does this make sense at all or does anyone have a better idea on how to detect an overflow of the options array? |
Sorry, I have no insights. In keeping with the current approach, you could put a guard value on both sides to be safe. Another approach is to set the maximum number of options (NANOCOAP_NOPTS_MAX) to a small value and try a functional test. That's what I'm working on. |
You also could craft an array with NANOCOAP_NOPTS_MAX options, parse it, and expect success. Then add another option to it and expect -ENOMEM. That should be sufficient for this test. No need to get into the low level overflow detection. |
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.
Need to fix option count comparison.
@@ -111,6 +111,9 @@ int coap_parse(coap_pkt_t *pkt, uint8_t *buf, size_t len) | |||
DEBUG("optpos option_nr=%u %u\n", (unsigned)option_nr, (unsigned)optpos->offset); | |||
optpos++; | |||
option_count++; | |||
if (option_count >= NANOCOAP_NOPTS_MAX) { |
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.
It should be OK to include NANOCOAP_NOPTS_MAX options. This test should be moved above addition to the array, probably line 109. The test then should be:
if (option_count == NANOCOAP_NOPTS_MAX) {
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.
Yes. The new test seems to be working, it exposed that using "==" here caused to write one behind the options array. So I moved the check to the beginning of the if case.
I think I found a way. At least on native it works as expected. |
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 agree the verification in coap_parse() is in the right place now. See my suggested alternative unit test in kapar030/#41. We're getting closer...
@@ -433,6 +434,40 @@ static void test_nanocoap__server_reply_simple_con(void) | |||
TEST_ASSERT_EQUAL_INT(COAP_TYPE_ACK, coap_get_type(&pkt)); | |||
} | |||
|
|||
static void test_nanocoap__server_option_count_overflow_check(void) |
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 kind of understand what you are doing to test the overflow. Why are there 42 options in guard data? How does the unit test work? I think it's important for others to understand this without a lot of thought/investigation.
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've added some comments.
I have cherry-picked the commit. IMO more test code doesn't hurt, even if they test the same thing. |
I agree it's OK to include both tests since they verify from different directions. These tests run OK for me on native and samr21-xpro. I verified that allowing coap_parse() to write an extra option makes the tests fail. Thanks for adding the comments in the test. The only remaining question for me is why are there 42 options in guard_data instead of only one or two. When I allowed the parse to overwrite the guard data, I found the overwrite occurred in the first few bytes. |
@nmeum provided this packet in his original report, and I was lazy enough to take it as-is. The number just needs to be higher than |
OK, good enough. ACK, please squash. |
8b86050
to
1058a8d
Compare
Thanks @kb2ma! |
@kaspar030 could you provide a backport to the 2018.10 branch? |
Contribution description
nanocoap limits the number of options it parses, but didn't check if that limit was reached when parsing a packet. (See report in #10753).
This PR provides a fix. It also adds a unittest that exposes the flaw.
Fixes #10753.
Testing procedure
Run unittests without uppermost commit. The nanocoap test should crash on native. Run again with topmost commit. Tests should succeed.
Issues/PRs references
See #10753.