Skip to content

[BUG] pthread_getspecific possibly called before pthread_key_create #1236

Closed
@denravonska

Description

@denravonska

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions