1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

sys/newlib_syscalls_default: fix race condition in __sinit()

This eagerly calls `__sinit()` instead of lazy initialization upon the
first call to stdio (e.g. `puts()`, `printf()`). The issue is that
without locking (as is currently the case for all RIOT platforms but
ESP) two concurrent "first calls" may result in concurrent
initialization of the same structure and data corruption.

Fixes https://github.com/RIOT-OS/RIOT/issues/20067
This commit is contained in:
Marian Buschsieweke 2024-02-16 06:51:28 +01:00
parent ef0e3fb54e
commit 375aed13e6
No known key found for this signature in database
GPG Key ID: 77AA882EC78084E6

View File

@ -24,32 +24,27 @@
* @}
*/
#include <unistd.h>
#include <reent.h>
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <reent.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/unistd.h>
#include <unistd.h>
#include "cpu.h"
#include "board.h"
#include "sched.h"
#include "thread.h"
#include "irq.h"
#include "log.h"
#include "modules.h"
#include "periph/pm.h"
#include "sched.h"
#include "stdio_base.h"
#include "thread.h"
#if MODULE_VFS
#include "vfs.h"
#endif
#include "stdio_base.h"
#include <sys/times.h>
#ifdef MODULE_XTIMER
#include <sys/time.h>
#include "div.h"
@ -149,7 +144,23 @@ static const struct heap heaps[NUM_HEAPS] = {
*/
void _init(void)
{
/* nothing to do here */
/* Definition copied from newlib/libc/stdio/local.h */
extern void __sinit (struct _reent *);
/* When running multiple threads: Initialize reentrant structure before the
* scheduler starts. This normally happens upon the first stdio function
* called. However, if no boot message happens this can result in two
* concurrent "first calls" to stdio in data corruption, if no locking is
* used. Except for ESP (which is using its own syscalls.c anyway), this
* currently is the case in RIOT. */
if (MAXTHREADS > 1) {
/* Also, make an exception for riotboot, which does not use stdio
* at all. This would pull in stdio and increase .text size
* significantly there */
if (!IS_USED(MODULE_RIOTBOOT)) {
__sinit(_REENT);
}
}
}
/**