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

[spinel] check the frame buffer size before reading the next frame #10015

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

zhanglongxia
Copy link
Contributor

When the spinel rx multiple frame buffer is full, calling GetNextSavedFrame() may cause the code to access the area behind the multiple frame buffer.

This commit checks the received frame buffer size before reading the next frame to avoid accessing illegal area.

When the spinel rx multiple frame buffer is full, calling
`GetNextSavedFrame()` may cause the code to access the area
behind the multiple frame buffer.

This commit checks the received frame buffer size before reading the
next frame to avoid accessing illegal area.
@zhanglongxia
Copy link
Contributor Author

Here is the backtrace we got when this issue happens.

Stack Trace:
  RELADDR           FUNCTION                                                                                                                                                 FILE:LINE
         (inlined)  ot::LittleEndian::ReadUint16(unsigned char const*) (BuildId: 4449f9236dbeb90480f244a574482e73)                                                           external/openthread/src/core/common/encoding.hpp:307:83
         (inlined)  ot::Spinel::MultiFrameBuffer<(unsigned short)8192>::GetNextSavedFrame(unsigned char*&, unsigned short&) (BuildId: 4449f9236dbeb90480f244a574482e73)      external/openthread/src/lib/spinel/multi_frame_buffer.hpp:376:36
         (inlined)  ot::Spinel::RadioSpinel::ProcessFrameQueue() (BuildId: 4449f9236dbeb90480f244a574482e73)                                                                 external/openthread/src/lib/spinel/radio_spinel.cpp:860:27
  00000000001539c0  ot::Spinel::RadioSpinel::Process(void const*) (BuildId: 4449f9236dbeb90480f244a574482e73)                                                                external/openthread/src/lib/spinel/radio_spinel.cpp:943:9
  00000000001426ec  platformRadioProcess (BuildId: 4449f9236dbeb90480f244a574482e73)                                                                                         external/openthread/src/posix/platform/radio.cpp:460:22
  0000000000148adc  otSysMainloopProcess (BuildId: 4449f9236dbeb90480f244a574482e73)                                                                                         external/openthread/src/posix/platform/system.cpp:398:5
  000000000004d030  otbr::Ncp::ControllerOpenThread::Process(otSysMainloopContext const&) (BuildId: 4449f9236dbeb90480f244a574482e73)                                        external/ot-br-posix/src/ncp/ncp_openthread.cpp:328:5
  0000000000052824  otbr::MainloopManager::Process(otSysMainloopContext const&) (BuildId: 4449f9236dbeb90480f244a574482e73)                                                  external/ot-br-posix/src/common/mainloop_manager.cpp:57:28
  000000000003069c  otbr::Application::Run() (BuildId: 4449f9236dbeb90480f244a574482e73)                                                                                     external/ot-br-posix/src/agent/application.cpp:200:44
         (inlined)  realmain(int, char**) (BuildId: 4449f9236dbeb90480f244a574482e73)                                                                                        external/ot-br-posix/src/agent/main.cpp:301:19
  0000000000061264  main (BuildId: 4449f9236dbeb90480f244a574482e73)                                                                                                         external/ot-br-posix/src/agent/main.cpp:347:12
  000000000005f944  __libc_init (BuildId: 5f5ff93f925112aa256b1322cd657327)                                                                                                  bionic/libc/bionic/libc_init_dynamic.cpp:169:8
  0000000000030074  _start_main (BuildId: 4449f9236dbeb90480f244a574482e73)                                                                                                  bionic/libc/arch-common/bionic/crtbegin.c:81:3

Copy link

size-report bot commented Apr 10, 2024

Size Report of OpenThread

Merging #10015 into main(30aa3e8).

name branch text data bss total
ot-cli-ftd main 467208 856 66364 534428
#10015 467208 856 66364 534428
+/- 0 0 0 0
ot-ncp-ftd main 436108 760 61576 498444
#10015 436108 760 61576 498444
+/- 0 0 0 0
libopenthread-ftd.a main 236248 95 40310 276653
#10015 236248 95 40310 276653
+/- 0 0 0 0
libopenthread-cli-ftd.a main 57549 0 8075 65624
#10015 57549 0 8075 65624
+/- 0 0 0 0
libopenthread-ncp-ftd.a main 31857 0 5916 37773
#10015 31857 0 5916 37773
+/- 0 0 0 0
ot-cli-mtd main 364712 760 51220 416692
#10015 364712 760 51220 416692
+/- 0 0 0 0
ot-ncp-mtd main 347244 760 46448 394452
#10015 347244 760 46448 394452
+/- 0 0 0 0
libopenthread-mtd.a main 158327 0 25182 183509
#10015 158327 0 25182 183509
+/- 0 0 0 0
libopenthread-cli-mtd.a main 39787 0 8059 47846
#10015 39787 0 8059 47846
+/- 0 0 0 0
libopenthread-ncp-mtd.a main 24737 0 5916 30653
#10015 24737 0 5916 30653
+/- 0 0 0 0
ot-cli-ftd-br main 549824 864 131196 681884
#10015 549824 864 131196 681884
+/- 0 0 0 0
libopenthread-ftd-br.a main 322995 100 105118 428213
#10015 322995 100 105118 428213
+/- 0 0 0 0
libopenthread-cli-ftd-br.a main 71212 0 8099 79311
#10015 71212 0 8099 79311
+/- 0 0 0 0
ot-rcp main 62248 564 20604 83416
#10015 62248 564 20604 83416
+/- 0 0 0 0
libopenthread-rcp.a main 9542 0 5052 14594
#10015 9542 0 5052 14594
+/- 0 0 0 0
libopenthread-radio.a main 18870 0 214 19084
#10015 18870 0 214 19084
+/- 0 0 0 0

@@ -371,7 +371,7 @@ template <uint16_t kSize> class MultiFrameBuffer : public FrameWritePointer

aFrame = (aFrame == nullptr) ? mBuffer : aFrame + aLength;

if (HasSavedFrame() && (aFrame != mWriteFrameStart))
if (HasSavedFrame() && (aFrame != mWriteFrameStart) && ((aFrame + kHeaderSize) < GetArrayEnd(mBuffer)))
Copy link
Member

Choose a reason for hiding this comment

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

Why will there be an incomplete frame while HasSavedFrame() is true? Should we avoid saving incomplete frame?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The function GetNextSavedFrame ()only iterate frames in the multi-frame-buffer. All frames are still be saved in the multi-frame-buffer when calling GetNextSavedFrame(), so the function HasSavedFrame () does the right job here.

@@ -371,7 +371,7 @@ template <uint16_t kSize> class MultiFrameBuffer : public FrameWritePointer

aFrame = (aFrame == nullptr) ? mBuffer : aFrame + aLength;

if (HasSavedFrame() && (aFrame != mWriteFrameStart))
if (HasSavedFrame() && (aFrame != mWriteFrameStart) && ((aFrame + kHeaderSize) < GetArrayEnd(mBuffer)))
Copy link
Member

Choose a reason for hiding this comment

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

@zhanglongxia can you please share how we may get into bad state where we would need the ((aFrame + kHeaderSize) < GetArrayEnd(mBuffer)).

I tried to check the code, but cannot see how this can happen.

In SaveFrame() we have a check which makes sure we have bytes left for the next frame header, otherwise we fail (not save the frame and not change mWriteFrameStart).

    otError SaveFrame(void)
    {
        otError error = OT_ERROR_NONE;

        // If the next header will overflow the buffer, we can't save the frame.
        if (!CanWrite(kHeaderSize))
        {
            error = OT_ERROR_NO_BUFS;
        }
        else
        {
            LittleEndian::WriteUint16(GetSkipLength() + GetLength(), mWriteFrameStart + kHeaderTotalLengthOffset);
            mWriteFrameStart = mWritePointer;
            IgnoreError(SetSkipLength(0));
        }

        return error;
    }

So we should always have at least kHeaderSize remaining in buffer after mWriteFrameStart?

Copy link
Member

Choose a reason for hiding this comment

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

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.

None yet

3 participants