Skip to content

Fix getrandom detection with musl libc - #843

Open
okning wants to merge 3 commits into
Mbed-TLS:developmentfrom
okning:fix/musl-getrandom
Open

Fix getrandom detection with musl libc#843
okning wants to merge 3 commits into
Mbed-TLS:developmentfrom
okning:fix/musl-getrandom

Conversation

@okning

@okning okning commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Description

On Linux, the platform entropy implementation only enables getrandom() for
glibc and Midipix. musl provides a getrandom() wrapper in <sys/random.h> but
does not define __GLIBC__, so affected builds fall back to /dev/random.
This can make a second PSA crypto initialization block after the first process
has consumed the available entropy on Linux 5.6 and earlier.

Prefer the libc wrapper when <sys/random.h> is available, while preserving
the existing raw-syscall path for older glibc/toolchain combinations and the
existing fallback when getrandom() is unavailable at runtime.

Validation:

  • CMake Debug build with AppleClang 21.0.0.
  • CTest: 132/132 tests passed.
  • ChangeLog assembly check passed.
  • Cross-compiled a static ARM EABI5 Debug binary with GCC 12.4.0 and musl.
  • Ran that binary twice consecutively under qemu-arm; both processes completed
    PSA crypto initialization and reached the connection attempt without
    blocking.

PR checklist

  • changelog provided
  • framework PR not required
  • TF-PSA-Crypto development PR provided by this PR
  • TF-PSA-Crypto 1.1 PR not provided; a backport can follow once the development fix is reviewed
  • mbedtls development PR not required because the implementation is maintained in TF-PSA-Crypto
  • mbedtls 4.1 PR not provided; the corresponding submodule update can follow the TF-PSA-Crypto backport
  • mbedtls 3.6 PR not provided; a backport can follow once the development fix is reviewed
  • tests not required because this changes compile-time libc selection; the affected musl path was validated with a cross-build and consecutive qemu-arm runs

Detect sys/random.h before selecting the Linux entropy path. This lets musl builds use their libc getrandom wrapper instead of falling back to blocking /dev/random.

Signed-off-by: Ning Xia <hi@nosec.me>
@gilles-peskine-arm
gilles-peskine-arm self-requested a review July 21, 2026 15:23
@gilles-peskine-arm gilles-peskine-arm added enhancement New feature or request needs-review Every commit must be reviewed by at least two team members needs-reviewer This PR needs someone to pick it up for review size-xs Estimated task size: extra small (a few hours at most) component-platform Portability layer and build scripts priority-medium Medium priority - this can be reviewed as time permits needs-backports Backports are missing or are pending review and approval. labels Jul 21, 2026
@gilles-peskine-arm gilles-peskine-arm moved this to Scoped in Community Jul 21, 2026
@okning
okning marked this pull request as ready for review July 22, 2026 11:58

@gilles-peskine-arm gilles-peskine-arm 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.

I'm all for improving the library on musl, but not if it breaks the build elsewhere.

The right thing to do would be to guard the non-portable code with #if __MUSL__ or some such. But since this does not and will not exist, I'm afraid we're stuck. We could add a way to declare “I swear I have getrandom()” at compile time. But that's even more complexity in code that's already more complex than I'd like. So I'd want to set up some testing if we do that, and that's complicated.

Comment thread platform/platform_util.c
* libcs such as musl which provide getrandom() but not __GLIBC__.
*/
#if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__))
#if defined(__linux__) && defined(__has_include)

@gilles-peskine-arm gilles-peskine-arm Jul 29, 2026

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.

This breaks the build with dietlibc.

  CC    source/platform/platform_util.c
In file included from source/platform/platform_util.c:305:
/usr/include/x86_64-linux-gnu/sys/random.h: In function ‘getrandom’:
/usr/include/x86_64-linux-gnu/sys/random.h:35:42: error: unknown type name ‘__wur’; did you mean ‘__wsum’?
   35 |                    unsigned int __flags) __wur
      |                                          ^~~~~
      |                                          __wsum
/usr/include/x86_64-linux-gnu/sys/random.h:36:35: error: expected declaration specifiers or ‘...’ before ‘(’ token
   36 |                    __attr_access ((__write_only__, 1, 2));
      |                                   ^
/usr/include/x86_64-linux-gnu/sys/random.h:40:50: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘__wur’
   40 | int getentropy (void *__buffer, size_t __length) __wur
      |                                                  ^~~~~
source/platform/platform_util.c:309:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or __attribute__’ before ‘{’ token
  309 | {
      | ^
source/platform/platform_util.c:387:1: error: parameter ‘mbedtls_platform_dev_random’ is initialized
  387 | const char *mbedtls_platform_dev_random = MBEDTLS_PLATFORM_DEV_RANDOM;
      | ^~~~~
source/platform/platform_util.c:392:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or __attribute__’ before ‘{’ token
  392 | {
      | ^
/usr/include/x86_64-linux-gnu/sys/random.h:34:9: error: old-style parameter declarations in prototyped function definition
   34 | ssize_t getrandom (void *__buffer, size_t __length,
      |         ^~~~~~~~~
source/platform/platform_util.c:447: error: expected ‘{’ at end of input
source/platform/platform_util.c:447: error: control reaches end of non-void function [-Werror=return-type]
cc1: all warnings being treated as errors
make: *** [Makefile:11984: platform/platform_util.o] Error 1

(on Ubuntu 24.04)

(I'm pretty sure that's why I didn't do that when I overhauled our random-on-Linux code recently.)

Comment thread ChangeLog.d/musl_getrandom.txt Outdated
@@ -0,0 +1,3 @@
Bugfix

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.

I wouldn't consider this a bug in TF-PSA-Crypto (but a bug in older Linux kernels). We're just not taking advantage of a nicer feature exposed by musl.

@gilles-peskine-arm gilles-peskine-arm added needs-work and removed needs-review Every commit must be reviewed by at least two team members needs-reviewer This PR needs someone to pick it up for review labels Jul 29, 2026
@okning

okning commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, you're right — checking only for the presence of <sys/random.h> is insufficient and causes a regression for dietlibc. I'll remove the automatic detection and reclassify the changelog entry as a feature.

Before updating the implementation, would you be open to an explicit opt-in configuration macro, for example MBEDTLS_PLATFORM_HAS_GETRANDOM? The default behavior would remain unchanged, and the libc wrapper would only be used when the integrator explicitly declares it available. I would add build coverage for both the enabled path and the unchanged fallback path, while retaining the musl/QEMU consecutive-initialization validation.

@gilles-peskine-arm

Copy link
Copy Markdown
Contributor

We prefer to keep the number of compile-time options down, but if that's the only way, we'll accept it.

But there's one thing I'm not sure I've tried: maybe the block that uses syscall(SYS_getrandom, ...) would work on the platforms where __has_include(<sys/syscall.h>) works? Would you mind checking how that goes with dietlibc and musl and anything else you have easy access to?

Ideally we'd like this to be covered in our CI, but that would require more work on our CI images than we have time for at the moment. So we'll settle for manual testing for now.

@okning

okning commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

That's a great idea—thanks for pointing it out. I replaced the
<sys/random.h>/libc-wrapper detection with a guarded raw-syscall path:

  • On Linux, use __has_include(<sys/syscall.h>) when available.
  • Only enable the syscall path when SYS_getrandom is defined.
  • Retain the existing glibc/Midipix condition for older toolchains.
  • Otherwise preserve the existing /dev/random fallback.

I also reclassified the changelog entry as a feature.

Validation performed:

  • glibc 2.43 / GCC 16.1: build passed; syscall path selected; two
    consecutive initializations passed.
  • musl / GCC 12.4: full build passed; syscall path selected; two
    consecutive initializations passed.
  • dietlibc 0.34: <sys/syscall.h> is present but SYS_getrandom is not
    defined; the build passed and the existing fallback remained selected.
    This avoids the <sys/random.h> regression.
  • uClibc-ng 1.0.54 / GCC 14.3: static build passed; syscall path selected;
    two consecutive initializations passed.
  • Android bionic / NDK r29 / API 21 / x86_64: dynamic and static builds
    passed; syscall path selected; the static binary passed two consecutive
    initializations.
  • AppleClang 21 Debug build passed, followed by 132/132 CTest tests.

Signed-off-by: Ning Xia <hi@nosec.me>
@okning
okning force-pushed the fix/musl-getrandom branch from 7828d13 to c615026 Compare August 3, 2026 13:41

@gilles-peskine-arm gilles-peskine-arm 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.

LGTM

Comment thread ChangeLog.d/musl_getrandom.txt Outdated
@@ -0,0 +1,5 @@
Features
* Use the `getrandom` system call for PSA crypto initialization on Linux

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.

Cosmetic: changelog entries are text, not markdown, so they shouldn't use backticks. Also, it's conventional to write getrandom() with parentheses.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've removed the Markdown backticks and changed it to the conventional getrandom() spelling.

@gilles-peskine-arm gilles-peskine-arm added needs-review Every commit must be reviewed by at least two team members needs-reviewer This PR needs someone to pick it up for review and removed needs-work labels Aug 3, 2026
@gilles-peskine-arm gilles-peskine-arm moved this from Scoped to Next 3 items in Community Aug 3, 2026
Signed-off-by: Ning Xia <hi@nosec.me>

@gilles-peskine-arm gilles-peskine-arm 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.

LGTM

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

Labels

component-platform Portability layer and build scripts enhancement New feature or request needs-backports Backports are missing or are pending review and approval. needs-review Every commit must be reviewed by at least two team members needs-reviewer This PR needs someone to pick it up for review priority-medium Medium priority - this can be reviewed as time permits size-xs Estimated task size: extra small (a few hours at most)

Projects

Status: Next 3 items
Status: In Development

Development

Successfully merging this pull request may close these issues.

2 participants