Skip to content

[BUG] pthread_getspecific possibly called before pthread_key_create #1236

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

Closed
denravonska opened this issue Feb 4, 2025 · 5 comments
Closed
Assignees
Labels
bug Something isn't working

Comments

@denravonska
Copy link

Describe the bug
!1223 introduced a way to mark threads as FreeRTOS threads. This works fine on 3 of our 4 development stations (3 local stations and one CI) but once one of our developer updated the code base he started experiencing crashes in the tests, see additional context.

The lines in question, port.c:169, looks harmless:

    pucThreadData = ( uint8_t * ) pthread_getspecific( xThreadKey );
    if( ( pucThreadData != NULL ) && ( *pucThreadData == 1 ) )        <------

The only reason that dereference can fail is if the returned pointer is not-NULL and points to invalid memory. The only way this can happen is if passing a key that has not been obtained from pthread_key_create

If we add a call to prvInitThreadKey() in prvIsFreeRTOSThread() before the key is retrieved the crashes stopped, which leads me to believe that the malloc path enters prvIsFreeRTOSThread() before any call to the key creation. I haven't verified this as I have no way of reproducing it.

The effect of calling pthread_getspecific() or pthread_setspecific() with a key value not obtained from pthread_key_create() or after key has been deleted with pthread_key_delete() is undefined.

See the pthread_getspecific and pthread_key_create man pages. In particular the thread_key_create one which uses pthread_once rather than manual tracking to construct the key only once

Target

  • Development board: CC1354P10
  • Instruction Set Architecture: ARMv8-M
  • IDE and version: VS Code 1.96.4
  • Toolchain and version: arm-none-eabi-gcc & arm-none-eabi-g++ 14.2.Rel1

Host
Works on:

  • Ubuntu 24.04.1 LTS (gcc-13.3.0)
  • Up to date ArchLinux (gcc-13.3.1 and gcc-14.2.1)

Crashes on:

  • Mint 21.3 (gcc-13.1.0)

To Reproduce
Not 100% sure but my hypothesis is to create a task (not static) with heap4 from main.

Additional context

./__Core_test_exe.out 
=================================================================
==353028==ERROR: AddressSanitizer: unknown-crash on address 0x7ecec379c000 at pc 0x56d43e594873 bp 0x7ffcabee0440 sp 0x7ffcabee0430
READ of size 1 at 0x7ecec379c000 thread T0
    #0 0x56d43e594872 in prvIsFreeRTOSThread ../app_sdk/third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c:169
    #1 0x56d43e5952b1 in vPortDisableInterrupts ../app_sdk/third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c:393
    #2 0x56d43e595303 in vPortEnterCritical ../app_sdk/third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c:347
    #3 0x56d43e584a3e in xTaskResumeAll ../app_sdk/third-party/freertos/repo/tasks.c:4023
    #4 0x56d43e5974be in pvPortMalloc ../app_sdk/third-party/freertos/repo/portable/MemMang/heap_4.c:334
    #5 0x56d43e5806d2 in prvCreateTask ../app_sdk/third-party/freertos/repo/tasks.c:1693
    #6 0x56d43e581181 in xTaskCreate ../app_sdk/third-party/freertos/repo/tasks.c:1753
    #7 0x56d43e537f9d in main ../app_sdk/test/src/main.cpp:26
    #8 0x7ecec2029d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #9 0x7ecec2029e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #10 0x56d43e4c07f4 in _start (/home/darwand/app-sdk/examples/blinky/out/__Core_test_exe.out+0x1957f4) (BuildId: a82ec7926be809b6f099b378cc4084e42674385a)

Address 0x7ecec379c000 is a wild pointer inside of access range of size 0x000000000001.
SUMMARY: AddressSanitizer: unknown-crash ../app_sdk/third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c:169 in prvIsFreeRTOSThread
Shadow bytes around the buggy address:
  0x7ecec379bd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ecec379be00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ecec379be80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ecec379bf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ecec379bf80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7ecec379c000:[fe]fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x7ecec379c080: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x7ecec379c100: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x7ecec379c180: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x7ecec379c200: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x7ecec379c280: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==353028==ABORTING
@denravonska denravonska added the bug Something isn't working label Feb 4, 2025
@denravonska
Copy link
Author

Double checked, prvMarkAsFreeRTOSThread is called twice, in my case, before the key is created in prvInitThreadKey.

Breakpoints at both locations.

(gdb) break prvInitThreadKey
Breakpoint 1 at 0x2546c4: file ../third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c, line 136.
(gdb) break prvMarkAsFreeRTOSThread
Breakpoint 2 at 0x254bc7: file ../third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c, line 149.

Run

(gdb) run
Starting program: /home/marco/dev/app-sdk/out/__Core_test_exe.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[New Thread 0x7ffff3bff6c0 (LWP 3525394)]
[New Thread 0x7ffff33fe6c0 (LWP 3525395)]
[Switching to Thread 0x7ffff3bff6c0 (LWP 3525394)]

Thread 2 "__Core_test_exe" hit Breakpoint 2, prvMarkAsFreeRTOSThread () at ../third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c:149
149	{
(gdb) c
Continuing.
[Switching to Thread 0x7ffff33fe6c0 (LWP 3525395)]

Thread 3 "__Core_test_exe" hit Breakpoint 2, prvMarkAsFreeRTOSThread () at ../third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c:149
149	{
(gdb) c
Continuing.
[New Thread 0x7ffff15eb6c0 (LWP 3525397)]
[Switching to Thread 0x7ffff3bff6c0 (LWP 3525394)]

Thread 2 "__Core_test_exe" hit Breakpoint 1, prvInitThreadKey () at ../third-party/freertos/repo/portable/ThirdParty/GCC/Posix/port.c:136
136	{

@kar-rahul-aws
Copy link
Member

Hi @denravonska
Can you please check this patch and see if it solves the issue?

issue_1236_udpated.patch

@denravonska
Copy link
Author

Hi @denravonska Can you please check this patch and see if it solves the issue?

issue_1236_udpated.patch

I was able to reproduce it in Docker using this Mint image and the patch seems to have fixed it.

@kar-rahul-aws
Copy link
Member

Thanks for confirming . I will raise a PR shortly to address the issue.

@kar-rahul-aws
Copy link
Member

The PR #1238 which addresses the issue has been verified and merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants