Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ ifdef NO_AUTODECODE
override DFLAGS += -version=NoAutodecodeStrings
endif

ifdef LINUX_LEGACY_EMULATE_GETRANDOM
override DFLAGS += -version=linux_legacy_emulate_getrandom
endif

UDFLAGS=-unittest -version=StdUnittest

LINKDL:=$(if $(findstring $(OS),linux),-L-ldl,)
Expand Down
66 changes: 56 additions & 10 deletions std/random.d
Original file line number Diff line number Diff line change
Expand Up @@ -1774,19 +1774,65 @@ else

version (linux)
{
// `getrandom()` was introduced in Linux 3.17.
version (linux_legacy_emulate_getrandom)
Copy link
Member

Choose a reason for hiding this comment

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

import gcc.config;
static if (Have_Getrandom)

Copy link
Member Author

Choose a reason for hiding this comment

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

@ibuclaw Is this something you’d like me to incorporate?
Or was it more like a note to yourself?

Copy link
Member

@ibuclaw ibuclaw Apr 12, 2025

Choose a reason for hiding this comment

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

It would have been nice if this was an enum, as that can survive in the installed sources after the library has been built, and there's already other tests whose results get written to this module at configure time.

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libphobos/libdruntime/gcc/config.d.in;h=e5fcd5073a96a2ffdee25c33348fc73bdddb6bbb;hb=HEAD

version (GNU)
{
    import gcc.config;
}
else version (linux_legacy_emulate_getrandom)
{
    enum Have_Getrandom = false;
}
else
{
    enum Have_Getrandom = true;
}

Have added this, though minor annoyance that it's its own thing rather than using the existing "features" module.

https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=libphobos/m4/druntime/os.m4;h=ef8ca434407149c176e5d93ab4012d53511048e3;hp=15cde3b04b8d47a66f83fa6ae56057359b66adac;hb=b905ce8caf04253e02e153d60d6ea8f99d300af6;hpb=882d3b319dbf50ae64080731a1398031c100b7c7

Copy link
Member

Choose a reason for hiding this comment

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

Fortunately, this is a function, and not a template. Otherwise this shim would be a non-starter.

Copy link
Member Author

Choose a reason for hiding this comment

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

Anything urgent here?
Otherwise I’d rather wait to see this getting hopefully replaced by something like #10748 in the near future anyway.

{
/+
Emulates `getrandom()` for backwards compatibility
with outdated kernels and legacy libc versions.

`getrandom()` was added to the GNU C Library in v2.25.
+/
pragma(msg, "`getrandom()` emulation for legacy Linux targets is enabled.");
Copy link
Member Author

Choose a reason for hiding this comment

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

This is obviously a bit spammy. Maybe we should comment it out?


/+
On modern kernels (5.6+), `/dev/random` would behave more similar
to `getrandom()`.
However, this emulator was specifically written for systems older
than that. Hence, `/dev/urandom` is the CSPRNG of choice.

<https://web.archive.org/web/20200914181930/https://www.2uo.de/myths-about-urandom/>
+/
private static immutable _pathLinuxSystemCSPRNG = "/dev/urandom";

import core.sys.posix.sys.types : ssize_t;

/+
Linux `getrandom()` emulation built upon `/dev/urandom`.
Parameter `flags` is happily ignored.
+/
private ssize_t getrandom(
void* buf,
size_t buflen,
uint flags,
) @system nothrow @nogc
{
import core.stdc.stdio : fclose, fopen, fread;

// Shim for missing bindings in druntime
version (none)
import core.sys.linux.sys.random : getrandom;
auto blockDev = fopen(_pathLinuxSystemCSPRNG.ptr, "r");
if (blockDev is null)
assert(false, "System CSPRNG unavailable: `fopen(\"" ~ _pathLinuxSystemCSPRNG ~ "\")` failed.");
scope (exit) fclose(blockDev);

const bytesRead = fread(buf, 1, buflen, blockDev);
return bytesRead;
}
}
else
{
import core.sys.posix.sys.types : ssize_t;
extern extern(C) ssize_t getrandom(
void* buf,
size_t buflen,
uint flags,
) @system nothrow @nogc;
// `getrandom()` was introduced in Linux 3.17.

// Shim for missing bindings in druntime
version (none)
import core.sys.linux.sys.random : getrandom;
else
{
import core.sys.posix.sys.types : ssize_t;
private extern extern(C) ssize_t getrandom(
void* buf,
size_t buflen,
uint flags,
) @system nothrow @nogc;
}
}
}

Expand Down
Loading