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

Fix CRMP resend null out retained buffer #7312

Merged
merged 3 commits into from
Jun 16, 2021

Conversation

kghost
Copy link
Contributor

@kghost kghost commented Jun 2, 2021

Problem

There is a bug that resend message will null out CRMP retained buffer. Due to this line:

dispatcher->ResendMessage(rc->GetExchangeContext()->GetSecureSession(), std::move(entry->retainedBuf), &entry->retainedBuf)

The code is a little strange, hard to understand, and error-prone.

Change overview

The PR split send message into 2 steps:

  1. PrepareMessage: create a message buffer which can be send multiple times without changing.
  2. SendPreparedMessage: send the prepared message, this function is re-entrance.

Then SendMessage becomes:

EncryptedPacketBufferHandle preparedMessage;
ReturnErrorOnFailure(PrepareMessage(session, payloadHeader, std::move(message), preparedMessage));
ReturnErrorOnFailure(SendPreparedMessage(session, preparedMessage));

ResendMessage becomes:

ReturnErrorOnFailure(SendPreparedMessage(session, preparedMessage));

This makes all things clear and easy to understand.

Testing

Manually tested with echo and im

* 3. Encode the packet header and prepend it to message.
* Returns a prepared message in preparedMessage.
*/
CHIP_ERROR PrepareMessage(SecureSessionHandle session, PayloadHeader & payloadHeader, System::PacketBufferHandle && msgBuf,
Copy link
Contributor

Choose a reason for hiding this comment

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

The way I understand it, the method takes a buffer of data and encrypts its + adds the packet header. I find "prepare" a bit vague and it forces me to read through the comments to understand what the method does.

Is it correct that this is the one way we expect to convert a packet handle to an encrypted one? How about in this case:

EncryptPayload or BuildEncryptedMessagePayload

and

SendEncryptedPayload ?

This way I do not read comments, I understand that giving a buffer, I encrypt it and send it.

Copy link
Contributor Author

@kghost kghost Jun 2, 2021

Choose a reason for hiding this comment

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

This API is also handling unsecure message in SessionEstablishmentExchangeDispatch.cpp, So it is not proper to name it BuildEncryptedMessagePayload

And BuildMessagePayload is also a bit strange.

Copy link
Contributor

Choose a reason for hiding this comment

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

The prepared steps in the comment say "it encrypts the msgBuf".
I am trying to find out if we can get a more descriptive name than "Prepare". From what I see this is that this has:

  • Input: session, header, messagebuffer
  • Output: EncryptedMessageBuffer

Which tells me it encrypts and adds a header. Realistically also wondering why we take a sessionhandle instead of just keys if we do encryption, but that is not for this PR.

Could you either update the comment about encryption or find some descriptive name (or both)?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think missing "override" made me not realize this particular implementation does "encrypt" but others may not. Please add override keyword here and below as needed and then I think the name is ok.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, this particular impl always encrypts. The message dispatch bits can keep Prepare(), etc, but we could name this API something different and clearer.

Copy link
Contributor

@andy31415 andy31415 left a comment

Choose a reason for hiding this comment

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

The summary states that manual testing was done and I was about to comment about 'can we also have automated tests please?' However I also see test cases modified, so the code is exercised in unit tests as well.

Could we update the unit tests to be able to detect the bug to make sure it never happens again?

@kghost
Copy link
Contributor Author

kghost commented Jun 2, 2021

Could we update the unit tests to be able to detect the bug to make sure it never happens again?

The logic causing the problem no longer exists, SendPreparedMessage now takes a const PacketHandle, it is unable to modify it. So it is not possible to write a unit test to detect it.

@github-actions
Copy link

github-actions bot commented Jun 2, 2021

Size increase report for "gn_qpg6100-example-build" from f6af7b9

File Section File VM
chip-qpg6100-lighting-example.out .text -176 -176
Full report output
BLOAT REPORT

Files found only in the build output:
    report.csv

Comparing ./master_artifact/chip-qpg6100-lighting-example.out.map and ./pull_artifact/chip-qpg6100-lighting-example.out.map:

BLOAT EXECUTION FAILED WITH CODE 1:
bloaty: unknown file type for file './pull_artifact/chip-qpg6100-lighting-example.out.map'

Comparing ./master_artifact/chip-qpg6100-lighting-example.out and ./pull_artifact/chip-qpg6100-lighting-example.out:

sections,vmsize,filesize
[Unmapped],0,176
.debug_aranges,0,-24
.symtab,0,-80
.debug_frame,0,-92
.debug_abbrev,0,-113
.text,-176,-176
.strtab,0,-188
.debug_str,0,-289
.debug_ranges,0,-368
.debug_line,0,-426
.debug_loc,0,-876
.debug_info,0,-1512


if (state == nullptr)
{
return CHIP_ERROR_NOT_CONNECTED;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: ";" not needed here

src/messaging/ExchangeMessageDispatch.cpp Outdated Show resolved Hide resolved
src/messaging/ExchangeMessageDispatch.cpp Outdated Show resolved Hide resolved
src/messaging/ExchangeMessageDispatch.h Show resolved Hide resolved
@@ -68,6 +68,8 @@ class EncryptedPacketBufferHandle final : private System::PacketBufferHandle

uint32_t GetMsgId() const;

PacketBufferHandle Retain() const { return PacketBufferHandle::Retain(); }
Copy link
Contributor

Choose a reason for hiding this comment

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

This is violating the main invariant of this class, which is that you have to call CastToWritable to be able to modify it.

There are two options here:

  1. We make CastToWritable callable on an lvalue and have it do a Retain() internally: PacketBufferHandle CastToWritable() { return PacketBufferHandle::Retain(); }
  2. We add a Retain that returns EncryptedPacketBufferHandle: EncryptedPacketBufferHandle Retain() { return EncryptedPacketBufferHandle(PacketBufferHandle::Retain()); } and then we CastToWritable that thing that Retain returns.

src/transport/SecureSessionMgr.h Outdated Show resolved Hide resolved
* 3. Encode the packet header and prepend it to message.
* Returns a prepared message in preparedMessage.
*/
CHIP_ERROR PrepareMessage(SecureSessionHandle session, PayloadHeader & payloadHeader, System::PacketBufferHandle && msgBuf,
Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, this particular impl always encrypts. The message dispatch bits can keep Prepare(), etc, but we could name this API something different and clearer.

@github-actions
Copy link

github-actions bot commented Jun 4, 2021

Size increase report for "nrfconnect-example-build" from 7d54157

File Section File VM
chip-lock.elf device_handles -4 -4
chip-lock.elf rodata -24 -24
chip-lock.elf text -204 -204
chip-shell.elf text -64 -64
Full report output
BLOAT REPORT

Files found only in the build output:
    report.csv

Comparing ./master_artifact/chip-lock.elf and ./pull_artifact/chip-lock.elf:

sections,vmsize,filesize
.debug_str,0,8555
.debug_info,0,3431
.debug_loc,0,57
.shstrtab,0,2
device_handles,-4,-4
.debug_aranges,0,-24
rodata,-24,-24
.debug_frame,0,-92
.symtab,0,-96
.strtab,0,-174
text,-204,-204
.debug_line,0,-219
.debug_ranges,0,-368
.debug_abbrev,0,-820

Comparing ./master_artifact/chip-shell.elf and ./pull_artifact/chip-shell.elf:

sections,vmsize,filesize
.debug_str,0,8795
.debug_info,0,5588
.debug_loc,0,953
.debug_abbrev,0,249
.debug_line,0,143
.shstrtab,0,1
.debug_aranges,0,-16
.symtab,0,-32
.debug_frame,0,-64
text,-64,-64
.debug_ranges,0,-144
.strtab,0,-177


@github-actions
Copy link

github-actions bot commented Jun 4, 2021

Size increase report for "esp32-example-build" from 7d54157

File Section File VM
chip-all-clusters-app.elf .flash.rodata -24 -24
chip-all-clusters-app.elf .flash.text -232 -232
Full report output
BLOAT REPORT

Files found only in the build output:
    report.csv

Comparing ./master_artifact/chip-pigweed-app.elf and ./pull_artifact/chip-pigweed-app.elf:

sections,vmsize,filesize

Comparing ./master_artifact/chip-all-clusters-app.elf and ./pull_artifact/chip-all-clusters-app.elf:

sections,vmsize,filesize
.debug_str,0,8301
.debug_info,0,3001
.xt.prop._ZNK4chip36SessionEstablishmentExchangeDispatch29IsReliableTransmissionAllowedEv,0,76
.xt.prop._ZNK4chip9Messaging23ExchangeMessageDispatch29IsReliableTransmissionAllowedEv,0,76
[Unmapped],0,24
.shstrtab,0,2
.debug_aranges,0,-24
.flash.rodata,-24,-24
.symtab,0,-32
.debug_frame,0,-72
.xt.prop._ZN4chip36SessionEstablishmentExchangeDispatch29IsReliableTransmissionAllowedEv,0,-76
.xt.prop._ZN4chip9Messaging23ExchangeMessageDispatch29IsReliableTransmissionAllowedEv,0,-76
.strtab,0,-174
.debug_ranges,0,-176
.flash.text,-232,-232
.debug_loc,0,-467
.debug_line,0,-477
.debug_abbrev,0,-1158


@woody-apple
Copy link
Contributor

/rebase

@kghost
Copy link
Contributor Author

kghost commented Jun 10, 2021

@bzbarsky-apple I have upated a new patch to resolve your suggestion, please take a look

Copy link
Contributor

@bzbarsky-apple bzbarsky-apple left a comment

Choose a reason for hiding this comment

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

My apologies for the lag; I missed the comments being addressed. Thank you for the direct ping!

src/transport/SecureSessionMgr.h Outdated Show resolved Hide resolved
src/transport/SecureSessionMgr.h Outdated Show resolved Hide resolved
@woody-apple
Copy link
Contributor

/rebase

@woody-apple
Copy link
Contributor

@saurabhst @msandstedt @andy31415 ?

@woody-apple woody-apple merged commit 23d3a6d into project-chip:master Jun 16, 2021
@kghost kghost deleted the fix-rref branch June 16, 2021 16:55
nikita-s-wrk pushed a commit to nikita-s-wrk/connectedhomeip that referenced this pull request Sep 23, 2021
* Fix CRMP resend null out retained buffer

* Resolve comments

* Apply suggestions from code review

Co-authored-by: Boris Zbarsky <[email protected]>

Co-authored-by: Boris Zbarsky <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants