Skip to content

Aligned allocators - #11949

Open
aidankeefe2022 wants to merge 5 commits into
wolfSSL:masterfrom
aidankeefe2022:AlignedAllocators
Open

aidankeefe2022 wants to merge 5 commits into
wolfSSL:masterfrom
aidankeefe2022:AlignedAllocators

Conversation

@aidankeefe2022

@aidankeefe2022 aidankeefe2022 commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Description

This is a set of allocators that manually align the allocation to what ever alignment is passed in.
There is also a new XREALLOC_SCRUBBED that is introduced.

This PR also changes the configurations to always compile memory.c this adds 1.9 KB to the binary size in --disable-memory builds. Let me know if we want to find a fix for this

Align Allocators

The purpose of these allocators is to enforce proper alignment when it is not handled for us https://fenrir.wolfssl.com/finding/11986 is an example.

This comes with 4 new public APIs

WOLFSSL_API void *wc_MallocAlign(size_t alignment, size_t size, void *heap,
                                 int tag);
WOLFSSL_API void wc_FreeAlign(void *ptr, void *heap, int tag);
WOLFSSL_API void *wc_ReallocAlignScrubbed(void *ptr, size_t alignment,
                                          size_t size, void *heap, int tag);
WOLFSSL_API void *wc_ReallocAlign(void *ptr, size_t alignment, size_t size,
                                  void *heap, int tag);

Each has a matching macro like XMALLOC etc.

These can be overridden by users same as XMALLOC but they have to be done as a group no mixing and matching implementations.

The alignment metadata is keep track of via a hidden header allocated before the start of the requested memory.

/*
 *                     v what is returned
 * |padding|offset|size|  memory  |
 * |-----(offset)------|--(size)--|
 * */

This allows for the use of XMALLOC and XFREE as our allocation backend meaning we automatically inherit any configuration such as static memory.

Scrubbed Realloc

This is somewhat not related to the first change. The scrubbed realloc wipes any chunk lost during reallocation.
Downside is that there is never an inplace reallocation. This is also true for ReallocAlign.

This is also another new API and Macro

WOLFSSL_API void *wc_ReallocScrubbed(void *ptr, size_t old_size,
                                     size_t size, void *heap, int tag);

Testing

A new battery of test was added along with this change to make sure every corner is covered

  1. simple_memalign_test(alignment, sz), run from memory_test() once for each alignment 0, 2, 4, sizeof(void*), 16, 64 and 256:
    • XMALLOCALIGN returns memory with the requested alignment, for powers of 2 of at least 2.
    • Every byte of the block can be written and read back.
  2. memalign_macros_test(), for the WC_VAR_ALIGNED and WC_ARRAY_ALIGNED macros:
    • The single variable and each of the 3 array items are aligned to 64 (8 on IAR ARM stack builds). This is only checked on compilers where the alignment is actually guaranteed.
    • Writing every byte doesn't clobber neighbouring items.
    • WC_CALLOC_VAR_ALIGNED_EX returns zeroed memory.
  3. memalign_realloc_test(), for XREALLOCALIGN, XREALLOCALIGN_SCRUBBED and XREALLOC_SCRUBBED:
    • Realloc of NULL works like a fresh aligned allocation.
    • Growing (scrubbed), shrinking a lot, and growing far past allocator slack (unscrubbed) all keep the contents and the alignment.
    • A non-power-of-2 alignment is rejected and the original block is left intact. This session fixed the double free it hit when that rejection failed (MEDIUM-1).
    • Unaligned scrubbed grow and shrink keep the leading contents.
    • Realloc to size 0 frees the block and returns NULL, for all three macros.
  4. memalign_scrub_test(), which only runs with WOLFSSL_CHECK_MEM_ZERO and wolfSSL memory, without static memory:
    • Fills each block with a pattern and registers it with wc_MemZero_Add(). wolfSSL_Free() then aborts if a _SCRUBBED realloc didn't zero the old block before freeing it.
    • Covers aligned grow, aligned realloc to 0, unaligned grow and unaligned realloc to 0.
  5. memalign_shim_test() (added this session, MEDIUM-2):
    • Calls wc_MallocAlign, wc_ReallocAlign, wc_ReallocAlignScrubbed and wc_FreeAlign directly, so they're tested even when a port binds XMALLOCALIGN to something else.
    • Bad alignment (24) and a padded size that would overflow are both rejected.
    • The allocation is aligned and fully usable.
    • Growing keeps contents and alignment; a bad alignment on realloc leaves the original intact.
    • Scrubbed shrink keeps the leading contents; scrubbed realloc to 0 returns NULL.
    • Realloc of NULL with alignment 128, then an unscrubbed realloc to 0.
    • Freeing NULL is a no-op.

Checklist

  • added tests
  • updated/added doxygen
  • updated appropriate READMEs
  • Updated manual and documentation

@aidankeefe2022 aidankeefe2022 self-assigned this Oct 30, 2026
Copilot AI balanced review requested due to automatic review settings October 30, 2026 21:34
New set of tests and clean up

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Memory-callback-disabled builds omit required allocator implementations, causing undefined references, while the new 4096-byte allocation test incorrectly fails valid low-resource static-memory configurations.

2 open issues
What changed in this PR

This PR adds aligned allocation and scrubbed reallocation APIs to wolfSSL’s memory layer, using existing allocator backends to preserve heap and allocation-type handling.

Changes:

  • Adds aligned allocation APIs, override macros, and stack/heap declaration helpers.
  • Uses scrubbed reallocation for big-integer storage and plaintext private-key buffers.
  • Adds allocator tests and documents the new APIs and macros.
File Description
wolfssl/​wolfcrypt/​types.h Adds allocator macros and aligned stack/heap helpers.
wolfssl/​wolfcrypt/​memory.h Declares new APIs and exposes the zeroization test hook.
wolfcrypt/​test/​test.c Adds alignment, reallocation, and scrubbing tests; adopts aligned AES allocation.
wolfcrypt/​src/​memory.c Implements aligned allocation and scrubbed reallocation.
wolfcrypt/​src/​integer.c Scrubs old digit storage when growing big integers.
src/​pk.c Scrubs old private-key DER storage during buffer growth.
doc/​dox_comments/​header_files/​types.h Documents allocator macros and their contracts.
doc/​dox_comments/​header_files/​memory.h Documents the five new public memory APIs.

Review effort: Balanced

Comment thread wolfssl/wolfcrypt/types.h Resolved
Comment thread wolfcrypt/test/test.c Resolved

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #11949

Scan targets checked: wolfcrypt-src, wolfcrypt-bugs, wolfssl-src, wolfssl-bugs
Not reviewed (no scan target covers them): doc/dox_comments/header_files/memory.h, doc/dox_comments/header_files/types.h
Coverage: 6 of 6 in-scope changed file(s) opened by the reviewer

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

Review tier: Lite

@aidankeefe2022
aidankeefe2022 marked this pull request as ready for review October 30, 2026 23:02
@aidankeefe2022
aidankeefe2022 requested a balanced review from Copilot October 30, 2026 23:03
@github-actions

Copy link
Copy Markdown

retest this please

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report · Explore what changed →

gcc-arm-cortex-m0plus

  • FLASH: .text +312 B (+0.4%, 70,991 B / 262,144 B, total: 27% used)

gcc-arm-cortex-m3

  • FLASH: .text +288 B (+0.2%, 131,713 B / 262,144 B, total: 50% used)

gcc-arm-cortex-m4

  • FLASH: .text +256 B (+0.1%, 208,688 B / 262,144 B, total: 80% used)

gcc-arm-cortex-m4-baremetal

  • FLASH: .text +320 B (+0.4%, 73,655 B / 262,144 B, total: 28% used)

gcc-arm-cortex-m4-crypto-only

  • FLASH: .text +256 B (+0.1%, 181,843 B / 262,144 B, total: 69% used)

gcc-arm-cortex-m4-dtls13

  • FLASH: .text +256 B (+0.1%, 195,352 B / 1,048,576 B, total: 19% used)

gcc-arm-cortex-m4-min-ecc

  • FLASH: .text +256 B (+0.4%, 68,249 B / 262,144 B, total: 26% used)

gcc-arm-cortex-m4-openssl-compat

  • FLASH: .text +320 B (+0.0%, 797,372 B / 1,048,576 B, total: 76% used)

gcc-arm-cortex-m4-pkcs7

  • FLASH: .text +256 B (+0.1%, 222,932 B / 262,144 B, total: 85% used)

gcc-arm-cortex-m4-pq

  • FLASH: .text +256 B (+0.1%, 312,080 B / 1,048,576 B, total: 30% used)

gcc-arm-cortex-m4-rsa-only

  • FLASH: .text +256 B (+0.1%, 342,920 B / 1,048,576 B, total: 33% used)

gcc-arm-cortex-m4-sp-math

  • FLASH: .text +256 B (+0.4%, 68,249 B / 262,144 B, total: 26% used)

gcc-arm-cortex-m4-tls12

  • FLASH: .text +320 B (+0.2%, 132,497 B / 262,144 B, total: 51% used)

gcc-arm-cortex-m4-tls13

  • FLASH: .text +320 B (+0.1%, 249,058 B / 262,144 B, total: 95% used)

gcc-arm-cortex-m7

  • FLASH: .text +320 B (+0.2%, 208,752 B / 262,144 B, total: 80% used)

gcc-arm-cortex-m7-pq

  • FLASH: .text +320 B (+0.1%, 312,976 B / 1,048,576 B, total: 30% used)

gcc-arm-cortex-m7-tls13

  • FLASH: .text +256 B (+0.1%, 249,058 B / 262,144 B, total: 95% used)

stm32-sim-stm32h753

  • FLASH: .text +2,648 B (+1.3%, 207,236 B / 2,097,152 B, total: 10% used)

zephyr-frdm_rw612

  • FLASH: log_const_area -8 B, rodata +20 B, text +3,496 B (+1.2%, 285,972 B / 67,108,864 B, total: 0% used)

Catch memory regressions in CI with MemBrowse. Free for open source.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical defects can violate alignment, cause invalid frees or I/O-buffer data loss, and make public-macro calls with size expressions fail to compile.

3 open issues
2 resolved since last review

Review effort: Balanced

Comment thread linuxkm/linuxkm_wc_port.h
Comment on lines +2425 to +2436
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)
#ifndef XMALLOCALIGN
#define XMALLOCALIGN(a, s, h, t) ((void)(a), (void)(h), (void)(t), malloc(s))
#define XFREEALIGN(p, h, t) do { (void)(h); (void)(t); free(p); } while (0)
/* reallocation for aligned allocations */
#define XREALLOCALIGN(p, align, size, h, t) \
((void)(align), (void)(h), (void)(t), realloc(p, size))
/* reallocation with scrubbing of lost blocks for aligned allocations */
#define XREALLOCALIGN_SCRUBBED(p, align, old_size, size, h, t) \
((void)(align), wc_ReallocScrubbed(p, old_size, size, h, t))
#endif /* XMALLOCALIGN */
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) */
Comment thread wolfcrypt/src/memory.c
Comment on lines +1895 to +1897
XMEMCPY(new_p, ptr, (old_size < size) ? old_size : size);
wc_ReallocScrub(ptr, old_size);
XFREE(ptr, heap, tag);
Comment thread wolfssl/wolfcrypt/types.h
wc_ReallocAlign(p, align, size, h, t)
/* reallocation with scrubbing of lost blocks for aligned allocations */
#define XREALLOCALIGN_SCRUBBED(p, align, old_size, size, h, t) \
((void)old_size, wc_ReallocAlignScrubbed(p, align, size, h, t))

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #11949

Scan targets checked: linuxkm-src, linuxkm-bugs, wolfcrypt-src, wolfcrypt-bugs, wolfssl-src, wolfssl-bugs
Not reviewed (no scan target covers them): cmake/functions.cmake, doc/dox_comments/header_files/memory.h, doc/dox_comments/header_files/types.h, src/include.am
Coverage: 3 of 3 in-scope changed file(s) opened by the reviewer

Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Review tier: Lite

Comment thread linuxkm/linuxkm_wc_port.h
#endif /* !XMALLOC_USER && !XMALLOC_OVERRIDE */
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kernel 5.4 XMALLOCALIGN override drops alignment on kernels without natural kmalloc alignment · Kernel memory safety

On kernels before 5.4, XMALLOCALIGN/XREALLOCALIGN throw away a/align and call plain malloc/realloc (kmalloc/krealloc). Those kernels only guarantee ARCH_KMALLOC_MINALIGN, so callers that need 16/64-byte alignment (e.g. for AES-NI) get misaligned buffers. The gate looks inverted.

Suggested fix: Remove the pre-5.4 override so these kernels use the generic wc_MallocAlign family, which enforces the requested alignment.
Basis: Linux Documentation/core-api/memory-allocation.rst (since v5.4): kmalloc gives at least ARCH_KMALLOC_MINALIGN, plus natural alignment for power-of-two sizes; earlier kernels only promise ARCH_KMALLOC_MINALIGN.

Related known findings (similar but distinct; listed for context, not part of this finding)

Comment thread wolfcrypt/test/test.c

/* non-power-of-2 alignment: rejected, original intact. */
if (ret == 0) {
q = (byte*)XREALLOCALIGN(p, 24U, 1600U, HEAP_HINT,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memalign_realloc_test fails under the in-tree linuxkm (5.4) XREALLOCALIGN override, which ignores alignment · Logic errors

The test expects XREALLOCALIGN(p, 24U, ...) to fail. On kernels older than 5.4, the new linuxkm override maps it to realloc(p, size) and drops align, so the call succeeds and the linuxkm module self-test fails. The same override also leaves XMALLOCALIGN without any alignment guarantee there, and the alignment checks in simple_memalign_test depend on that guarantee.

Suggested fix: Make the linuxkm <5.4 override honor alignment (or drop it so wc_MallocAlign/wc_ReallocAlign are used), or guard these macro-level assertions to builds where the defaults are in effect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants