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>
Add support for encoding null values in json. This is useful to be
able to encode optional values as null when they are not set.
Signed-off-by: Tim Pambor <tim.pambor@codewrights.de>
- Change `config SMF` to `menuconfig SMF` since it serves as a parent
for child config options under `if SMF`.
- Update help text descriptions to follow Zephyr wording conventions,
replacing descriptions with clearer explanations.
Signed-off-by: Vladislav Kulikov <vlad_kulikov_c@pm.me>
Combine toolchains provided by the host into one variant. This includes
both gcc and llvm installation typically coming from the distribution
(on Linux).
Both gcc and llvm are now part of the 'host' variant, the default is the
gnu compiler, so setting
ZEPHYR_TOOLCHAIN_VARIANT=host
Will select the gnu compiler. To select llvm or any other compuler
provided in this variant, use the follwoing format:
ZEPHYR_TOOLCHAIN_VARIANT=<variant>/<compiler>
The following will select llvm:
ZEPHYR_TOOLCHAIN_VARIANT=host/llvm
Although gnu is the default, it can also be selected using the above
syntax:
ZEPHYR_TOOLCHAIN_VARIANT=host/gnu
This commit removes the llvm variant for now, it should be deperecated
in another commit to follow.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
LLVM C++ Standard Library aka. libc++ makes use of POSIX and GNU C
extensions in its headers.
While far from ideal, there is no other option but to globally enable these
extensions for C++ source files in order to ensure that libc++ headers can
be used.
Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
LLVM C++ Standard Library aka. libc++ may be used with Picolibc -- for
example, LLVM Embedded Toolchain for Arm ships with Picolibc and libc++
compiled for Picolibc, and so does Zephyr SDK LLVM toolchain.
Ideally, we would a flag like `TOOLCHAIN_HAS_LIBCXX_PICOLIBC` indicating
that toolchain has libc++ compiled specifically for Picolibc; but, we do
not want to overcomplicate the toolchain feature flags at this time without
proper underlying infrastructure to handle it.
Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
This commit introduces `TOOLCHAIN_HAS_LIBCXX` CMake variable, which is set
to `y` when LLVM C++ Standard Library aka. libc++ is available.
This helps filter libc++-specific Kconfig and tests in a more refined
manner.
Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
This commit introduces `TOOLCHAIN_HAS_GLIBCXX` CMake variable, which is
set to `y` when GNU C++ Standard Library aka. libstdc++ is available.
This helps filter libstdc++-specific Kconfig and tests in a more refined
manner.
Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
Add instrumentation hooks for transitions and actions, as well as
error states. This will allow us to track the state of the state
machine during testing, and also provide a way to debug issues
that may arise during execution.
Signed-off-by: Glenn Andrews <andrewsglenn@meta.com>
At FULL hardening, trailer canaries on used chunks implicitly guard
adjacent free chunk headers: a sequential buffer overflow must corrupt
the used chunk's trailer before reaching the next header. However,
when a free neighbor's metadata is needed for merging during free(),
the neighbor's header could already have been corrupted by an overflow
from its left used chunk that hasn't been freed yet. For example:
[hdr_U1] [data_U1] [trailer_U1] [hdr_F] [...] [hdr_U2] [trailer_U2]
If data_U1 overflows past trailer_U1 and corrupts hdr_F, freeing U2
would use hdr_F's corrupted size and free-list pointers for merging,
potentially leading to heap structure corruption or arbitrary writes.
Additionally, a corrupted LEFT_SIZE in a used chunk being freed can
point to a fake header crafted inside the left neighbor's data area:
[hdr_U1] [data_U1 ..fake_hdr.. trailer_U1'] [hdr_U2'] [data_U2] ...
| corrupted LEFT_SIZE points
| by overflow to fake_hdr
+<--------------------------+
A determined attacker can make fake_hdr's size field self-consistent
with the corrupted LEFT_SIZE so that the structural round-trip checks
pass. If fake_hdr is marked "used", free_chunk() skips the left
merge and the corruption goes undetected. If marked "free", it
triggers a bogus merge with attacker-controlled free-list pointers.
Both cases are caught by verifying the left used neighbor's canary:
any overflow from the left must pass through trailer_U1 to reach
hdr_U2's LEFT_SIZE field, so the corrupted canary acts as a tripwire
regardless of whether the resulting fake header is marked used or free.
Address this by introducing free_chunk_check() which validates a free
chunk's structural integrity before trusting its header fields. It
consolidates the existing MODERATE-level structural checks (chunk
linkage, used-bit consistency) with a new FULL-level canary
verification of the left used neighbor. Factoring these checks into
a dedicated function lets callers specify @left_trusted according to
context (e.g. the chunk being freed is the left neighbor of the right
merge candidate, so its canary need not be rechecked).
In inplace_realloc()'s shrink path, the freed suffix's left neighbor
is always the chunk being reallocated (used, just validated). This
path inlines only the right merge to avoid the unnecessary left canary
check.
The check is called before every free list removal: in free_chunk()
for left/right merge candidates, in alloc_chunk() when pulling from
a bucket, and in inplace_realloc() before consuming the right
neighbor.
Also give chunk0 a canary trailer so that the left-neighbor canary
check works uniformly for the first free chunk in the heap.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Replace the standalone SYS_HEAP_CANARIES bool with a tiered
SYS_HEAP_HARDENING choice controlling runtime validation:
NONE (0) - no checks
BASIC (1) - double-free and overflow detection in free/realloc
MODERATE (2) - free list and neighbor consistency checks
FULL (3) - trailer canary on every allocation
EXTREME (4) - exhaustive heap validation on every operation
Default is MODERATE when ASSERT is enabled, BASIC otherwise.
Hardening checks are independent of CONFIG_ASSERT: they use
LOG_ERR + k_panic() instead of __ASSERT so the configured level
is always honored regardless of assertion settings.
Also adds heap logging via LOG_MODULE_REGISTER. This paves the way for
eventual permanent debugging instrumentation.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Factor out the core heap validation logic into z_heap_full_check()
which takes a struct z_heap pointer directly. This allows internal
callers (e.g. alloc_chunk) to validate the heap without needing
the public struct sys_heap wrapper.
sys_heap_validate() becomes a thin wrapper that calls
z_heap_full_check() and then validates runtime stats.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Add optional canary values at the end of each heap allocation to detect
memory corruption. The canary is validated when memory is freed, catching
buffer overflows (writing past allocation) and double-free errors.
The canary is computed from the chunk address and size, XORed with a
magic value. On free, it is checked and then poisoned to detect
double-free attempts.
The canary is stored as trailer data at the end of the chunk rather than
in the header to avoid complicating aligned allocation processing, and
because buffer overflows are most likely to overwrite past the buffer end
anyway.
This adds 8 bytes of memory overhead per allocation and a canary
computation on alloc and validation on free. It is useful for hardening
against memory corruption as well as for chasing bugs during
development. The trailer structure can be readily extended to carry
additional per-allocation metadata if so desired.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
The function checks if a chunk is too small to be added to the free list.
The new name better reflects its purpose and the comparison now uses
min_chunk_size() for clarity.
Such chunks are not added to the free list because they would be too
small to be allocatable, and they might be too small to store the free
list pointers. It happens that min_chunk_size() is always >= the free
pointer storage size.
The big_heap() condition short-circuits the comparison with a build-time
constant when undersized chunks cannot occur.
A following commit will rely on this to exclude chunks that are smaller
than min_chunk_size() which will grow to account for trailer data.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Replace chunksz_to_bytes() which took a chunk size with
chunk_usable_bytes() which takes a chunk_id directly. This eliminates
the redundant pattern of chunksz_to_bytes(h, chunk_size(h, c)) and makes
the API clearer by returning actual usable bytes (excluding the header).
Add mem_align_gap() helper to compute alignment padding between the
start of usable chunk memory and the actual memory pointer, using
efficient bit masking. This simplifies sys_heap_usable_size() and
inplace_realloc(). Use these helpers to make runtime stats reporting
reflect actual usable chunk memory (excluding chunk headers), and heap
listener notifications also account for alignment gaps.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Z_HEAP_MIN_SIZE and Z_HEAP_MIN_SIZE_FOR were defined in kernel.h as
hardcoded magic numbers gated by a growing tower of #ifdefs — one
per Kconfig option that happened to affect the heap struct layout.
Every internal change required manually recomputing the constants,
duplicating layout knowledge across files, and praying nobody forgot
to update the #ifdef matrix. This is fragile and unscalable: adding
a single new heap feature (e.g. a chunk canary trailer) would add yet
another dimension to the combinatorial explosion.
Replace this with build-time computation from the actual C structures.
A new lib/heap/heap_constants.c uses GEN_ABSOLUTE_SYM to emit the
correct values into a generated heap_constants.h header via the
zephyr_constants_library() infrastructure. Z_HEAP_MIN_SIZE is
derived through an iterative fixed-point expansion (3 rounds, always
convergent) that mirrors the runtime logic in sys_heap_init().
Big vs small heap determination uses CONFIG_SYS_HEAP_SMALL_ONLY,
CONFIG_SYS_HEAP_BIG_ONLY, and sizeof(void *), mirroring the
big_heap_chunks() logic in heap.h.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Replace ternary operator with if-else to avoid mixing signed and unsigned
types in the conditional expression. This eliminates the compiler warning
while preserving the original logic.
Fixes#104581
Signed-off-by: Roman Bakshansky <bakshansky@protonmail.com>
Add missing memory barriers after branching on k_is_user_context() to
prevent reordering possible of privileged memory access.
Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
The EBUSY return condition was incorrect and e.g. sem_destroy was in some
cases reporting this error even if no thread was blocked by this semaphore.
This commit fixes that by checking the waitqueue instead of the semaphore
count.
Signed-off-by: Jakub Michalski <jmichalski@antmicro.com>
The UUID library has been present as an experimental library in
the Zephyr code base since v4.2.
Since no need for major API changes has emerged in the last two
Zephyr version the library can be safely promoted to unstable.
Signed-off-by: Simone Orru <simone.orru@secomind.com>
At FULL hardening, trailer canaries on used chunks implicitly guard
adjacent free chunk headers: a sequential buffer overflow must corrupt
the used chunk's trailer before reaching the next header. However,
when a free neighbor's metadata is needed for merging during free(),
the neighbor's header could already have been corrupted by an overflow
from its left used chunk that hasn't been freed yet. For example:
[hdr_U1] [data_U1] [trailer_U1] [hdr_F] [...] [hdr_U2] [trailer_U2]
If data_U1 overflows past trailer_U1 and corrupts hdr_F, freeing U2
would use hdr_F's corrupted size and free-list pointers for merging,
potentially leading to heap structure corruption or arbitrary writes.
Additionally, a corrupted LEFT_SIZE in a used chunk being freed can
point to a fake header crafted inside the left neighbor's data area:
[hdr_U1] [data_U1 ..fake_hdr.. trailer_U1'] [hdr_U2'] [data_U2] ...
| corrupted LEFT_SIZE points
| by overflow to fake_hdr
+<--------------------------+
A determined attacker can make fake_hdr's size field self-consistent
with the corrupted LEFT_SIZE so that the structural round-trip checks
pass. If fake_hdr is marked "used", free_chunk() skips the left
merge and the corruption goes undetected. If marked "free", it
triggers a bogus merge with attacker-controlled free-list pointers.
Both cases are caught by verifying the left used neighbor's canary:
any overflow from the left must pass through trailer_U1 to reach
hdr_U2's LEFT_SIZE field, so the corrupted canary acts as a tripwire
regardless of whether the resulting fake header is marked used or free.
Address this by introducing free_chunk_check() which validates a free
chunk's structural integrity before trusting its header fields. It
consolidates the existing MODERATE-level structural checks (chunk
linkage, used-bit consistency) with a new FULL-level canary
verification of the left used neighbor. Factoring these checks into
a dedicated function lets callers specify @left_trusted according to
context (e.g. the chunk being freed is the left neighbor of the right
merge candidate, so its canary need not be rechecked).
In inplace_realloc()'s shrink path, the freed suffix's left neighbor
is always the chunk being reallocated (used, just validated). This
path inlines only the right merge to avoid the unnecessary left canary
check.
The check is called before every free list removal: in free_chunk()
for left/right merge candidates, in alloc_chunk() when pulling from
a bucket, and in inplace_realloc() before consuming the right
neighbor.
Also give chunk0 a canary trailer so that the left-neighbor canary
check works uniformly for the first free chunk in the heap.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Replace the standalone SYS_HEAP_CANARIES bool with a tiered
SYS_HEAP_HARDENING choice controlling runtime validation:
NONE (0) - no checks
BASIC (1) - double-free and overflow detection in free/realloc
MODERATE (2) - free list and neighbor consistency checks
FULL (3) - trailer canary on every allocation
EXTREME (4) - exhaustive heap validation on every operation
Default is MODERATE when ASSERT is enabled, BASIC otherwise.
Hardening checks are independent of CONFIG_ASSERT: they use
LOG_ERR + k_panic() instead of __ASSERT so the configured level
is always honored regardless of assertion settings.
Also adds heap logging via LOG_MODULE_REGISTER. This paves the way for
eventual permanent debugging instrumentation.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Factor out the core heap validation logic into z_heap_full_check()
which takes a struct z_heap pointer directly. This allows internal
callers (e.g. alloc_chunk) to validate the heap without needing
the public struct sys_heap wrapper.
sys_heap_validate() becomes a thin wrapper that calls
z_heap_full_check() and then validates runtime stats.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Add optional canary values at the end of each heap allocation to detect
memory corruption. The canary is validated when memory is freed, catching
buffer overflows (writing past allocation) and double-free errors.
The canary is computed from the chunk address and size, XORed with a
magic value. On free, it is checked and then poisoned to detect
double-free attempts.
The canary is stored as trailer data at the end of the chunk rather than
in the header to avoid complicating aligned allocation processing, and
because buffer overflows are most likely to overwrite past the buffer end
anyway.
This adds 8 bytes of memory overhead per allocation and a canary
computation on alloc and validation on free. It is useful for hardening
against memory corruption as well as for chasing bugs during
development. The trailer structure can be readily extended to carry
additional per-allocation metadata if so desired.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
The function checks if a chunk is too small to be added to the free list.
The new name better reflects its purpose and the comparison now uses
min_chunk_size() for clarity.
Such chunks are not added to the free list because they would be too
small to be allocatable, and they might be too small to store the free
list pointers. It happens that min_chunk_size() is always >= the free
pointer storage size.
The big_heap() condition short-circuits the comparison with a build-time
constant when undersized chunks cannot occur.
A following commit will rely on this to exclude chunks that are smaller
than min_chunk_size() which will grow to account for trailer data.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Replace chunksz_to_bytes() which took a chunk size with
chunk_usable_bytes() which takes a chunk_id directly. This eliminates
the redundant pattern of chunksz_to_bytes(h, chunk_size(h, c)) and makes
the API clearer by returning actual usable bytes (excluding the header).
Add mem_align_gap() helper to compute alignment padding between the
start of usable chunk memory and the actual memory pointer, using
efficient bit masking. This simplifies sys_heap_usable_size() and
inplace_realloc(). Use these helpers to make runtime stats reporting
reflect actual usable chunk memory (excluding chunk headers), and heap
listener notifications also account for alignment gaps.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Z_HEAP_MIN_SIZE and Z_HEAP_MIN_SIZE_FOR were defined in kernel.h as
hardcoded magic numbers gated by a growing tower of #ifdefs — one
per Kconfig option that happened to affect the heap struct layout.
Every internal change required manually recomputing the constants,
duplicating layout knowledge across files, and praying nobody forgot
to update the #ifdef matrix. This is fragile and unscalable: adding
a single new heap feature (e.g. a chunk canary trailer) would add yet
another dimension to the combinatorial explosion.
Replace this with build-time computation from the actual C structures.
A new lib/heap/heap_constants.c is compiled as part of the offsets
library and uses GEN_ABSOLUTE_SYM to emit the correct values into the
generated offsets.h. Z_HEAP_MIN_SIZE is derived through an iterative
fixed-point expansion (3 rounds, always convergent) that mirrors the
runtime logic in sys_heap_init(). Z_HEAP_MIN_SIZE_FOR overhead and
bucket sizes are also generated, keeping all internal heap layout
knowledge in one place.
Big vs small heap determination uses CONFIG_SYS_HEAP_SMALL_ONLY,
CONFIG_SYS_HEAP_BIG_ONLY, and sizeof(void *), mirroring the
big_heap_chunks() logic in heap.h.
kernel.h picks up the generated values via
__has_include(<zephyr/offsets.h>) so there is no circular dependency
with the offsets compilation itself. The old _Z_HEAP_SIZE manual
sizeof and BUILD_ASSERT scaffolding in heap.c are removed.
gen_offset_header.py is updated to accept multiple input object files
so that the heap constants object can coexist with the per-arch offsets
object in the same offsets library. COMMAND_EXPAND_LISTS is added to
the offsets generation custom command so that CMake correctly expands
the $<TARGET_OBJECTS:> generator expression into separate arguments
when the offsets library contains more than one object file.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Use the zvfs macros in the code of the module itself, instead of using
the versions from the POSIX API, and remove the header that defined those
as it is not needed anymore.
Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
Calling sys_heap_runtime_stats_get on a valid but uninitialized heap
results in a NULL pointer access. Add an additional check in this
function that the heap is valid and has also been initialized.
Signed-off-by: Graham Roff <grahamr@qti.qualcomm.com>
Add option to use default alignment when building a cbprintf package
on riscv (rv32e). It is useful in case when cbprintf packages are not
formatted on rv32e but on another core. There is such case on nrf54h20
where log messages are formatted by the ARM Cortex M33 core (cpuapp)
and without this option 64 bit arguments are incorrectly formatted.
Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>