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>
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>