Added option CONFIG_LOG_PRINTK_STATIC which redirects printk's to
logging macro which creates message during compilation by examining
argument types using _Generic keyword. When this option is enabled
printk format string is not accessed in runtime so it can be removed
(e.g. in dictionary based logging). When this option is enabled printk
is much faster. Option is implied when dictionary based logging is
enabled.
The only condition that must be met to use build time message creation
macros is that format string is a string literal and not a variable.
That is the case for printk because it is using __printf_like gcc
extension to validate that.
Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
Lightweight write sanitizer for sys_heap. Uses
-fsanitize=kernel-address compiler instrumentation combined with a
per-heap shadow bitarray (one bit per granule) to detect buffer
overflows, underflows, and use-after-free on write accesses.
Ships its own lightweight sanitizer runtime (__asan_store* callbacks);
does not depend on an external ASAN library and supports debugging on
real embedded targets.
Instrumentation is opt-in per CMake target via
zephyr_target_enable_heap_kasan(), or per directory via
zephyr_heap_kasan_enable_directory(). Only writes are checked
(-asan-instrument-reads=0). Bulk-write library calls (memset,
memcpy, str*, printf family) are redirected to checked wrappers at
compile time via -Dfoo=__asan_foo, requiring no source changes in
application code.
Heap tracking is likewise opt-in: register each heap with
SYS_HEAP_KASAN_ENABLE() / K_HEAP_KASAN_ENABLE(), or enable
CONFIG_SYS_HEAP_KASAN_MALLOC / CONFIG_SYS_HEAP_KASAN_SYSTEM for the
common libc malloc and kernel system heaps.
Usage:
CONFIG_SYS_HEAP_KASAN=y
CONFIG_SYS_HEAP_KASAN_MALLOC=y # auto-track malloc/free
CONFIG_SYS_HEAP_KASAN_SYSTEM=y # auto-track k_malloc/k_free
# Instrument all sources of <target> (CMakeLists.txt)
zephyr_target_enable_heap_kasan(app)
# Or instrument sources under <dir>
zephyr_heap_kasan_enable_directory(src/mymodule)
/* Opt-in tracking for a custom heap */
K_HEAP_DEFINE(my_heap, 4096);
K_HEAP_KASAN_ENABLE(my_heap, 4096);
Signed-off-by: Jinming Zhao <jinmzhao@qti.qualcomm.com>
Change these (back) to the single use version, they have been changed
recently for "consistency" reasons but that seems to be incorrect.
Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
Add a sys_heap sanitizer backend behind the SYS_HEAP_SANITIZER_HOOKS.
The backend integrates the toolchain's Address Sanitizer (ASAN) runtime
for use on native simulator based platforms.
The backend (heap_sanitizer_asan.c) implements the three hook entry
points as thin wrappers over the ASAN manual poisoning runtime:
sys_heap_init poisons the whole heap buffer, a successful allocation
unpoisons exactly the user-requested region and a free re-poisons the
usable region. Accesses to freed, never-allocated or out-of-bounds heap
memory are then reported by ASAN with a full backtrace and shadow dump.
The init hook runs at the end of sys_heap_init (after the bucket array
has been zeroed), so the chunk headers and internal metadata stay
poisoned for the lifetime of the heap and act as permanent redzones.
The heap implementation owns the bytes it poisons (chunk headers,
free-list links, canaries), so the heap internal sources are excluded
from ASAN instrumentation with -fno-sanitize=address. Those sources are
added to the root-scoped "zephyr" target, so the COMPILE_OPTIONS
property is set with TARGET_DIRECTORY; a plain
set_source_files_properties() in this directory does not reach the
target and leaves the sources instrumented.
SYS_HEAP_SANITIZER_ASAN requires the big-heap chunk format so the user
pointer and the end of the usable region are 8-byte aligned, matching
ASAN's shadow granularity (implied on 64-bit, explicit on 32-bit). The
runtime API and manual poisoning interface are common to GCC (libasan)
and Clang/LLVM (compiler-rt), so the feature is not tied to a single
compiler.
Verified on native_sim: in-bounds allocation and access across a range
of sizes is clean (no false positives) and a use-after-free is reported,
with both the host GCC and host LLVM toolchains.
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
Introduce a single set of hook points so a heap memory sanitizer can be
plugged into sys_heap without scattering backend-specific conditionals
through heap.c.
A new internal header lib/heap/heap_sanitizer.h declares three entry
points:
heap_sanitizer_on_init (heap, mem, bytes) poison the whole heap buffer
heap_sanitizer_on_alloc(heap, mem, bytes) unpoison [mem, mem+bytes)
heap_sanitizer_on_free (heap, mem, bytes) re-poison the usable region
heap.c calls them at the public-API boundary (sys_heap_init,
sys_heap_alloc, sys_heap_aligned_alloc, sys_heap_free) gated on a hidden
CONFIG_SYS_HEAP_SANITIZER_HOOKS symbol that a backend selects. In-place
realloc is expressed as on_free(old_usable) followed by on_alloc(new),
which produces the correct shadow for both grow and shrink without a
dedicated re-poison helper.
The allocate-and-copy realloc fallback re-grants access to the source
block's full usable region around the internal memcpy (which a
reads-checking backend would otherwise keep poisoned past the requested
size) and lets the subsequent free re-poison it.
No backend is provided here, so CONFIG_SYS_HEAP_SANITIZER_HOOKS is
unset and the hooks compile to nothing: no functional change. Verified
that tests/lib/heap still passes on native_sim.
Assisted-by: Copilot:claude-opus-4.8
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
Replace lowercase min() with the standard Zephyr MIN() macro
in sys_heap_realloc() and sys_heap_aligned_realloc() for
consistency with the rest of the codebase.
No functional change.
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
make_endpoint_info() and make_function_block_info() populate only the
first two words of the 128-bit UMP, leaving the remaining two words
uninitialised. They are sent verbatim, leaking 8 bytes of stack to any
UMP peer per request.
Zero-initialise the struct.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
CONFIG_LINKER_USE_PINNED_SECTION is the second half of the selective
kernel-pinning model removed in issue #108773. With the kernel image
now always resident at boot (previous commit), the __pinned_*
attribute family is a no-op: every page they would have segregated is
already pinned by z_mem_manage_init()'s whole-image loop, so the
tagging contract neither adds safety nor remains maintainable.
Drop it.
Mechanical removals:
* All ~219 in-tree uses of __pinned_text, __pinned_rodata,
__pinned_data, __pinned_bss, __pinned_noinit, and __pinned_func
across arch/x86, drivers/interrupt_controller, drivers/timer,
arch/common, kernel, lib/libc, subsys/portability/posix, tests, and
the syscall code generator (scripts/build/gen_syscalls.py).
* The assembly aliases PINNED_TEXT/RODATA/DATA/BSS/NOINIT used in
arch/x86/core/ia32/*.S and drivers/interrupt_controller/
intc_loapic_spurious.S become plain TEXT/RODATA/DATA/BSS/NOINIT.
* K_KERNEL_PINNED_STACK_DEFINE, K_KERNEL_PINNED_STACK_ARRAY_DEFINE,
K_KERNEL_PINNED_STACK_ARRAY_DECLARE, K_THREAD_PINNED_STACK_DEFINE,
and K_THREAD_PINNED_STACK_ARRAY_DEFINE are removed. The few
in-tree callers (kernel/init.c, arch/arm/core/cortex_a_r/smp.c,
arch/arm64/core/fatal.c, arch/rx/core/prep_c.c,
arch/x86/core/prep_c.c, kernel/include/kernel_internal.h,
tests/bluetooth/hci_uart_async) move to the corresponding
non-pinned macros.
Machinery removals:
* Kconfig.zephyr drops CONFIG_LINKER_USE_PINNED_SECTION.
qemu_x86_tiny and qemu_x86_atom_virt drop their =y overrides.
* include/zephyr/linker/section_tags.h drops the __pinned_* macro
definitions (both arms). __isr collapses to an empty macro since
its only purpose was to alias __pinned_func.
* include/zephyr/linker/sections.h drops PINNED_TEXT_SECTION_NAME,
PINNED_BSS_SECTION_NAME, etc. and the bare PINNED_TEXT/RODATA/etc.
forwarders, plus the _APP_SMEM_PINNED_SECTION_NAME constant.
* include/zephyr/linker/linker-defs.h drops the lnkr_pinned_*
externs, the _app_smem_pinned_* externs, and the lnkr_is_pinned()
/ lnkr_is_region_pinned() inline helpers.
* include/zephyr/linker/utils.h drops the lnkr_pinned_rodata branch
in linker_is_in_rodata().
* include/zephyr/linker/app_smem_pinned{,_aligned,_unaligned}.ld
are deleted; cmake/linker/ld/target_configure.cmake stops
configuring them.
* boards/qemu/x86/qemu_x86_tiny.ld and
include/zephyr/arch/x86/ia32/linker.ld drop their pinned-section
blocks and the now-redundant #ifndef CONFIG_LINKER_USE_PINNED_SECTION
conditionals throughout the body. The
LIB_KERNEL_IN_SECT / LIB_ARCH_X86_IN_SECT / LIB_ZEPHYR_IN_SECT /
LIB_C_IN_SECT / LIB_DRIVERS_IN_SECT / LIB_SUBSYS_LOGGING_IN_SECT /
LIB_ZEPHYR_OBJECT_FILE_IN_SECT / ZEPHYR_KERNEL_FUNCS_IN_SECT macros
in qemu_x86_tiny.ld are deleted; they existed only to feed the
pinned text/rodata/data/bss/noinit sections.
* kernel/mmu.c drops the mark_linker_section_pinned(lnkr_pinned_start,
...) call. The mark_linker_section_pinned() helper survives but is
now gated only on CONFIG_LINKER_USE_BOOT_SECTION.
* arch/common/init.c and include/zephyr/arch/common/init.h drop
arch_bss_zero_pinned(); arch/x86/core/ia32/crt0.S drops the call
to it.
* arch/x86/core/userspace.c drops the eager k_mem_page_in() of the
thread's privileged stack on user-mode entry. With the kernel
image fully resident the stack is already mapped.
* arch/x86/gen_mmu.py drops map_region("lnkr_pinned") and the
set_region_perms() calls for lnkr_pinned_text / lnkr_pinned_rodata.
* CMakeLists.txt drops the LINKER_USE_PINNED_SECTION block that
generated APP_SMEM_PINNED_* variables and the
pinned_partitions target property feeding gen_app_partitions.py.
cmake/modules/extensions.cmake removes the PINNED_RODATA /
PINNED_RAM_SECTIONS / PINNED_DATA_SECTIONS zephyr_linker_sources()
location keywords and their snippet files.
scripts/build/gen_app_partitions.py drops --pinoutput /
--pinpartitions arguments and the pinned-output branch.
subsys/testsuite/coverage/CMakeLists.txt drops its
CONFIG_DEMAND_PAGING-conditional fork.
* scripts/build/gen_kobject_list.py drops the
app_smem_pinned_start / _end fallback for kobject placement
validation.
* tests/arch/x86/pagetables and tests/kernel/mem_protect/userspace
drop their lnkr_pinned_text / lnkr_pinned_rodata branches.
* include/zephyr/arch/x86/ia32/arch.h folds IRQSTUBS_TEXT_SECTION
to the unconditional ".text.irqstubs" form.
* tests/subsys/llext/src/syscalls_ext.c drops a stale comment about
syscalls landing in .pinned_text.
Targeted retentions:
* arch/x86/core/bootargs.c keeps multiboot_cmdline and efi_bootargs
in .noinit (was __pinned_noinit, which decayed to __noinit when
LINKER_USE_PINNED_SECTION was unset). The multiboot and zefi loader
paths write these buffers before Zephyr's BSS-zero step, so
zeroing them at boot loses the cmdline.
* arch/x86/core/ia32/fatal.c keeps _df_esf and _df_stack in .noinit.
They are scratch space written by the double-fault handler and have
no zero-init requirement; keeping them in .noinit also preserves
the historical post-noinit alignment that gen_mmu.py relies on
(z_mapped_size is computed before CMake-injected iterable sections
are appended to the linker script, so the post-noinit page padding
is what keeps those sections within the mapped region).
* include/zephyr/arch/x86/ia32/syscall.h and
include/zephyr/arch/x86/arch.h wrap the per-arch
arch_syscall_invoke* / arch_is_user_context / arch_k_cycle_get_*
implementations in @cond INTERNAL_HIDDEN. The public Doxygen
contract lives on the prototypes in
include/zephyr/arch/arch_interface.h; the per-arch implementations
are internal. Without this, removing the __pinned_func attribute
exposes the implementations to the doxygen-coverage delta check
as 10 newly-undocumented APIs.
Documentation updates are deferred to a separate commit.
Issue: #108773
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Similarly to the existing CONFIG_ZVFS_OPEN_ADD_SIZE_* mechanism used to
size the file descriptor table, allow subsystems to declare their eventfd
count requirements via CONFIG_ZVFS_EVENTFD_ADD_SIZE_* Kconfig options.
These are summed up at build time and compared against
CONFIG_ZVFS_EVENTFD_MAX, with the larger of the two values used to size
the eventfd table, exposed as the ZVFS_EVENTFD_SIZE compile definition.
A new CONFIG_ZVFS_EVENTFD_IGNORE_MIN option allows to override the
calculated requirement and use CONFIG_ZVFS_EVENTFD_MAX as-is.
As each eventfd also consumes a file descriptor, the resulting eventfd
count is now reserved in the file descriptor table as well, replacing the
former CONFIG_ZVFS_OPEN_ADD_SIZE_EVENTFD option which only accounted for
CONFIG_ZVFS_EVENTFD_MAX.
The WPA supplicant requirement is moved from a CONFIG_ZVFS_EVENTFD_MAX
default into a dedicated
CONFIG_ZVFS_EVENTFD_ADD_SIZE_WIFI_NM_WPA_SUPPLICANT option.
Assisted-by: Cursor:Claude Opus 4.8
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Replace z_unpend_first_thread() with z_unpend_first_thread_locked() and
migrate every caller across the kernel. The old function dropped the
scheduler spinlock before returning, exposing a race window between
its caller's "arch_thread_return_value_set + z_ready_thread" pair and
a still-in-flight timeout handler that could ready the thread first --
the woken thread might then run on another CPU and see an uninitialized
swap_retval. Pre-1b8c7a3 the dticks-cancel check made the handler bail;
here we fix it cleanly by requiring the caller to hold _sched_spinlock
across the entire wake, so the handler is blocked for the duration and
runs as a no-op afterwards.
z_unpend_first_thread_locked() requires the caller to be inside a
locked region and must be paired with z_sched_ready_locked() (and
whatever return-value setup is needed) under the same lock acquisition.
Sites migrated:
Simple "set retval [+ swap_data] and ready" callers use the existing
z_sched_wake() convenience wrapper, refactored to use the new
helper internally:
sem (give, reset), mem_slab (free), stack (push),
condvar (signal, broadcast), msgq (purge),
queue (cancel_wait, queue_insert, append_list),
futex (wake).
Sites that need additional setup on the woken thread use
LOCK_SCHED_SPINLOCK + z_unpend_first_thread_locked() + custom wake:
mutex (unlock -- needs the thread reference to track new owner),
msgq put / get (needs memcpy into the receiver's swap_data
buffer before the return value is set).
The dticks-cancel check in z_thread_timeout() is left in place; it is
no longer load-bearing once z_abort_thread_timeout() has no callers,
and is removed in the next commit.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Picolibc selects printf variants (minimal, integer, long-long, float)
via --defsym linker directives generated by GCC's picolibc.specs file.
Clang does not support specs files, so the -DPICOLIBC_*_PRINTF_SCANF
flags passed at link time were silently ignored, causing vfprintf to
always resolve to the full implementation regardless of configuration.
Signed-off-by: Adarsha Regmi <aregmi@qti.qualcomm.com>
The MWDT toolchain's <string.h> does not declare strsignal(),
which is a POSIX XSI extension. Without a declaration the
compiler treats calls to strsignal() as implicit int-returning
functions, causing the return value to be passed as a pointer:
error: incompatible integer to pointer conversion passing
'int' to parameter of type 'const void *'
Add the declaration alongside the existing strnlen() declaration.
The implementation is already provided by Zephyr's POSIX
portability subsystem in subsys/portability/posix/options/signal.c.
Signed-off-by: Mohamed Moawad <moawad@synopsys.com>
The MWDT toolchain defines clockid_t as int in its <time.h>, pid_t
as long and uid_t as long in its <sys/types.h>. Zephyr's POSIX
headers redefine these with different underlying types, causing:
error: typedef redefinition with different types
Fix by including <sys/types.h> early in the arcmwdt <time.h> and
<signal.h> wrappers so that the MWDT type guard macros are set
before posix_time.h and posix_signal.h attempt to define those
types. Also set _PID_T_DECLARED in the arcmwdt <sys/types.h>
wrapper to suppress the conflicting Zephyr pid_t definition.
Signed-off-by: Mohamed Moawad <moawad@synopsys.com>
When CONFIG_POSIX_DEVICE_IO and CONFIG_PICOLIBC are enabled,
stdinout_write_vmeth will return 0, causing the write function to
busy-wait forever on file descriptor 1 (stdout).
This change makes the function work with Picolibc, so we can use
write with file descriptor 1 to output data to the stdout_hook of
picolibc.
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Having an interface library named "mbedTLS" and the real library named
"mbedtls" (as provided by the Mbed TLS module) is misleading.
This commit replaces:
- mbedTLS -> mbedtls_iface for the CMake library. "mbedTLS" is still
available as alias to "mbedtls_iface" for backward
compatibility, but this should be removed in the future.
- mbedTLS -> Mbed TLS in comments and documentation.
Signed-off-by: Valerio Setti <vsetti@baylibre.com>
Fix two issues in heap canary check:
Correct double-free reporting: In sys_heap_free and inplace_realloc, the
basic chunk_used check (from SYS_HEAP_HARDENING_BASIC) was executing
before the canary check (SYS_HEAP_HARDENING_FULL). This caused
inaccurate error messages during double-free events. Reordered
verify_chunk_canary to run before chunk_used to ensure precise
reporting. Move the poison_chunk_canary to free_chunk for unified
poisoning.
Fix missing poisoning after merge: When free chunks were merged, the
pre-merge trailer location, which moves out from under chunk_trailer()
once set_chunk_size updates the size during merge. This led to
subsequent double-free events reading an incorrect canary, which was
misidentified as heap corruption. Therefore, poison the free chunk at
the end of the merge process.
Signed-off-by: Frank Li <lgl88911@163.com>
Since commit 37717b229f ("sys: util: rename Z_MIN Z_MAX Z_CLAMP to min
max and clamp"), <zephyr/sys/util.h> unconditionally defines function-
like macros named `min`, `max`, and `clamp` in the global namespace (in
C mode). util.h gets pulled in transitively by very broad headers,
including the POSIX layer's <pthread.h>, so any third-party C code that
uses these names as ordinary identifiers (e.g. XNNPACK's static `clamp`
helper and its public `clamp` struct field) fails to build as soon as
<pthread.h> is included.
Following the approach used by Linux, move the lowercase `min`, `max`,
`min3`, `max3`, and `clamp` macros (and their helpers) into a new
<zephyr/sys/minmax.h> header that has to be included explicitly by
source files that want them. util.h keeps the uppercase MIN/MAX/CLAMP,
so most code is unaffected; only the (much smaller) set of files that
actually use the lowercase variants needs to pick up the new include.
Fixes#107853.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
the boot banner is printed at the end of
the init process with
``SYS_INIT(boot_banner, APPLICATION, 0);``
we don't need the early console for it.
When CONFIG_EARLY_CONSOLE is enabled,
the console will init with PRE_KERNEL_1, otherwise
with POST_KERNEL. Both are before APPLICATION.
Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
When cbvprintf_package() packages a %s argument, append_string()
eventually calls strlen(str) on the pointer. If the caller passed
NULL to %s, strlen() dereferences address 0. On MMU-less targets
this is undefined behavior; on TF-M targets the SPU fields a read
at address 0 as SECURE_FAULT, which aborts the whole image.
Passing NULL to %s is a caller bug. However, deferred/packaged
logging captures the argument now and dereferences it later,
disconnecting the crash site from the offending call site and
making triage significantly harder. Substitute "(null)" in place
of a NULL string, matching the behavior of glibc's printf family,
so the buggy caller shows up in the log output rather than the
log infrastructure crashing.
Signed-off-by: Diego Solano <diegosolano@gmail.com>
It should not depend on CONFIG_MBEDTLS nor CONFIG_MBEDTLS_PSA_CRYPTO_C
as a PSA Crypto provider other than Mbed TLS may be enabled.
In fact, it doesn't even need to depend on CONFIG_PSA_CRYPTO
because CONFIG_PSA_WANT_ALG_SHA_1 is already guarded behind
CONFIG_PSA_CRYPTO_CLIENT.
At the same time, replace all the `depends on UUID` by a single if
which is the standard way to do. Also turn CONFIG_UUID into a menuconfig
instead of creating a menu manually.
Signed-off-by: Tomi Fontanilles <tomi.fontanilles@nordicsemi.no>
The CONFIG_NET_SOCKETS_POLL_MAX Kconfig option was deprecated in
Zephyr 4.0.0, remove it and any leftover in-tree option use.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Introduces K_MEM_SLAB_DEFINE_TYPE() and K_MEM_SLAB_DEFINE_STATIC_TYPE()
helpers to allow the user to declare slabs for types without having to
manually ensure the alignment is correct.
Manual slab alignment was very error-prone and this change fixes several
instances of misalignment that would be trapped by the undefined
behavior sanitizer when running on 64-bit targets.
Signed-off-by: Egill Sigurdur <egill@egill.xyz>
393350fd65 made it so that the `mbedTLS`
library is only created when `CONFIG_MBEDTLS_BUILTIN`.
Before this commit, users of Mbed TLS did the following:
`zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)`
If the `mbedTLS` CMake library doesn't exist but is still linked to
(as is the case when `CONFIG_MBEDTLS && !CONFIG_MBEDTLS_BUILTIN`),
the linker command is populated with `-lmbedTLS` which makes the build
fail because there is no `libmbedTLS.a` in the build.
Make it so that users of Mbed TLS only link to the `mbedTLS` CMake
library when the builtin version is used.
Signed-off-by: Tomi Fontanilles <tomi.fontanilles@nordicsemi.no>
This moves the atomic_c.c from kernel to lib/os as atomic
functions are not exactly kernel features.
This also moves all the atomic kconfigs from kernel to lib/os
as the atomic headers are already under include/zephyr/sys/.
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
errno is not exactly a kernel functionality but more of C
library feature. So move errno from kernel into lib/libc/common.
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
The two reference counts in the net_buf library -- the per-header
`buf->ref` and the per-data-block `*ref_count` byte at the start of
each variable-data allocation -- were manipulated with plain non-atomic
C operators (`++`, `--`, `if (--rc)`, `if (!rc)`).
The documented contract says otherwise. The Network Buffers chapter of
the Zephyr docs (`doc/services/net_buf/index.rst`) states:
"The buffers have native support for being passed through k_fifo
kernel objects. Use k_fifo_put and k_fifo_get to pass buffer from
one thread to another."
"The reference count can be incremented with net_buf_ref() or
decremented with net_buf_unref(). When the count drops to zero the
buffer is automatically placed back to the free buffers pool."
There is no requirement for callers to hold a higher-level lock around
ref/unref. The API is documented as self-synchronizing, and existing
users (notably zbus's msg-subscriber path) rely on exactly that:
a producer clones a buffer N times and hands the clones off to N
subscriber threads via their FIFOs, after which the N+1 holders
independently call `net_buf_unref()` with no surrounding lock.
With non-atomic decrement-and-test, two CPUs can concurrently observe
the same prior value (e.g. 1), both decrement, and both conclude they
were the last reference. Concrete failure modes:
* `mem_pool_data_unref`: both CPUs call `k_heap_free(pool, ref_count)`
on the same block. `k_heap_free` is internally serialized, so the
duplicate free typically corrupts heap metadata silently.
* `heap_data_unref`: both CPUs call `k_free(ref_count)` on the same
block. `k_free` reads the owning `struct k_heap *` from the 8 bytes
immediately preceding `ref_count`. The first call frees the block
and the heap-hardening fill replaces those 8 bytes with the poison
pattern (0xcfdfdfdfdfdfdfcf). The second call then dereferences a
poisoned pointer and faults inside `k_spin_lock` (translation
fault on the bogus heap address).
* `net_buf_unref`: two CPUs racing the per-header decrement-and-test
can both decide "I am the last reference," both proceed to
`net_buf_destroy()`, and the buffer is returned to the pool's LIFO
twice -- silently corrupting the free list.
Fix: use atomic operations on both reference counts.
The per-data-block refcount changes from `uint8_t` to `atomic_t`. This
fits inside the existing `GET_ALIGN(pool)` reservation (>= sizeof(void
*)) at no memory cost.
The per-header `buf->ref` is overlaid in a union with three small
adjacent uint8_t fields (`flags`, `pool_id`, `user_data_size`) and an
`atomic_t ref_word` view of the same storage:
union {
atomic_t ref_word;
struct {
uint8_t ref;
uint8_t flags;
uint8_t pool_id;
uint8_t user_data_size;
};
};
(Byte order conditional on endianness so `ref` is always the LSB of
`ref_word`; on big-endian 64-bit, the byte struct is shifted by 4
bytes of padding for the same reason.)
Net_buf internals issue `atomic_inc(&buf->ref_word)` /
`atomic_dec(&buf->ref_word)` and narrow the returned word value to
`uint8_t` to extract the ref byte. Because the ref count is bounded
to 254 (already implicit in its uint8_t domain), atomic_inc/dec
adjusts only the LSB; the other three bytes are untouched. Plain
uint8_t reads of `buf->ref` from non-atomic call sites continue to
work, so the change is transparent to the dozens of consumers that
read it for diagnostics.
`flags`, `pool_id` and `user_data_size` are written exactly once at
allocation time on a single thread (or, for `flags`, from a context
that owns the buf exclusively such as bt_buf_make_view on a fresh
view), so there are no concurrent byte writes that could conflict
with the atomic word update. struct net_buf does not grow on either
32-bit or 64-bit: on 32-bit the four bytes are exactly `sizeof(long)`,
on 64-bit they fit in alignment padding the next field already
required.
A BUILD_ASSERT in lib/net_buf/buf.c documents the
`atomic_t == long` assumption that the conditional padding relies on.
In `net_buf_unref`, the per-header refcount and the fields needed for
the debug log (`buf->pool_id`) are captured into local variables
*before* the atomic decrement -- once the reference is dropped, another
CPU may immediately free the buffer, so the buffer must not be read
again. The post-decrement diagnostic log uses the value returned by
`atomic_dec` rather than re-reading `buf->ref`. The `pool->avail_count`
sanity check uses the value returned by `atomic_inc` to avoid a
follow-up `atomic_get` of memory another CPU may have changed.
`net_pkt_frag_unref()` previously had the racy
`if (frag->ref == 1U) alloc_del(); net_buf_unref();` pattern; it is
restructured to do the atomic decrement here and slot the tracker call
in atomically with the "I'm the last reference" decision, with
`net_pkt_frag_del()` routed through it.
This bug had been latent. On real SMP hardware the race window is very
small and the typical net_buf consumers (Bluetooth, networking) tend
to use fixed-data pools (`fixed_data_unref` is a no-op). The race
manifests reliably under FVP, where the FastModel's quantum-based
execution model can schedule N threads to all reach the unref point in
the same simulated moment. We discovered it through the zbus
`msg_subscriber_dynamic_isolated` sample, which exchanges shared data
buffers among 16+ subscribers running on 4 SMP cores.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This moves boot arguments from kernel into the lib/os.
This is not strictly a kernel function so this change provides
a separation between core kernel functionalities and others.
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
Boot banner is not exactly a kernel feature. It is more like
an OS feature so moving it into lib/os.
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
acpi is not really library code based on the new definition of what
should go into lib/. Move acpi into arch/common/ as it is cross arch
feature.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
gen_offset.h is an architecture-specific header, not a kernel one.
Move it under the arch tree where it belongs.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
COBS streaming works without net_buf instances, optionally enable the
encode/decode helper functions, and remove the select.
Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
The C11 thrd_create() was casting the user's thrd_start_t (returns int)
to a pthread function pointer (returns void *) and passing it directly
to pthread_create(). This is undefined behavior per C99 6.3.2.3 and
breaks on architectures with split data/address return registers.
On TriCore, int returns in d2 (data register) while void * returns in
a2 (address register). The cast caused pthread internals to read the
return value from a2 (garbage) instead of d2, making thrd_join() always
return wrong results.
Use the already-defined struct thrd_trampoline_arg with a proper
trampoline function that calls the user function as int-returning and
converts the result via INT_TO_POINTER. A semaphore ensures the
parent's stack-allocated trampoline arg stays alive until the child
has copied it.
Fixes: tests/lib/c_lib/thrd failures on all TriCore targets.
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
The cbprintf_cb typedef used an empty parameter list () which in C23
is equivalent to (void), making it incompatible with any callback
function that takes parameters.
Fix by giving cbprintf_cb a proper prototype (int c, void *ctx),
removing the now-redundant cbprintf_cb_local typedef, and adding
explicit (cbprintf_cb) casts at call sites where the callback has a
different signature (fputc, sprintf_out).
Signed-off-by: Shuai Ma <Shuai.MA@cn.bosch.com>
Randomize the base canary value at heap creation in order to make
it unpredictable to attackers and reduce their size to 4 bytes,
which should still give enough entropy but reduce overhead
especially on 32-bit targets.
This adds a dependency for heap hardening levels with canaries to
a random number generator.
Signed-off-by: Christoph Busold <cbusold@qti.qualcomm.com>
Allow multiple descriptors with the same field name to support
polymorphic JSON fields such as id: string | integer.
The parser now tries all descriptors matching a field name and only
returns an error if all the attempts fail. This preserves existing
error behavior for non-polymorphic fields.
Signed-off-by: Alex Rodriguez <alejandro.rodriguezlimon@nxp.com>
Posix is not a library per the definition of libraries in Zephyr. It
always has been a portability layer and shall reside with other
portability layers under subsys/portability.
Addresses #99250
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit aims to slightly improve performance of
Zephyr-based applications by inlining often-used functions.
net_buf is used by different subsystems and applications so
performance of this library affects performance of many other
modules and it is important to keep its implementation efficient
and robust.
The following functions were moved from buf_simple.c to net_buf.h:
- net_buf_simple_headroom() - it was already used by some of inlined
functions which made inlining less efficient
- net_buf_simple_tailroom() and net_buf_simple_max_len() that do
very basic size calculations
Signed-off-by: Ivan Iushkov <ivan.iushkov@nordicsemi.no>